annotate DEPENDENCIES/generic/include/boost/asio/basic_socket_streambuf.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 //
Chris@16 2 // basic_socket_streambuf.hpp
Chris@16 3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
Chris@16 4 //
Chris@101 5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
Chris@16 6 //
Chris@16 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
Chris@16 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 9 //
Chris@16 10
Chris@16 11 #ifndef BOOST_ASIO_BASIC_SOCKET_STREAMBUF_HPP
Chris@16 12 #define BOOST_ASIO_BASIC_SOCKET_STREAMBUF_HPP
Chris@16 13
Chris@16 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
Chris@16 15 # pragma once
Chris@16 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
Chris@16 17
Chris@16 18 #include <boost/asio/detail/config.hpp>
Chris@16 19
Chris@16 20 #if !defined(BOOST_ASIO_NO_IOSTREAM)
Chris@16 21
Chris@16 22 #include <streambuf>
Chris@16 23 #include <boost/asio/basic_socket.hpp>
Chris@16 24 #include <boost/asio/deadline_timer_service.hpp>
Chris@16 25 #include <boost/asio/detail/array.hpp>
Chris@16 26 #include <boost/asio/detail/throw_error.hpp>
Chris@16 27 #include <boost/asio/io_service.hpp>
Chris@16 28 #include <boost/asio/stream_socket_service.hpp>
Chris@16 29
Chris@16 30 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
Chris@16 31 # include <boost/asio/deadline_timer.hpp>
Chris@16 32 #else
Chris@16 33 # include <boost/asio/steady_timer.hpp>
Chris@16 34 #endif
Chris@16 35
Chris@16 36 #if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
Chris@16 37
Chris@16 38 # include <boost/asio/detail/variadic_templates.hpp>
Chris@16 39
Chris@16 40 // A macro that should expand to:
Chris@16 41 // template <typename T1, ..., typename Tn>
Chris@16 42 // basic_socket_streambuf<Protocol, StreamSocketService,
Chris@16 43 // Time, TimeTraits, TimerService>* connect(
Chris@16 44 // T1 x1, ..., Tn xn)
Chris@16 45 // {
Chris@16 46 // init_buffers();
Chris@16 47 // this->basic_socket<Protocol, StreamSocketService>::close(ec_);
Chris@16 48 // typedef typename Protocol::resolver resolver_type;
Chris@16 49 // typedef typename resolver_type::query resolver_query;
Chris@16 50 // resolver_query query(x1, ..., xn);
Chris@16 51 // resolve_and_connect(query);
Chris@16 52 // return !ec_ ? this : 0;
Chris@16 53 // }
Chris@16 54 // This macro should only persist within this file.
Chris@16 55
Chris@16 56 # define BOOST_ASIO_PRIVATE_CONNECT_DEF(n) \
Chris@16 57 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
Chris@16 58 basic_socket_streambuf<Protocol, StreamSocketService, \
Chris@16 59 Time, TimeTraits, TimerService>* connect(BOOST_ASIO_VARIADIC_PARAMS(n)) \
Chris@16 60 { \
Chris@16 61 init_buffers(); \
Chris@16 62 this->basic_socket<Protocol, StreamSocketService>::close(ec_); \
Chris@16 63 typedef typename Protocol::resolver resolver_type; \
Chris@16 64 typedef typename resolver_type::query resolver_query; \
Chris@16 65 resolver_query query(BOOST_ASIO_VARIADIC_ARGS(n)); \
Chris@16 66 resolve_and_connect(query); \
Chris@16 67 return !ec_ ? this : 0; \
Chris@16 68 } \
Chris@16 69 /**/
Chris@16 70
Chris@16 71 #endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
Chris@16 72
Chris@16 73 #include <boost/asio/detail/push_options.hpp>
Chris@16 74
Chris@16 75 namespace boost {
Chris@16 76 namespace asio {
Chris@16 77 namespace detail {
Chris@16 78
Chris@16 79 // A separate base class is used to ensure that the io_service is initialised
Chris@16 80 // prior to the basic_socket_streambuf's basic_socket base class.
Chris@16 81 class socket_streambuf_base
Chris@16 82 {
Chris@16 83 protected:
Chris@16 84 io_service io_service_;
Chris@16 85 };
Chris@16 86
Chris@16 87 } // namespace detail
Chris@16 88
Chris@16 89 /// Iostream streambuf for a socket.
Chris@16 90 template <typename Protocol,
Chris@16 91 typename StreamSocketService = stream_socket_service<Protocol>,
Chris@16 92 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \
Chris@16 93 || defined(GENERATING_DOCUMENTATION)
Chris@16 94 typename Time = boost::posix_time::ptime,
Chris@16 95 typename TimeTraits = boost::asio::time_traits<Time>,
Chris@16 96 typename TimerService = deadline_timer_service<Time, TimeTraits> >
Chris@16 97 #else
Chris@16 98 typename Time = steady_timer::clock_type,
Chris@16 99 typename TimeTraits = steady_timer::traits_type,
Chris@16 100 typename TimerService = steady_timer::service_type>
Chris@16 101 #endif
Chris@16 102 class basic_socket_streambuf
Chris@16 103 : public std::streambuf,
Chris@16 104 private detail::socket_streambuf_base,
Chris@16 105 public basic_socket<Protocol, StreamSocketService>
Chris@16 106 {
Chris@16 107 private:
Chris@16 108 // These typedefs are intended keep this class's implementation independent
Chris@16 109 // of whether it's using Boost.DateTime, Boost.Chrono or std::chrono.
Chris@16 110 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
Chris@16 111 typedef TimeTraits traits_helper;
Chris@16 112 #else
Chris@16 113 typedef detail::chrono_time_traits<Time, TimeTraits> traits_helper;
Chris@16 114 #endif
Chris@16 115
Chris@16 116 public:
Chris@16 117 /// The endpoint type.
Chris@16 118 typedef typename Protocol::endpoint endpoint_type;
Chris@16 119
Chris@16 120 #if defined(GENERATING_DOCUMENTATION)
Chris@16 121 /// The time type.
Chris@16 122 typedef typename TimeTraits::time_type time_type;
Chris@16 123
Chris@16 124 /// The duration type.
Chris@16 125 typedef typename TimeTraits::duration_type duration_type;
Chris@16 126 #else
Chris@16 127 typedef typename traits_helper::time_type time_type;
Chris@16 128 typedef typename traits_helper::duration_type duration_type;
Chris@16 129 #endif
Chris@16 130
Chris@16 131 /// Construct a basic_socket_streambuf without establishing a connection.
Chris@16 132 basic_socket_streambuf()
Chris@16 133 : basic_socket<Protocol, StreamSocketService>(
Chris@16 134 this->detail::socket_streambuf_base::io_service_),
Chris@16 135 unbuffered_(false),
Chris@16 136 timer_service_(0),
Chris@16 137 timer_state_(no_timer)
Chris@16 138 {
Chris@16 139 init_buffers();
Chris@16 140 }
Chris@16 141
Chris@16 142 /// Destructor flushes buffered data.
Chris@16 143 virtual ~basic_socket_streambuf()
Chris@16 144 {
Chris@16 145 if (pptr() != pbase())
Chris@16 146 overflow(traits_type::eof());
Chris@16 147
Chris@16 148 destroy_timer();
Chris@16 149 }
Chris@16 150
Chris@16 151 /// Establish a connection.
Chris@16 152 /**
Chris@16 153 * This function establishes a connection to the specified endpoint.
Chris@16 154 *
Chris@16 155 * @return \c this if a connection was successfully established, a null
Chris@16 156 * pointer otherwise.
Chris@16 157 */
Chris@16 158 basic_socket_streambuf<Protocol, StreamSocketService,
Chris@16 159 Time, TimeTraits, TimerService>* connect(
Chris@16 160 const endpoint_type& endpoint)
Chris@16 161 {
Chris@16 162 init_buffers();
Chris@16 163
Chris@16 164 this->basic_socket<Protocol, StreamSocketService>::close(ec_);
Chris@16 165
Chris@16 166 if (timer_state_ == timer_has_expired)
Chris@16 167 {
Chris@16 168 ec_ = boost::asio::error::operation_aborted;
Chris@16 169 return 0;
Chris@16 170 }
Chris@16 171
Chris@16 172 io_handler handler = { this };
Chris@16 173 this->basic_socket<Protocol, StreamSocketService>::async_connect(
Chris@16 174 endpoint, handler);
Chris@16 175
Chris@16 176 ec_ = boost::asio::error::would_block;
Chris@16 177 this->get_service().get_io_service().reset();
Chris@16 178 do this->get_service().get_io_service().run_one();
Chris@16 179 while (ec_ == boost::asio::error::would_block);
Chris@16 180
Chris@16 181 return !ec_ ? this : 0;
Chris@16 182 }
Chris@16 183
Chris@16 184 #if defined(GENERATING_DOCUMENTATION)
Chris@16 185 /// Establish a connection.
Chris@16 186 /**
Chris@16 187 * This function automatically establishes a connection based on the supplied
Chris@16 188 * resolver query parameters. The arguments are used to construct a resolver
Chris@16 189 * query object.
Chris@16 190 *
Chris@16 191 * @return \c this if a connection was successfully established, a null
Chris@16 192 * pointer otherwise.
Chris@16 193 */
Chris@16 194 template <typename T1, ..., typename TN>
Chris@16 195 basic_socket_streambuf<Protocol, StreamSocketService>* connect(
Chris@16 196 T1 t1, ..., TN tn);
Chris@16 197 #elif defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
Chris@16 198 template <typename... T>
Chris@16 199 basic_socket_streambuf<Protocol, StreamSocketService,
Chris@16 200 Time, TimeTraits, TimerService>* connect(T... x)
Chris@16 201 {
Chris@16 202 init_buffers();
Chris@16 203 this->basic_socket<Protocol, StreamSocketService>::close(ec_);
Chris@16 204 typedef typename Protocol::resolver resolver_type;
Chris@16 205 typedef typename resolver_type::query resolver_query;
Chris@16 206 resolver_query query(x...);
Chris@16 207 resolve_and_connect(query);
Chris@16 208 return !ec_ ? this : 0;
Chris@16 209 }
Chris@16 210 #else
Chris@16 211 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CONNECT_DEF)
Chris@16 212 #endif
Chris@16 213
Chris@16 214 /// Close the connection.
Chris@16 215 /**
Chris@16 216 * @return \c this if a connection was successfully established, a null
Chris@16 217 * pointer otherwise.
Chris@16 218 */
Chris@16 219 basic_socket_streambuf<Protocol, StreamSocketService,
Chris@16 220 Time, TimeTraits, TimerService>* close()
Chris@16 221 {
Chris@16 222 sync();
Chris@16 223 this->basic_socket<Protocol, StreamSocketService>::close(ec_);
Chris@16 224 if (!ec_)
Chris@16 225 init_buffers();
Chris@16 226 return !ec_ ? this : 0;
Chris@16 227 }
Chris@16 228
Chris@16 229 /// Get the last error associated with the stream buffer.
Chris@16 230 /**
Chris@16 231 * @return An \c error_code corresponding to the last error from the stream
Chris@16 232 * buffer.
Chris@16 233 */
Chris@16 234 const boost::system::error_code& puberror() const
Chris@16 235 {
Chris@16 236 return error();
Chris@16 237 }
Chris@16 238
Chris@16 239 /// Get the stream buffer's expiry time as an absolute time.
Chris@16 240 /**
Chris@16 241 * @return An absolute time value representing the stream buffer's expiry
Chris@16 242 * time.
Chris@16 243 */
Chris@16 244 time_type expires_at() const
Chris@16 245 {
Chris@16 246 return timer_service_
Chris@16 247 ? timer_service_->expires_at(timer_implementation_)
Chris@16 248 : time_type();
Chris@16 249 }
Chris@16 250
Chris@16 251 /// Set the stream buffer's expiry time as an absolute time.
Chris@16 252 /**
Chris@16 253 * This function sets the expiry time associated with the stream. Stream
Chris@16 254 * operations performed after this time (where the operations cannot be
Chris@16 255 * completed using the internal buffers) will fail with the error
Chris@16 256 * boost::asio::error::operation_aborted.
Chris@16 257 *
Chris@16 258 * @param expiry_time The expiry time to be used for the stream.
Chris@16 259 */
Chris@16 260 void expires_at(const time_type& expiry_time)
Chris@16 261 {
Chris@16 262 construct_timer();
Chris@16 263
Chris@16 264 boost::system::error_code ec;
Chris@16 265 timer_service_->expires_at(timer_implementation_, expiry_time, ec);
Chris@16 266 boost::asio::detail::throw_error(ec, "expires_at");
Chris@16 267
Chris@16 268 start_timer();
Chris@16 269 }
Chris@16 270
Chris@16 271 /// Get the stream buffer's expiry time relative to now.
Chris@16 272 /**
Chris@16 273 * @return A relative time value representing the stream buffer's expiry time.
Chris@16 274 */
Chris@16 275 duration_type expires_from_now() const
Chris@16 276 {
Chris@16 277 return traits_helper::subtract(expires_at(), traits_helper::now());
Chris@16 278 }
Chris@16 279
Chris@16 280 /// Set the stream buffer's expiry time relative to now.
Chris@16 281 /**
Chris@16 282 * This function sets the expiry time associated with the stream. Stream
Chris@16 283 * operations performed after this time (where the operations cannot be
Chris@16 284 * completed using the internal buffers) will fail with the error
Chris@16 285 * boost::asio::error::operation_aborted.
Chris@16 286 *
Chris@16 287 * @param expiry_time The expiry time to be used for the timer.
Chris@16 288 */
Chris@16 289 void expires_from_now(const duration_type& expiry_time)
Chris@16 290 {
Chris@16 291 construct_timer();
Chris@16 292
Chris@16 293 boost::system::error_code ec;
Chris@16 294 timer_service_->expires_from_now(timer_implementation_, expiry_time, ec);
Chris@16 295 boost::asio::detail::throw_error(ec, "expires_from_now");
Chris@16 296
Chris@16 297 start_timer();
Chris@16 298 }
Chris@16 299
Chris@16 300 protected:
Chris@16 301 int_type underflow()
Chris@16 302 {
Chris@16 303 if (gptr() == egptr())
Chris@16 304 {
Chris@16 305 if (timer_state_ == timer_has_expired)
Chris@16 306 {
Chris@16 307 ec_ = boost::asio::error::operation_aborted;
Chris@16 308 return traits_type::eof();
Chris@16 309 }
Chris@16 310
Chris@16 311 io_handler handler = { this };
Chris@16 312 this->get_service().async_receive(this->get_implementation(),
Chris@16 313 boost::asio::buffer(boost::asio::buffer(get_buffer_) + putback_max),
Chris@16 314 0, handler);
Chris@16 315
Chris@16 316 ec_ = boost::asio::error::would_block;
Chris@16 317 this->get_service().get_io_service().reset();
Chris@16 318 do this->get_service().get_io_service().run_one();
Chris@16 319 while (ec_ == boost::asio::error::would_block);
Chris@16 320 if (ec_)
Chris@16 321 return traits_type::eof();
Chris@16 322
Chris@16 323 setg(&get_buffer_[0], &get_buffer_[0] + putback_max,
Chris@16 324 &get_buffer_[0] + putback_max + bytes_transferred_);
Chris@16 325 return traits_type::to_int_type(*gptr());
Chris@16 326 }
Chris@16 327 else
Chris@16 328 {
Chris@16 329 return traits_type::eof();
Chris@16 330 }
Chris@16 331 }
Chris@16 332
Chris@16 333 int_type overflow(int_type c)
Chris@16 334 {
Chris@16 335 if (unbuffered_)
Chris@16 336 {
Chris@16 337 if (traits_type::eq_int_type(c, traits_type::eof()))
Chris@16 338 {
Chris@16 339 // Nothing to do.
Chris@16 340 return traits_type::not_eof(c);
Chris@16 341 }
Chris@16 342 else
Chris@16 343 {
Chris@16 344 if (timer_state_ == timer_has_expired)
Chris@16 345 {
Chris@16 346 ec_ = boost::asio::error::operation_aborted;
Chris@16 347 return traits_type::eof();
Chris@16 348 }
Chris@16 349
Chris@16 350 // Send the single character immediately.
Chris@16 351 char_type ch = traits_type::to_char_type(c);
Chris@16 352 io_handler handler = { this };
Chris@16 353 this->get_service().async_send(this->get_implementation(),
Chris@16 354 boost::asio::buffer(&ch, sizeof(char_type)), 0, handler);
Chris@16 355
Chris@16 356 ec_ = boost::asio::error::would_block;
Chris@16 357 this->get_service().get_io_service().reset();
Chris@16 358 do this->get_service().get_io_service().run_one();
Chris@16 359 while (ec_ == boost::asio::error::would_block);
Chris@16 360 if (ec_)
Chris@16 361 return traits_type::eof();
Chris@16 362
Chris@16 363 return c;
Chris@16 364 }
Chris@16 365 }
Chris@16 366 else
Chris@16 367 {
Chris@16 368 // Send all data in the output buffer.
Chris@16 369 boost::asio::const_buffer buffer =
Chris@16 370 boost::asio::buffer(pbase(), pptr() - pbase());
Chris@16 371 while (boost::asio::buffer_size(buffer) > 0)
Chris@16 372 {
Chris@16 373 if (timer_state_ == timer_has_expired)
Chris@16 374 {
Chris@16 375 ec_ = boost::asio::error::operation_aborted;
Chris@16 376 return traits_type::eof();
Chris@16 377 }
Chris@16 378
Chris@16 379 io_handler handler = { this };
Chris@16 380 this->get_service().async_send(this->get_implementation(),
Chris@16 381 boost::asio::buffer(buffer), 0, handler);
Chris@16 382
Chris@16 383 ec_ = boost::asio::error::would_block;
Chris@16 384 this->get_service().get_io_service().reset();
Chris@16 385 do this->get_service().get_io_service().run_one();
Chris@16 386 while (ec_ == boost::asio::error::would_block);
Chris@16 387 if (ec_)
Chris@16 388 return traits_type::eof();
Chris@16 389
Chris@16 390 buffer = buffer + bytes_transferred_;
Chris@16 391 }
Chris@16 392 setp(&put_buffer_[0], &put_buffer_[0] + put_buffer_.size());
Chris@16 393
Chris@16 394 // If the new character is eof then our work here is done.
Chris@16 395 if (traits_type::eq_int_type(c, traits_type::eof()))
Chris@16 396 return traits_type::not_eof(c);
Chris@16 397
Chris@16 398 // Add the new character to the output buffer.
Chris@16 399 *pptr() = traits_type::to_char_type(c);
Chris@16 400 pbump(1);
Chris@16 401 return c;
Chris@16 402 }
Chris@16 403 }
Chris@16 404
Chris@16 405 int sync()
Chris@16 406 {
Chris@16 407 return overflow(traits_type::eof());
Chris@16 408 }
Chris@16 409
Chris@16 410 std::streambuf* setbuf(char_type* s, std::streamsize n)
Chris@16 411 {
Chris@16 412 if (pptr() == pbase() && s == 0 && n == 0)
Chris@16 413 {
Chris@16 414 unbuffered_ = true;
Chris@16 415 setp(0, 0);
Chris@16 416 return this;
Chris@16 417 }
Chris@16 418
Chris@16 419 return 0;
Chris@16 420 }
Chris@16 421
Chris@16 422 /// Get the last error associated with the stream buffer.
Chris@16 423 /**
Chris@16 424 * @return An \c error_code corresponding to the last error from the stream
Chris@16 425 * buffer.
Chris@16 426 */
Chris@16 427 virtual const boost::system::error_code& error() const
Chris@16 428 {
Chris@16 429 return ec_;
Chris@16 430 }
Chris@16 431
Chris@16 432 private:
Chris@16 433 void init_buffers()
Chris@16 434 {
Chris@16 435 setg(&get_buffer_[0],
Chris@16 436 &get_buffer_[0] + putback_max,
Chris@16 437 &get_buffer_[0] + putback_max);
Chris@16 438 if (unbuffered_)
Chris@16 439 setp(0, 0);
Chris@16 440 else
Chris@16 441 setp(&put_buffer_[0], &put_buffer_[0] + put_buffer_.size());
Chris@16 442 }
Chris@16 443
Chris@16 444 template <typename ResolverQuery>
Chris@16 445 void resolve_and_connect(const ResolverQuery& query)
Chris@16 446 {
Chris@16 447 typedef typename Protocol::resolver resolver_type;
Chris@16 448 typedef typename resolver_type::iterator iterator_type;
Chris@16 449 resolver_type resolver(detail::socket_streambuf_base::io_service_);
Chris@16 450 iterator_type i = resolver.resolve(query, ec_);
Chris@16 451 if (!ec_)
Chris@16 452 {
Chris@16 453 iterator_type end;
Chris@16 454 ec_ = boost::asio::error::host_not_found;
Chris@16 455 while (ec_ && i != end)
Chris@16 456 {
Chris@16 457 this->basic_socket<Protocol, StreamSocketService>::close(ec_);
Chris@16 458
Chris@16 459 if (timer_state_ == timer_has_expired)
Chris@16 460 {
Chris@16 461 ec_ = boost::asio::error::operation_aborted;
Chris@16 462 return;
Chris@16 463 }
Chris@16 464
Chris@16 465 io_handler handler = { this };
Chris@16 466 this->basic_socket<Protocol, StreamSocketService>::async_connect(
Chris@16 467 *i, handler);
Chris@16 468
Chris@16 469 ec_ = boost::asio::error::would_block;
Chris@16 470 this->get_service().get_io_service().reset();
Chris@16 471 do this->get_service().get_io_service().run_one();
Chris@16 472 while (ec_ == boost::asio::error::would_block);
Chris@16 473
Chris@16 474 ++i;
Chris@16 475 }
Chris@16 476 }
Chris@16 477 }
Chris@16 478
Chris@16 479 struct io_handler;
Chris@16 480 friend struct io_handler;
Chris@16 481 struct io_handler
Chris@16 482 {
Chris@16 483 basic_socket_streambuf* this_;
Chris@16 484
Chris@16 485 void operator()(const boost::system::error_code& ec,
Chris@16 486 std::size_t bytes_transferred = 0)
Chris@16 487 {
Chris@16 488 this_->ec_ = ec;
Chris@16 489 this_->bytes_transferred_ = bytes_transferred;
Chris@16 490 }
Chris@16 491 };
Chris@16 492
Chris@16 493 struct timer_handler;
Chris@16 494 friend struct timer_handler;
Chris@16 495 struct timer_handler
Chris@16 496 {
Chris@16 497 basic_socket_streambuf* this_;
Chris@16 498
Chris@16 499 void operator()(const boost::system::error_code&)
Chris@16 500 {
Chris@16 501 time_type now = traits_helper::now();
Chris@16 502
Chris@16 503 time_type expiry_time = this_->timer_service_->expires_at(
Chris@16 504 this_->timer_implementation_);
Chris@16 505
Chris@16 506 if (traits_helper::less_than(now, expiry_time))
Chris@16 507 {
Chris@16 508 this_->timer_state_ = timer_is_pending;
Chris@16 509 this_->timer_service_->async_wait(this_->timer_implementation_, *this);
Chris@16 510 }
Chris@16 511 else
Chris@16 512 {
Chris@16 513 this_->timer_state_ = timer_has_expired;
Chris@16 514 boost::system::error_code ec;
Chris@16 515 this_->basic_socket<Protocol, StreamSocketService>::close(ec);
Chris@16 516 }
Chris@16 517 }
Chris@16 518 };
Chris@16 519
Chris@16 520 void construct_timer()
Chris@16 521 {
Chris@16 522 if (timer_service_ == 0)
Chris@16 523 {
Chris@16 524 TimerService& timer_service = use_service<TimerService>(
Chris@16 525 detail::socket_streambuf_base::io_service_);
Chris@16 526 timer_service.construct(timer_implementation_);
Chris@16 527 timer_service_ = &timer_service;
Chris@16 528 }
Chris@16 529 }
Chris@16 530
Chris@16 531 void destroy_timer()
Chris@16 532 {
Chris@16 533 if (timer_service_)
Chris@16 534 timer_service_->destroy(timer_implementation_);
Chris@16 535 }
Chris@16 536
Chris@16 537 void start_timer()
Chris@16 538 {
Chris@16 539 if (timer_state_ != timer_is_pending)
Chris@16 540 {
Chris@16 541 timer_handler handler = { this };
Chris@16 542 handler(boost::system::error_code());
Chris@16 543 }
Chris@16 544 }
Chris@16 545
Chris@16 546 enum { putback_max = 8 };
Chris@16 547 enum { buffer_size = 512 };
Chris@16 548 boost::asio::detail::array<char, buffer_size> get_buffer_;
Chris@16 549 boost::asio::detail::array<char, buffer_size> put_buffer_;
Chris@16 550 bool unbuffered_;
Chris@16 551 boost::system::error_code ec_;
Chris@16 552 std::size_t bytes_transferred_;
Chris@16 553 TimerService* timer_service_;
Chris@16 554 typename TimerService::implementation_type timer_implementation_;
Chris@16 555 enum state { no_timer, timer_is_pending, timer_has_expired } timer_state_;
Chris@16 556 };
Chris@16 557
Chris@16 558 } // namespace asio
Chris@16 559 } // namespace boost
Chris@16 560
Chris@16 561 #include <boost/asio/detail/pop_options.hpp>
Chris@16 562
Chris@16 563 #if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
Chris@16 564 # undef BOOST_ASIO_PRIVATE_CONNECT_DEF
Chris@16 565 #endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
Chris@16 566
Chris@16 567 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
Chris@16 568
Chris@16 569 #endif // BOOST_ASIO_BASIC_SOCKET_STREAMBUF_HPP