// // tick_count_timer.cpp // ~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // 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) // #include #include #include #include #include #if defined(WIN32) # include #else # error This example is for Windows only! #endif #ifdef max // the Windows max macro conflicts with the limits library #undef max #endif struct tick_count_traits { // The time type. This type has no constructor that takes a DWORD to ensure // that the timer can only be used with relative times. class time_type { public: time_type() : ticks_(0) {} DWORD get_ticks() const {return ticks_;} private: friend struct tick_count_traits; DWORD ticks_; }; // The duration type. class duration_type { public: duration_type() : ticks_(0) {} duration_type(long ticks) : ticks_(ticks) {} long get_ticks() const {return ticks_;} private: friend struct tick_count_traits; long ticks_; }; // Get the current time. static time_type now() { time_type result; result.ticks_ = ::GetTickCount(); return result; } // Add a duration to a time. static time_type add(const time_type& t, const duration_type& d) { time_type result; result.ticks_ = t.ticks_ + d.ticks_; return result; } // Subtract one time from another. static duration_type subtract(const time_type& t1, const time_type& t2) { // DWORD tick count values wrap periodically, so we'll use a heuristic that // says that if subtracting t1 from t2 yields a value smaller than 2^31, // then t1 is probably less than t2. This means that we can't handle // durations larger than 2^31, which shouldn't be a problem in practice. static DWORD const diff_limit(static_cast(1 << 31)); long duration(0); if (t1.ticks_ < t2.ticks_) { DWORD diff = t2.ticks_ - t1.ticks_; if (diff >= diff_limit) { duration = static_cast( std::numeric_limits::max() - t2.ticks_ + t1.ticks_ + 1); } else { duration = - static_cast(diff); } } else { DWORD diff = t1.ticks_ - t2.ticks_; if (diff >= diff_limit) { duration = - static_cast( std::numeric_limits::max() - t1.ticks_ + t2.ticks_ + 1); } else { duration = static_cast(diff); } } return duration_type(duration); } // Test whether one time is less than another. static bool less_than(const time_type& t1, const time_type& t2) { bool is_less = subtract(t2, t1).ticks_ > 0; return is_less; } // Convert to POSIX duration type. static boost::posix_time::time_duration to_posix_duration( const duration_type& d) { return boost::posix_time::milliseconds(d.ticks_); } }; typedef boost::asio::basic_deadline_timer< DWORD, tick_count_traits> tick_count_timer; void handle_timeout(const boost::system::error_code&) { std::cout << "handle_timeout\n"; } int main() { typedef tick_count_traits::time_type time_type; typedef tick_count_traits::duration_type duration_type; static long const TestDuration = 715827883; // tick_count_traits test // time_type t0 = time_type(); time_type t1 = tick_count_traits::add(t0, duration_type(TestDuration)); time_type t2 = tick_count_traits::add(t1, duration_type(TestDuration)); time_type t3 = tick_count_traits::add(t2, duration_type(TestDuration)); time_type t4 = tick_count_traits::add(t3, duration_type(TestDuration)); time_type t5 = tick_count_traits::add(t4, duration_type(TestDuration)); time_type t6 = tick_count_traits::add(t5, duration_type(TestDuration)); duration_type d1 = tick_count_traits::subtract(t1, t2); duration_type r1 = tick_count_traits::subtract(t2, t1); duration_type d2 = tick_count_traits::subtract(t2, t4); duration_type r2 = tick_count_traits::subtract(t4, t2); duration_type d3 = tick_count_traits::subtract(t4, t5); duration_type r3 = tick_count_traits::subtract(t5, t4); duration_type d4 = tick_count_traits::subtract(t5, t6); duration_type r4 = tick_count_traits::subtract(t6, t5); duration_type d5 = tick_count_traits::subtract(t5, t1); duration_type r5 = tick_count_traits::subtract(t1, t5); assert(t0.get_ticks() == 0); assert(t1.get_ticks() == 715827883); assert(t2.get_ticks() == 1431655766); assert(t3.get_ticks() == 2147483649); assert(t4.get_ticks() == 2863311532); assert(t5.get_ticks() == 3579139415); assert(t6.get_ticks() == 2); assert(d1.get_ticks() == -715827883); assert(r1.get_ticks() == 715827883); assert(d2.get_ticks() == -1431655766); assert(r2.get_ticks() == 1431655766); assert(d3.get_ticks() == -715827883); assert(r3.get_ticks() == 715827883); assert(d4.get_ticks() == -715827883); assert(r4.get_ticks() == 715827883); assert(d5.get_ticks() == -1431655764); // note due to overrun at t6 this is: assert(r5.get_ticks() == 1431655764); // TestDuration * 2 - 2 assert(tick_count_traits::less_than(t0, t0) == false); assert(tick_count_traits::less_than(t2, t2) == false); assert(tick_count_traits::less_than(t5, t5) == false); assert(tick_count_traits::less_than(t1, t2)); assert(tick_count_traits::less_than(t2, t4)); assert(tick_count_traits::less_than(t4, t5)); assert(tick_count_traits::less_than(t5, t6)); assert(tick_count_traits::less_than(t2, t1) == false); assert(tick_count_traits::less_than(t4, t2) == false); assert(tick_count_traits::less_than(t5, t4) == false); assert(tick_count_traits::less_than(t6, t5) == false); try { boost::asio::io_service io_service; tick_count_timer timer(io_service, 5000); std::cout << "Starting synchronous wait\n"; timer.wait(); std::cout << "Finished synchronous wait\n"; timer.expires_from_now(5000); std::cout << "Starting asynchronous wait\n"; timer.async_wait(handle_timeout); io_service.run(); std::cout << "Finished asynchronous wait\n"; } catch (std::exception& e) { std::cout << "Exception: " << e.what() << "\n"; } return 0; }