Go to the documentation of this file.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/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
00046 typedef typename Time_Traits::time_type time_type;
00047
00048
00049 typedef typename Time_Traits::duration_type duration_type;
00050
00051
00052
00053 struct implementation_type
00054 : private asio::detail::noncopyable
00055 {
00056 time_type expiry;
00057 bool might_have_pending_waits;
00058 };
00059
00060
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
00070 ~deadline_timer_service()
00071 {
00072 scheduler_.remove_timer_queue(timer_queue_);
00073 }
00074
00075
00076 void shutdown_service()
00077 {
00078 }
00079
00080
00081 void construct(implementation_type& impl)
00082 {
00083 impl.expiry = time_type();
00084 impl.might_have_pending_waits = false;
00085 }
00086
00087
00088 void destroy(implementation_type& impl)
00089 {
00090 asio::error_code ec;
00091 cancel(impl, ec);
00092 }
00093
00094
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
00109 time_type expires_at(const implementation_type& impl) const
00110 {
00111 return impl.expiry;
00112 }
00113
00114
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
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
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
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
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
00189 timer_queue<Time_Traits> timer_queue_;
00190
00191
00192 Timer_Scheduler& scheduler_;
00193 };
00194
00195 }
00196 }
00197
00198 #include "asio/detail/pop_options.hpp"
00199
00200 #endif // ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP