00001
00002
00003
00004
00005
00006
00007
00008
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/noncopyable.hpp"
00030 #include "asio/detail/service_base.hpp"
00031 #include "asio/detail/socket_ops.hpp"
00032 #include "asio/detail/socket_types.hpp"
00033 #include "asio/detail/timer_queue.hpp"
00034
00035 namespace asio {
00036 namespace detail {
00037
00038 template <typename Time_Traits, typename Timer_Scheduler>
00039 class deadline_timer_service
00040 : public asio::detail::service_base<
00041 deadline_timer_service<Time_Traits, Timer_Scheduler> >
00042 {
00043 public:
00044
00045 typedef typename Time_Traits::time_type time_type;
00046
00047
00048 typedef typename Time_Traits::duration_type duration_type;
00049
00050
00051
00052 struct implementation_type
00053 : private asio::detail::noncopyable
00054 {
00055 time_type expiry;
00056 bool might_have_pending_waits;
00057 };
00058
00059
00060 deadline_timer_service(asio::io_service& io_service)
00061 : asio::detail::service_base<
00062 deadline_timer_service<Time_Traits, Timer_Scheduler> >(io_service),
00063 scheduler_(asio::use_service<Timer_Scheduler>(io_service))
00064 {
00065 scheduler_.add_timer_queue(timer_queue_);
00066 }
00067
00068
00069 ~deadline_timer_service()
00070 {
00071 scheduler_.remove_timer_queue(timer_queue_);
00072 }
00073
00074
00075 void shutdown_service()
00076 {
00077 }
00078
00079
00080 void construct(implementation_type& impl)
00081 {
00082 impl.expiry = time_type();
00083 impl.might_have_pending_waits = false;
00084 }
00085
00086
00087 void destroy(implementation_type& impl)
00088 {
00089 asio::error_code ec;
00090 cancel(impl, ec);
00091 }
00092
00093
00094 std::size_t cancel(implementation_type& impl, asio::error_code& ec)
00095 {
00096 if (!impl.might_have_pending_waits)
00097 {
00098 ec = asio::error_code();
00099 return 0;
00100 }
00101 std::size_t count = scheduler_.cancel_timer(timer_queue_, &impl);
00102 impl.might_have_pending_waits = false;
00103 ec = asio::error_code();
00104 return count;
00105 }
00106
00107
00108 time_type expires_at(const implementation_type& impl) const
00109 {
00110 return impl.expiry;
00111 }
00112
00113
00114 std::size_t expires_at(implementation_type& impl,
00115 const time_type& expiry_time, asio::error_code& ec)
00116 {
00117 std::size_t count = cancel(impl, ec);
00118 impl.expiry = expiry_time;
00119 ec = asio::error_code();
00120 return count;
00121 }
00122
00123
00124 duration_type expires_from_now(const implementation_type& impl) const
00125 {
00126 return Time_Traits::subtract(expires_at(impl), Time_Traits::now());
00127 }
00128
00129
00130 std::size_t expires_from_now(implementation_type& impl,
00131 const duration_type& expiry_time, asio::error_code& ec)
00132 {
00133 return expires_at(impl,
00134 Time_Traits::add(Time_Traits::now(), expiry_time), ec);
00135 }
00136
00137
00138 void wait(implementation_type& impl, asio::error_code& ec)
00139 {
00140 time_type now = Time_Traits::now();
00141 while (Time_Traits::less_than(now, impl.expiry))
00142 {
00143 boost::posix_time::time_duration timeout =
00144 Time_Traits::to_posix_duration(Time_Traits::subtract(impl.expiry, now));
00145 ::timeval tv;
00146 tv.tv_sec = timeout.total_seconds();
00147 tv.tv_usec = timeout.total_microseconds() % 1000000;
00148 asio::error_code ec;
00149 socket_ops::select(0, 0, 0, 0, &tv, ec);
00150 now = Time_Traits::now();
00151 }
00152 ec = asio::error_code();
00153 }
00154
00155 template <typename Handler>
00156 class wait_handler
00157 {
00158 public:
00159 wait_handler(asio::io_service& io_service, Handler handler)
00160 : io_service_(io_service),
00161 work_(io_service),
00162 handler_(handler)
00163 {
00164 }
00165
00166 void operator()(const asio::error_code& result)
00167 {
00168 io_service_.post(detail::bind_handler(handler_, result));
00169 }
00170
00171 private:
00172 asio::io_service& io_service_;
00173 asio::io_service::work work_;
00174 Handler handler_;
00175 };
00176
00177
00178 template <typename Handler>
00179 void async_wait(implementation_type& impl, Handler handler)
00180 {
00181 impl.might_have_pending_waits = true;
00182 scheduler_.schedule_timer(timer_queue_, impl.expiry,
00183 wait_handler<Handler>(this->io_service(), handler), &impl);
00184 }
00185
00186 private:
00187
00188 timer_queue<Time_Traits> timer_queue_;
00189
00190
00191 Timer_Scheduler& scheduler_;
00192 };
00193
00194 }
00195 }
00196
00197 #include "asio/detail/pop_options.hpp"
00198
00199 #endif // ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP