[filesystem] Epoch of trivial_clock
The filesystem::trivial_clock type is implementation-defined [1]. That means that the epoch is also implementation-defined. How do we determine the epoch of trivial_clock? For instance, we may need to represent the last_write_time() timestamp to the end-user, or transfer it to another node when we implement a network file system. PS: I am looking at the std::filesystem proposal, but I assume that boost::filesystem will be update accordingly. [1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4097.html#8
On 22 Aug 2014 at 13:10, Bjorn Reese wrote:
The filesystem::trivial_clock type is implementation-defined [1]. That means that the epoch is also implementation-defined.
Something which Bjorn discovered is that - believe it or not - POSIX leaves the epoch of time_t as implementation defined. That means that when you fetch a time_t from system_clock, it may, or may not, be using the epoch of other time_t's on the same system. I would assume in practice that when porting a STL to a platform the porter would make sure they align, but from a serialisation POV a never standardised epoch is a problem when moving data between systems. In other words, it is harder than it should be to write a timestamp to a file with an absolute guarantee it means the same thing to every reader. Replies to Bjorn's question above may wish to bear this disjunct in mind when answering. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
On 22/08/2014 08:10 a.m., Bjorn Reese wrote:
The filesystem::trivial_clock type is implementation-defined [1]. That means that the epoch is also implementation-defined.
How do we determine the epoch of trivial_clock?
Given a clock `C`, a default constructed `C::time_point` (or any instantiation of `time_point` for the clock `C`) represents the epoch of the clock. That is, for such a `time_point`, `time_since_epoch()` will return a duration of 0. That is somewhat obvious, the epoch is the origin, and unlikely to help your use case.
For instance, we may need to represent the last_write_time() timestamp to the end-user, or transfer it to another node when we implement a network file system.
It seems to me that what you need instead is to map a `time_point` from one clock to another, one that has an epoch under your control. That time_point could be the epoch of a clock. That is roughly done with: tp2 = C2::now() + (tp1 - C1::now()) Regards, -- Agustín K-ballo Bergé.- http://talesofcpp.fusionfenix.com
On August 22, 2014 2:11:41 PM EDT, "Agustín K-ballo Bergé"
On 22/08/2014 08:10 a.m., Bjorn Reese wrote:
The filesystem::trivial_clock type is implementation-defined [1]. That means that the epoch is also implementation-defined.
How do we determine the epoch of trivial_clock?
Given a clock `C`, a default constructed `C::time_point` (or any instantiation of `time_point` for the clock `C`) represents the epoch of the clock. That is, for such a `time_point`, `time_since_epoch()` will return a duration of 0.
That is somewhat obvious, the epoch is the origin, and unlikely to help your use case.
It seems to me that what you need instead is to map a `time_point` from one clock to another, one that has an epoch under your control. That time_point could be the epoch of a clock. That is roughly done with:
tp2 = C2::now() + (tp1 - C1::now())
That would be unstable as there's a race between the two calls to now(). It would also be unduly costly. Instead, just account for the origin differences: tp2 = tp1 + C2:: time_point() - C1:: time_point(); ___ Rob (Sent from my portable computation engine)
On 08/23/2014 02:58 PM, Rob Stewart wrote:
That would be unstable as there's a race between the two calls to now(). It would also be unduly costly. Instead, just account for the origin differences:
tp2 = tp1 + C2:: time_point() - C1:: time_point();
AFAIK you cannot do arithmetic operations between time_point from different clocks.
On 23/08/2014 10:54 a.m., Bjorn Reese wrote:
On 08/23/2014 02:58 PM, Rob Stewart wrote:
That would be unstable as there's a race between the two calls to now(). It would also be unduly costly. Instead, just account for the origin differences:
tp2 = tp1 + C2:: time_point() - C1:: time_point();
AFAIK you cannot do arithmetic operations between time_point from different clocks.
That's correct. We can still make that snippet work by moving things around: tp2 = (tp1 - C1::tp()) + C2::tp() // ok, duration + time_point tp2 = tp1.time_since_epoch() + C2::tp() // same thing C2::tp tp2{tp1.time_since_epoch()}; // assuming compatible durations Which gives you a time point which is as far from the epoch of C2 as the original time point was from C1. Which as far as I know, it's meaningless. Regards, -- Agustín K-ballo Bergé.- http://talesofcpp.fusionfenix.com
On 08/22/2014 08:11 PM, Agustín K-ballo Bergé wrote:
On 22/08/2014 08:10 a.m., Bjorn Reese wrote:
How do we determine the epoch of trivial_clock?
Given a clock `C`, a default constructed `C::time_point` (or any instantiation of `time_point` for the clock `C`) represents the epoch of the clock. That is, for such a `time_point`, `time_since_epoch()` will return a duration of 0.
That is true by definition. My question was how do I determine the epoch of the clock in Gregorian time. My best attempt so far is to resort to <ctime>, because struct std::tm is relative to 1900-01-01. I can covert this into a std::time_t using std::mktime(), and then pass it to C::from_time_t(). However, there are two problems with this solution: 1. from_time_t() and to_time_t() are only required by system_clock, not by TrivialClock (as used by std/boost::filesystem.) 2. std::mktime() returns local time, but I need UTC. So I must invoke the thread-unsafe std::localtime() and std::gmtime() functions to compensate for timezones (and yes, I am aware of the _r counterparts but I am looking for a portable solution based on the C++ standard.)
It seems to me that what you need instead is to map a `time_point` from one clock to another, one that has an epoch under your control. That time_point could be the epoch of a clock. That is roughly done with:
tp2 = C2::now() + (tp1 - C1::now())
I can see two problems with this solution: 1. How do I create a clock with an epoch under my control? POSIX no longer gives guarantees about its epoch. 2. The two now() calls are not guaranteed to happen simultaneously, so it will introduce jitter. This jitter will become more salient as the clock resolution becomes more fine-grained. Notice that POSIX has APIs with nanosecond resolution on file timestamps: http://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html
On Fri, Aug 22, 2014 at 7:10 AM, Bjorn Reese
The filesystem::trivial_clock type is implementation-defined [1]. That means that the epoch is also implementation-defined.
How do we determine the epoch of trivial_clock?
For instance, we may need to represent the last_write_time() timestamp to the end-user, or transfer it to another node when we implement a network file system.
PS: I am looking at the std::filesystem proposal, but I assume that boost::filesystem will be update accordingly.
Yes. I'm working on that right now, and hope to have a beta ready within a month, and ship a final version in 1.57.0. I'm not sure of the answers to your questions until the actual implementation is done. Thanks, --Beman
participants (5)
-
Agustín K-ballo Bergé
-
Beman Dawes
-
Bjorn Reese
-
Niall Douglas
-
Rob Stewart