This (relatively short) article will explain to you the concepts of chrono, the “time library” of the latest C++ standard. It will also explain how timers in sge work.
chrono is defined in the latest standard, but until you decide to use C++0x instead of the good olde C++03, you need to use an alternative implementation (luckily, implementing chrono doesn’t require other C++0x features – it stands on its own).
There are two implementations of chrono: fcppt::chrono and boost::chrono. The latter, however, requires boost-1.47.0, so we’re going to use fcppt::chrono. Both are virtually identical, anyway, since they both implement the same standard.
We want to “manage time”. This means that we don’t care about the current day of month or how many days there are until christmas. Things are simpler and more abstract in chrono. We’ve got three “concepts” to learn:
- Time points
Let’s start with clocks. A clock is something that you can ask for the current time. But how do you define “current time” in abstract terms? Surely we won’t get back a string “07/30/2011 14:58:58”, since we want to do calculations with the return type.
So instead, you get a number which tells you how much “time units” have expired since the clock’s “epoch”. If you’ve heard about the Unix Timestamp, you’ll immediately feel at home. This particular timestamp measures the seconds (or sometimes milliseconds/microseconds, depending on the book you read) since 01/01/1970 0:00. That’s a number you can do calculations with! For example, taking two Unix Timestamps and subtracting them gives you the difference in seconds between two time points. Using that, we could define:
time_point now() const
This is, of course, very rudimentary. It would be better if
duration were classes with overloaded operators so we can write things like:
time_point current = clock.now();
duration difference = clock.now() - current;
And it would print out how much time has passed between the subtraction and the assignment (probably “0” for most clocks).
Compile time fractions, wtf?
Apart from the Unix Timestamp, there are other clocks imaginable. For example, a clock could define the “epoch” as the duration in seconds since the system start, measuring these seconds as float. Or we could have a clock having the epoch at 0 a.d., measuring in days. And so on.
All of these clocks have different native durations (seconds in integers, seconds in float, days in integers, …). We cannot, however, convert between these different durations yet, since we have no specification on how they relate to each other. They’re just numbers as of yet.
That’s why in chrono, a duration has another piece of information included in its type: A fraction “1/m” telling you how the duration relates to “1 second”. For example, a duration
tells you that the integer stored in it represents “milliseconds”. As you can see, these fractions are compile time properties, just as the duration of a clock is a compile time property.
Getting more concrete
Let’s look at the definition of a clock in
typedef implementation_defined rep;
// m and n are implementation defined
typedef ratio::object<m,n> period;
static bool const is_steady = false;
Let’s go through it one by one.
The first typedef,
rep, is the numeric value of the clock (that’s the type calculations are done with). This is usually something pretty large, like a 64 bit integer, so the clock doesn’t “wrap around” too quickly. But as with durations, this can be a floating point type, too!
The second typedef,
period, is the fraction I talked about in the previous section.
Then we have durations and time points. Time points just know about the clock type.
is_steady tells you if the clock guarantees “steadiness”. This means that for two time points t1 and t2, returned by the
now function, t1 <= t2 must hold. Additionally, the time between clock ticks must be constant.
The duration type looks like this:
typedef Rep rep;
typedef Period period;
/// Default constructs a duration with an undeterminate value
/// Constructs a duration from a compatible internal representation
* For example seconds(10) will result in a duration representing 10 seconds
Rep2 const &);
/// Constructs a duration from another compatible duration and converts if necessary.
template<typename Rep2,typename Period2>
duration<Rep2,Period2> const &);
/// Returns the internal representation
duration const &);
duration const &);
rep const &);
rep const &);
rep const &);
duration const &);
/// The duration with a zero value
/// The duration with the minimum value
/// The duration with the maximum value
As you can see, you can get the numeric value from the duration and do calculations with durations like subtracting them from another. These calculations, however, can only be performed with durations of the same type. Stuff like…
myseconds -= fcppt::chrono::milliseconds(10);
is not possible. However, there are binary variants of these operators so you can subtract/add/… two arbitrary durations:
result_duration_type result =
fcppt::chrono::seconds(1) - fcppt::chrono::milliseconds(10);
result_duration_type, you ask? Well, in general, that’s not so simple. The result will be a duration with at least the resolution
milliseconds, so no information is lost. If you want to convert the result to a coarser duration, you have to use
duration_cast. So, put simply, something sane will be produced and you cannot shoot yourself in the foot that easily.
Time point API
typedef Clock clock;
typedef Duration duration;
typedef typename duration::rep rep;
typedef typename duration::period period;
/// Constructs a time_point from a duration.
* This duration is interpreted as if it were obtained from time_since_epoch().
duration const &);
/// Constructs a time_point from a compatible time_point.
* This may convert if necessary.
time_point<clock, Duration2> const &);
/// Returns the duration from the beginning of the Clock to this time_point
duration const &);
duration const &);
/// The minimal time_point
/// The maximal time_point
As you can see, a time point is just a wrapper around a duration, really. But I wanted to show you its api, anyway. As with durations, there are binary operators for subtracting time points or adding a duration to a time point which result in a duration (in the clock’s duration type) and a new time point, respectively.
Example: Limiting your game’s frame rate
To show the expressivity of chrono, I’m going to show you how to limit your game’s frame rate so that it doesn’t exceed a certain number of frames per second (yes, we should be using vertical sync and a blocking swap to do that. Let’s pretend those mechanisms don’t work).
We have to decide on a clock to use. chrono provides a few predefined clocks, among them
high_resolution_clock. This clock might not be steady (see above), but since we’re dealing with small time deltas here, a high-resolution clock seems like a wise choice (its internal duration ratio is nanoseconds).
Let me show you the code and figure out for yourselves how it works (this is an exercise, not laziness on my side ;))
typedef fcppt::chrono::high_resolution_clock clock_type;
typedef clock_type::rep fps_type;
fps_type desired_frames_per_second =
// Divide by a rep, get a new duration
fcppt::chrono::seconds(1)) / desired_frames_per_second);
clock_type::time_point const before_frame =
// Subtract two time points, get a clock duration!
clock_type::duration const diff =
clock_type::now() - before_frame;
// If the frame was over too quickly, compensate
if(diff < minimum_frame_length)
// Subtract two durations
minimum_frame_length - diff));
In your application (your game, for example), you may want to time things. Say you have a bonus system in your game and you want to let the bonus expire after 10 seconds while the player sees the seconds running down. You can do that with chrono, the structures are there…but it’s not very comfortable. You’d have to store a time point
bonus_started yourself, along with a duration
bonus_duration and watch if the timer has expired.
In sge, you can define a
sge::timer::basic<Clock> which gets a clock as template parameter. Again, in your application, you have to decide which type of clock you want to use. A timer has the following properties:
- An interval determining how long it lasts. Internally, this is stored in the clock’s duration type. The interface, however, doesn’t care about the specific type of the duration. You can pass in and retrieve it as any duration type and it will be implicitly converted.
- A starting time point, pretty self-explanatory. The only way this member can be modified is to call
reset() on the timer.
- An activation state which is simply a bool.
- An expiration flag which determines if the timer has expired. This can be set explicitly, but is otherwise determined by looking at the interval, the starting time point and the activation state.
Timers can be active or inactive, and they can be expired or not expired. This might be a bit confusing, so let me clarify: A timer is expired, if…
- you’ve explicitly set it to be expired (via
- it’s inactive
- the specified interval has elapsed since the last call to
reset() or since the timer’s construction
A timer is active if you’ve set it to be active. It’s inactive if you say
timer.active(false);. Note that the active flag will not be set to true when you call
reset(). The expired flag, however, will be set to false.
The timer interface looks like this
parameters const &);
bool expired() const;
bool active() const;
NewDuration const interval() const;
void interval(NewDuration const &);
time_point const now() const;
time_point const last_time() const;
Since we don’t want to specify all of the 4 properties of a timer when initializing it, there is a parameters class which you give to the constructor. Again, I think the timer is best explained with a simple example: Let’s stall the user for, say, 10 seconds and output a nice progress bar while they are waiting:
// Unnecessary, just here for exposition
// Let's reserve 60 characters for the progress bar.
unsigned const progress_bar_width = 60;
// Retrieve the elapsed time as a floating point value in [0,1]
double const fraction =
unsigned const elapsed_time =
static_cast<unsigned>(fraction * progress_bar_width);
// \r to rewind to the start of the line
std::cout << '\r' << '|';
// Draw the elapsed_time. We could also use one of std::string's constructors
// for this.
for(unsigned i = 0; i < elapsed_time; ++i)
std::cout << '-';
// Draw the remaining time
for(unsigned i = 0; i < (progress_bar_width - elapsed_time); ++i)
std::cout << ' ';
std::cout << '|';
There’s one more thing sge::timer provides, and that’s additional clocks. chrono defines three clocks:
high_resolution_clock we already saw
steady_clock which is guaranteed to be steady
system_clock which provides functions to interact with C’s time api (convert to and from
All of these clocks are stateless. They are classes, but they contain no data member. That’s why they have a static member function
now(). Now, unfortunately, they can be instantiated:
fcppt::chrono::high_resolution_clock::time_point my_now = my_highres_clock.now();
but this is just a bad design decision in the Standard.
Despite that, stateful clocks can be useful, too. For example, sge provides
sge::timer::clocks::adjustable<Clock>, which takes a stateless clock and modifies its behavior.
adjustable has a data member
factor, which determines how fast time moves forward. If this factor is 1.0, time moves at normal speed (relative to
Clock). Now, in a game, you could define
and give it this
game_clock to all your entities (the player, the bullets etc.). Then to enter pause mode, all you have to do is call
and the game stops, since all the timers use this clock. Similarly, if you just want to slow time down (yay, Bullet Time!), you could set the time factor to 0.5.
Remember, though, that you have to pass stateful clocks to the timers explicitly. E.g.:
Also, you have to call
game_clock.update() to make time progress.
That’s all I have to say for now about chrono, durations, clocks, and timers. I hope you see how well the standard guys thought about the time API, and why defining it with templates is a necessary evil in this situation. If you haven’t done much C++ yet, consider chrono one of the “good” C++ APIs.