|
Boost : |
Subject: Re: [boost] [timer] Boost Timer Library Version 2
From: Beman Dawes (bdawes_at_[hidden])
Date: 2011-09-28 14:33:11
On Wed, Sep 28, 2011 at 8:38 AM, Stewart, Robert <Robert.Stewart_at_[hidden]> wrote:
> Vicente J. Botet Escriba wrote:
>>
>> * Why does stop returns cpu-times? Why by reference? Why
>> elapsed is not returned by reference?
>>
>> cpu_times elapsed() const noexcept;
>>
>> const cpu_times& stop() noexcept;
>
> The interface is, of course, directed by the current
> implementation. Still, it would be appropriate for stop() to
> return by value to avoid forcing the implementation to store a
> cpu_times instance in the timer.
There is only one set of times in the timer. How could an
implementation not store the start times within the timer?
>> * I would associate the operations pairwise start/stop and
>> suspend/resume. I guess it would be easier to explain the
>> semantics.
>
> Yes. Of course. I knew I didn't quite like the current
> semantics, but it just didn't click. Another advantage of
> start/stop and suspend/resume is that RAII classes can be used to
> control the timer.
>
> Here's the new interface:
>
> void start();
> void stop();
> bool is_stopped();
> void suspend();
> void resume();
> bool is_suspended();
> cpu_times elapsed();
I'm totally confused by having four states: stopped/suspended,
stopped/not-suspended, not-stopped/suspended,
not-stopped/not-suspended.
What do the stopped/not-suppended and not-stopped/suspended states represent?
> start() notes the current time as the start time and marks the
> timer as not stopped, if is_stopped(), and marks the timer as not
> suspended.
I can't parse that. What does ", if is_stopped()," apply to? Or does
start() unconditionally mark the timer as not stopped and not
suspended?
> stop() notes the current time as the end time and marks the timer
> as stopped, if !is_stopped(), and marks the timer as not
> suspended.
Same problem with ", if is_stopped()," - what does the if apply to?
>
> suspend() notes the current time as the suspension time and marks
> the object as being suspended, if !is_stopped() &&
> !is_suspended().
Do you mean?
Effects: If !is_stopped() && !is_suspended(), save the current time
as the suspension
time and mark the object as being suspended? Otherwise, no effects.
> resume() calls start() and arranges for a future call to
> elapsed() to include the time elapsed until suspend() was called
> plus the time that elapses subsequently, if is_suspended().
>
> Reasonable? I know that means that both start and end times must
> be stored with this interface (two cpu_times instances, for
> example), but that seems a worthwhile price.
For what? Are you looking for two timers that start at the same time:
cpu_timer t1;
cpu_timer t2(t1);
> Here's a use case addressed by these ideas:
>
> nanosecond_type status_time(0);
> cpu_timer timer;
> for (int i(0); i < 100; ++i)
> {
> task_to_time();
> scoped_suspender _(timer);
> nanosecond_type const current_time(timer.elapsed().user);
> if (1000000000 < current_time - status_time)
> {
> report(timer);
> status_time = current_time;
> }
> }
>
> scoped_suspender is an RAII class that calls suspend() and
> resume(). Thus, the overhead of checking the elapsed time and
> writing output is not included in the time tracked by the timer.
> This approach permits doing non-timed work of various sorts in
> the midst of timed work.
How is your example different from this?
nanosecond_type status_time(0);
cpu_timer timer;
for (int i(0); i < 100; ++i)
{
task_to_time();
scoped_stop_and_resume(timer); // stop() in ctor, resume() in dtor
nanosecond_type const current_time(timer.elapsed().user);
if (1000000000 < current_time - status_time)
{
report(timer);
status_time = current_time;
}
timer.resume();
}
>
> scoped_suspender might be a class template with a generator:
>
> auto _(make_scoped_suspender(timer));
>
> That would allow supporting any timer type that provides
> suspend() and resume().
How is that different from stop() and resume() with current interface?
>
> I suspect that this use case would be pretty common, so it could
> be captured:
>
> timer_reporter report(1000000000); // once per second
> cpu_timer timer;
> for (int i(0); i < 100; ++i)
> {
> task_to_time();
> report(timer);
> }
>
> void
> timer_reporter::operator ()(cpu_timer & _timer)
> {
> if (_timer.is_stopped())
> {
> return;
> }
> scoped_suspender _(_timer);
> nanosecond_type const current(_timer.elapsed().user);
> if (delay_ < current - last_)
> {
> std::string const formatted(
> _timer.format(precision_, format_));
> os_ << formatted;
> last_ = current;
> }
> }
>
> Obviously, I'm suggesting that timer_reporter is somewhat similar
> to auto_cpu_timer in that it would save a std::ostream & for
> output, as well as the precision and a format string for calling
> cpu_timer::format().
Understood.
>
> I purposely did not supply the timer as a constructor argument
> because that would require construction after a timer already
> started or else stopping the timer, constructing the
> timer_reporter, and then starting the timer.
Interesting,
--Beman
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk