blob: de165529a2e74579a42a2c56c1a809526132ba83 [file] [log] [blame]
// boost/chrono/stopwatches/laps_stopwatch.hpp -----------------------------//
// Copyright 2011 Vicente J. Botet Escriba
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/libs/chrono/stopwatches for documentation.
#ifndef BOOST_CHRONO_STOPWATCHES_LAPS_STOPWATCH_HPP
#define BOOST_CHRONO_STOPWATCHES_LAPS_STOPWATCH_HPP
#include <boost/chrono/config.hpp>
#include <boost/chrono/stopwatches/stopwatch_scoped.hpp>
#include <boost/chrono/stopwatches/collectors/no_memory.hpp> // default laps_collector
#include <boost/chrono/stopwatches/dont_start.hpp>
#include <boost/chrono/system_clocks.hpp> // default_clock
#include <boost/system/error_code.hpp>
#include <utility>
namespace boost
{
namespace chrono
{
/**
* A laps_stopwatch is a model of @c Stopwatch taking as parameters the @c Clock and the @c LapsCollector.
*
* The main difference respect to a @c simple_stopwatch is that the user can stop it.
* Each sequence of start-stop results in a new elapsed duration sample that is provided to the LapsCollector.
*
* It is up to the LapsCollector to make whatever wants with each sample.
* A LapCollector must define a store(duration const&) and a clear() functions.
*
* The library provides LapsCollectors that forget the sample, store the
* last one, cummulates the samples in an accumulator set or store them in a container.
* For simplicity the default LapCollector is the one that forget the samples.
*
* Even if it is preferable to use process or thread wide clocks,
* the default of the Clock parameter is high_resolution_clock,
* as it is the single one ensured on all platforms.
*/
template<typename Clock=high_resolution_clock, typename LapsCollector=no_memory<typename Clock::duration> >
class laps_stopwatch
{
public:
typedef LapsCollector laps_collector;
typedef Clock clock;
typedef typename Clock::duration duration;
typedef typename Clock::time_point time_point;
typedef typename Clock::rep rep;
typedef typename Clock::period period;
BOOST_STATIC_CONSTEXPR bool is_steady = Clock::is_steady;
/**
* Default constructor.
*
* Effects: Starts the stopwatch.
* Post-conditions: is_running().
*/
explicit laps_stopwatch()
:
start_(duration::zero()),
running_(false),
laps_collector_()
{
start();
}
#if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
/**
* Default constructor.
*
* Effects: Assign the error code if any internal error occur while retrieving the current time.
* Effects: Starts the stopwatch.
* Post-conditions: is_running() if no error occur.
*/
explicit laps_stopwatch(
system::error_code & ec
) :
start_(duration::zero()),
running_(false),
laps_collector_()
{
start(ec);
}
#endif
/**
* Not starting constructor.
*
* Effects: Don't starts the stopwatch.
* Post-conditions: ! is_running() if no error occur.
*/
explicit laps_stopwatch(
const dont_start_t&
) :
start_(duration::zero()),
running_(false),
laps_collector_()
{
}
/**
* Starting constructor from a LapsCollector instance.
*
* Effects: Copies the LapsCollector. Starts the stopwatch.
* Post-conditions: is_running() if no error occur.
*
* Remark: The LapsCollector is copied and owned by the stopwatch.
*/
explicit laps_stopwatch(
laps_collector const& acc
) :
start_(duration::zero()),
running_(false),
laps_collector_(acc)
{
start();
}
#if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
/**
* Starting constructor from a LapsCollector instance.
*
* Effects: Assign the error code if any internal error occur while retrieving the current time.
* Effects: Copies the LapsCollector. Starts the stopwatch.
* Post-conditions: is_running() if no error occur.
*
* Remark: The LapsCollector is copied and owned by the stopwatch.
*/
explicit laps_stopwatch(
laps_collector const& acc,
system::error_code & ec
) :
start_(duration::zero()),
running_(false),
laps_collector_(acc)
{
start(ec);
}
#endif
/**
* Not starting constructor from a LapsCollector instance.
*
* Effects: Copies the LapsCollector. Don't starts the stopwatch.
* Post-conditions: ! is_running() if no error occur.
*
* Remark: The LapsCollector is copied and owned by the stopwatch.
*/
laps_stopwatch(
laps_collector const& acc,
const dont_start_t&
) :
start_(duration::zero()),
running_(false),
laps_collector_(acc)
{
}
/**
* Destructor.
*
* Effects: Do nothing.
*/
~laps_stopwatch()
{
}
/**
* Restart the stopwatch.
*
* Effects: Assign the error code if any internal error occur while retrieving the current time.
* Effects: As if stop(); start() were called, but ensuring that the start time is the same as the stop time.
*
* Post-conditions: is_running() if no error occur.
*/
void restart()
{
time_point tmp = clock::now();
if (is_running())
{
laps_collector_.store(tmp - start_);
}
else
{
running_ = true;
}
start_ = tmp;
}
#if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
/**
* Restart the stopwatch.
*
* Effects: Assign the error code if any internal error occur while retrieving the current time.
* Effects: As if stop(); start() were called, but ensuring that the start time is the same as the stop time.
*
* Post-conditions: is_running() if no error occur.
*/
void restart(
system::error_code & ec
)
{
time_point tmp = clock::now(ec);
if (!BOOST_CHRONO_IS_THROWS(ec) && ec) return;
if (is_running())
{
laps_collector_.store(tmp - start_);
}
else
{
running_ = true;
}
start_ = tmp;
}
#endif
/**
* Start the stopwatch.
*
* Effects: Memorize the current time.
*
* Post-conditions: is_running().
*/
void start()
{
start_ = clock::now();
running_ = true;
}
#if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
/**
* Start the stopwatch.
*
* Effects: Assign the error code if any internal error occur while retrieving the current time.
* Effects: Memorize the current time.
*
* Post-conditions: is_running() if no error occur.
*/
void start(
system::error_code & ec
)
{
time_point tmp = clock::now(ec);
if (!BOOST_CHRONO_IS_THROWS(ec) && ec) return;
start_ = tmp;
running_ = true;
}
#endif
/**
* Start the stopwatch.
*
* Effects: Gives the elapsed time since start time to the LapCollector.
*
* Throws: Any exception that the LapCollector can throw when .
*
* Post-conditions: !is_running() if no error occur.
*/
void stop()
{
if (is_running())
{
laps_collector_.store(clock::now() - start_);
start_ = time_point(duration::zero());
running_ = false;
}
}
#if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
/**
* Start the stopwatch.
*
* Effects: Assign the error code if any internal error occur while retrieving the current time.
* Effects: Gives the elapsed time since start time to the LapCollector if no internal error occurs.
*
* Throws: Any exception that the LapCollector can Throw.
*
* Post-conditions: !is_running() if no error occur.
*/
void stop(
system::error_code & ec
)
{
if (is_running())
{
time_point tmp = clock::now(ec);
if (!BOOST_CHRONO_IS_THROWS(ec) && ec) return;
laps_collector_.store(tmp - start_);
start_ = time_point(duration::zero());
running_ = false;
}
}
#endif
/**
* States if the Stopwatch is running.
*/
bool is_running() const {
return running_;
}
/**
* Elapsed time getter for the current lap.
*
* Returns: the elapsed time since the last start if no internal error occur.
*
*/
duration elapsed_current_lap() const
{
if (is_running())
{
return clock::now() - start_;
}
else
{
return duration::zero();
}
}
#if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
/**
* Elapsed time getter for the current lap.
*
* Effects: Assign the error code if any internal error occur while retrieving the current time.
*
* Returns: the elapsed time since the start if no internal error occur.
*
*/
duration elapsed_current_lap(
system::error_code & ec
) const
{
if (is_running())
{
time_point tmp = clock::now(ec);
if (!BOOST_CHRONO_IS_THROWS(ec) && ec) return duration::zero();
return tmp - start_;
} else
{
return duration::zero();
}
}
#endif
/**
* Elapsed time getter.
*
* Effects: Assign the error code if any internal error occur while retrieving the current time.
*
* Returns: the elapsed time since the start if no internal error occur.
*
*/
duration elapsed() const
{
return laps_collector_.elapsed()+elapsed_current_lap();
}
#if !defined BOOST_CHRONO_DONT_PROVIDE_HYBRID_ERROR_HANDLING
/**
* Elapsed time getter.
*
* Effects: Assign the error code if any internal error occur while retrieving the current time.
*
* Returns: the elapsed time since the start if no internal error occur.
*
*/
duration elapsed(
system::error_code & ec
) const
{
duration tmp = elapsed_current_lap(ec);
if (!BOOST_CHRONO_IS_THROWS(ec) && ec) return duration::zero();
return laps_collector_.elapsed() + tmp;
}
#endif
/**
* Elapsed time for the last lap.
*
* Returns: the elapsed time of the last lap.
*
*/
duration last() const
{
return laps_collector_.last();
}
/**
* Resets the stopwatch.
*
* Effects: Resets the LapCollector.
*
* Post-conditions: !is_running() if no error occur.
*
*/
void reset()
{
laps_collector_.reset();
running_ = false;
start_ = time_point(duration::zero());
}
/**
* LapsCollector getter.
*
* Returns: the LapCollector instance.
*
*/
laps_collector const& get_laps_collector() BOOST_NOEXCEPT
{
return laps_collector_;
}
/**
* Useful typedef for scoped run
*/
typedef stopwatch_runner<laps_stopwatch<Clock, LapsCollector> >
scoped_run;
/**
* Useful typedef for scoped stop
*/
typedef stopwatch_stopper<laps_stopwatch<Clock, LapsCollector> >
scoped_stop;
private:
time_point start_;
bool running_;
laps_collector laps_collector_;
};
} // namespace chrono
} // namespace boost
#endif // header