$search
00001 // 00002 // deadline_timer_service.hpp 00003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~ 00004 // 00005 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com) 00006 // 00007 // Distributed under the Boost Software License, Version 1.0. (See accompanying 00008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 00009 // 00010 00011 #ifndef ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP 00012 #define ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP 00013 00014 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 00015 # pragma once 00016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 00017 00018 #include "asio/detail/push_options.hpp" 00019 00020 #include "asio/detail/push_options.hpp" 00021 #include <cstddef> 00022 #include <boost/config.hpp> 00023 #include <boost/date_time/posix_time/posix_time_types.hpp> 00024 #include "asio/detail/pop_options.hpp" 00025 00026 #include "asio/error.hpp" 00027 #include "asio/io_service.hpp" 00028 #include "asio/detail/bind_handler.hpp" 00029 #include "asio/detail/handler_base_from_member.hpp" 00030 #include "asio/detail/noncopyable.hpp" 00031 #include "asio/detail/service_base.hpp" 00032 #include "asio/detail/socket_ops.hpp" 00033 #include "asio/detail/socket_types.hpp" 00034 #include "asio/detail/timer_queue.hpp" 00035 00036 namespace asio { 00037 namespace detail { 00038 00039 template <typename Time_Traits, typename Timer_Scheduler> 00040 class deadline_timer_service 00041 : public asio::detail::service_base< 00042 deadline_timer_service<Time_Traits, Timer_Scheduler> > 00043 { 00044 public: 00045 // The time type. 00046 typedef typename Time_Traits::time_type time_type; 00047 00048 // The duration type. 00049 typedef typename Time_Traits::duration_type duration_type; 00050 00051 // The implementation type of the timer. This type is dependent on the 00052 // underlying implementation of the timer service. 00053 struct implementation_type 00054 : private asio::detail::noncopyable 00055 { 00056 time_type expiry; 00057 bool might_have_pending_waits; 00058 }; 00059 00060 // Constructor. 00061 deadline_timer_service(asio::io_service& io_service) 00062 : asio::detail::service_base< 00063 deadline_timer_service<Time_Traits, Timer_Scheduler> >(io_service), 00064 scheduler_(asio::use_service<Timer_Scheduler>(io_service)) 00065 { 00066 scheduler_.add_timer_queue(timer_queue_); 00067 } 00068 00069 // Destructor. 00070 ~deadline_timer_service() 00071 { 00072 scheduler_.remove_timer_queue(timer_queue_); 00073 } 00074 00075 // Destroy all user-defined handler objects owned by the service. 00076 void shutdown_service() 00077 { 00078 } 00079 00080 // Construct a new timer implementation. 00081 void construct(implementation_type& impl) 00082 { 00083 impl.expiry = time_type(); 00084 impl.might_have_pending_waits = false; 00085 } 00086 00087 // Destroy a timer implementation. 00088 void destroy(implementation_type& impl) 00089 { 00090 asio::error_code ec; 00091 cancel(impl, ec); 00092 } 00093 00094 // Cancel any asynchronous wait operations associated with the timer. 00095 std::size_t cancel(implementation_type& impl, asio::error_code& ec) 00096 { 00097 if (!impl.might_have_pending_waits) 00098 { 00099 ec = asio::error_code(); 00100 return 0; 00101 } 00102 std::size_t count = scheduler_.cancel_timer(timer_queue_, &impl); 00103 impl.might_have_pending_waits = false; 00104 ec = asio::error_code(); 00105 return count; 00106 } 00107 00108 // Get the expiry time for the timer as an absolute time. 00109 time_type expires_at(const implementation_type& impl) const 00110 { 00111 return impl.expiry; 00112 } 00113 00114 // Set the expiry time for the timer as an absolute time. 00115 std::size_t expires_at(implementation_type& impl, 00116 const time_type& expiry_time, asio::error_code& ec) 00117 { 00118 std::size_t count = cancel(impl, ec); 00119 impl.expiry = expiry_time; 00120 ec = asio::error_code(); 00121 return count; 00122 } 00123 00124 // Get the expiry time for the timer relative to now. 00125 duration_type expires_from_now(const implementation_type& impl) const 00126 { 00127 return Time_Traits::subtract(expires_at(impl), Time_Traits::now()); 00128 } 00129 00130 // Set the expiry time for the timer relative to now. 00131 std::size_t expires_from_now(implementation_type& impl, 00132 const duration_type& expiry_time, asio::error_code& ec) 00133 { 00134 return expires_at(impl, 00135 Time_Traits::add(Time_Traits::now(), expiry_time), ec); 00136 } 00137 00138 // Perform a blocking wait on the timer. 00139 void wait(implementation_type& impl, asio::error_code& ec) 00140 { 00141 time_type now = Time_Traits::now(); 00142 while (Time_Traits::less_than(now, impl.expiry)) 00143 { 00144 boost::posix_time::time_duration timeout = 00145 Time_Traits::to_posix_duration(Time_Traits::subtract(impl.expiry, now)); 00146 ::timeval tv; 00147 tv.tv_sec = timeout.total_seconds(); 00148 tv.tv_usec = timeout.total_microseconds() % 1000000; 00149 asio::error_code ec; 00150 socket_ops::select(0, 0, 0, 0, &tv, ec); 00151 now = Time_Traits::now(); 00152 } 00153 ec = asio::error_code(); 00154 } 00155 00156 template <typename Handler> 00157 class wait_handler : 00158 public handler_base_from_member<Handler> 00159 { 00160 public: 00161 wait_handler(asio::io_service& io_service, Handler handler) 00162 : handler_base_from_member<Handler>(handler), 00163 io_service_(io_service), 00164 work_(io_service) 00165 { 00166 } 00167 00168 void operator()(const asio::error_code& result) 00169 { 00170 io_service_.post(detail::bind_handler(this->handler_, result)); 00171 } 00172 00173 private: 00174 asio::io_service& io_service_; 00175 asio::io_service::work work_; 00176 }; 00177 00178 // Start an asynchronous wait on the timer. 00179 template <typename Handler> 00180 void async_wait(implementation_type& impl, Handler handler) 00181 { 00182 impl.might_have_pending_waits = true; 00183 scheduler_.schedule_timer(timer_queue_, impl.expiry, 00184 wait_handler<Handler>(this->get_io_service(), handler), &impl); 00185 } 00186 00187 private: 00188 // The queue of timers. 00189 timer_queue<Time_Traits> timer_queue_; 00190 00191 // The object that schedules and executes timers. Usually a reactor. 00192 Timer_Scheduler& scheduler_; 00193 }; 00194 00195 } // namespace detail 00196 } // namespace asio 00197 00198 #include "asio/detail/pop_options.hpp" 00199 00200 #endif // ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP