Browse Source

Merge branch 'master' into trac684

chenzhengzhang 14 years ago
parent
commit
d11b5e8920
100 changed files with 11254 additions and 1733 deletions
  1. 128 6
      ChangeLog
  2. 273 177
      Makefile.am
  3. 94 13
      configure.ac
  4. 8 6
      doc/Doxyfile
  5. 7 2
      ext/asio/README
  6. 1 1
      ext/asio/asio.hpp
  7. 5 8
      ext/asio/asio/basic_datagram_socket.hpp
  8. 5 8
      ext/asio/asio/basic_deadline_timer.hpp
  9. 5 4
      ext/asio/asio/basic_io_object.hpp
  10. 6 9
      ext/asio/asio/basic_raw_socket.hpp
  11. 9 11
      ext/asio/asio/basic_serial_port.hpp
  12. 5 8
      ext/asio/asio/basic_socket.hpp
  13. 5 4
      ext/asio/asio/basic_socket_acceptor.hpp
  14. 6 11
      ext/asio/asio/basic_socket_iostream.hpp
  15. 7 12
      ext/asio/asio/basic_socket_streambuf.hpp
  16. 5 8
      ext/asio/asio/basic_stream_socket.hpp
  17. 28 10
      ext/asio/asio/basic_streambuf.hpp
  18. 33 0
      ext/asio/asio/basic_streambuf_fwd.hpp
  19. 12 10
      ext/asio/asio/buffer.hpp
  20. 6 9
      ext/asio/asio/buffered_read_stream.hpp
  21. 1 5
      ext/asio/asio/buffered_read_stream_fwd.hpp
  22. 5 8
      ext/asio/asio/buffered_stream.hpp
  23. 1 5
      ext/asio/asio/buffered_stream_fwd.hpp
  24. 7 10
      ext/asio/asio/buffered_write_stream.hpp
  25. 1 5
      ext/asio/asio/buffered_write_stream_fwd.hpp
  26. 13 7
      ext/asio/asio/buffers_iterator.hpp
  27. 3 5
      ext/asio/asio/completion_condition.hpp
  28. 4 8
      ext/asio/asio/datagram_socket_service.hpp
  29. 3 7
      ext/asio/asio/deadline_timer.hpp
  30. 5 9
      ext/asio/asio/deadline_timer_service.hpp
  31. 25 0
      ext/asio/asio/detail/array_fwd.hpp
  32. 10 7
      ext/asio/asio/detail/base_from_completion_cond.hpp
  33. 21 10
      ext/asio/asio/detail/bind_handler.hpp
  34. 5 7
      ext/asio/asio/detail/buffer_resize_guard.hpp
  35. 11 9
      ext/asio/asio/detail/buffer_sequence_adapter.hpp
  36. 6 8
      ext/asio/asio/detail/buffered_stream_storage.hpp
  37. 6 5
      ext/asio/asio/detail/call_stack.hpp
  38. 19 15
      ext/asio/asio/detail/completion_handler.hpp
  39. 205 0
      ext/asio/asio/detail/config.hpp
  40. 9 11
      ext/asio/asio/detail/consuming_buffers.hpp
  41. 20 56
      ext/asio/asio/detail/deadline_timer_service.hpp
  42. 50 121
      ext/asio/asio/detail/descriptor_ops.hpp
  43. 114 0
      ext/asio/asio/detail/descriptor_read_op.hpp
  44. 114 0
      ext/asio/asio/detail/descriptor_write_op.hpp
  45. 49 317
      ext/asio/asio/detail/dev_poll_reactor.hpp
  46. 6 13
      ext/asio/asio/detail/dev_poll_reactor_fwd.hpp
  47. 58 368
      ext/asio/asio/detail/epoll_reactor.hpp
  48. 6 20
      ext/asio/asio/detail/epoll_reactor_fwd.hpp
  49. 4 10
      ext/asio/asio/detail/event.hpp
  50. 14 106
      ext/asio/asio/detail/eventfd_select_interrupter.hpp
  51. 4 11
      ext/asio/asio/detail/fd_set_adapter.hpp
  52. 20 14
      ext/asio/asio/detail/fenced_block.hpp
  53. 76 0
      ext/asio/asio/detail/gcc_arm_fenced_block.hpp
  54. 58 0
      ext/asio/asio/detail/gcc_hppa_fenced_block.hpp
  55. 61 0
      ext/asio/asio/detail/gcc_sync_fenced_block.hpp
  56. 8 10
      ext/asio/asio/detail/gcc_x86_fenced_block.hpp
  57. 32 206
      ext/asio/asio/detail/handler_alloc_helpers.hpp
  58. 6 8
      ext/asio/asio/detail/handler_invoke_helpers.hpp
  59. 20 15
      ext/asio/asio/detail/hash_map.hpp
  60. 382 0
      ext/asio/asio/detail/impl/descriptor_ops.ipp
  61. 77 0
      ext/asio/asio/detail/impl/dev_poll_reactor.hpp
  62. 338 0
      ext/asio/asio/detail/impl/dev_poll_reactor.ipp
  63. 75 0
      ext/asio/asio/detail/impl/epoll_reactor.hpp
  64. 390 0
      ext/asio/asio/detail/impl/epoll_reactor.ipp
  65. 125 0
      ext/asio/asio/detail/impl/eventfd_select_interrupter.ipp
  66. 79 0
      ext/asio/asio/detail/impl/kqueue_reactor.hpp
  67. 385 0
      ext/asio/asio/detail/impl/kqueue_reactor.ipp
  68. 96 0
      ext/asio/asio/detail/impl/pipe_select_interrupter.ipp
  69. 46 0
      ext/asio/asio/detail/impl/posix_event.ipp
  70. 46 0
      ext/asio/asio/detail/impl/posix_mutex.ipp
  71. 74 0
      ext/asio/asio/detail/impl/posix_thread.ipp
  72. 46 0
      ext/asio/asio/detail/impl/posix_tss_ptr.ipp
  73. 136 0
      ext/asio/asio/detail/impl/reactive_descriptor_service.ipp
  74. 151 0
      ext/asio/asio/detail/impl/reactive_serial_port_service.ipp
  75. 212 0
      ext/asio/asio/detail/impl/reactive_socket_service_base.ipp
  76. 106 0
      ext/asio/asio/detail/impl/resolver_service_base.ipp
  77. 84 0
      ext/asio/asio/detail/impl/select_reactor.hpp
  78. 273 0
      ext/asio/asio/detail/impl/select_reactor.ipp
  79. 70 0
      ext/asio/asio/detail/impl/service_registry.hpp
  80. 164 0
      ext/asio/asio/detail/impl/service_registry.ipp
  81. 2917 0
      ext/asio/asio/detail/impl/socket_ops.ipp
  82. 151 0
      ext/asio/asio/detail/impl/socket_select_interrupter.ipp
  83. 140 0
      ext/asio/asio/detail/impl/strand_service.hpp
  84. 106 0
      ext/asio/asio/detail/impl/strand_service.ipp
  85. 60 0
      ext/asio/asio/detail/impl/task_io_service.hpp
  86. 354 0
      ext/asio/asio/detail/impl/task_io_service.ipp
  87. 47 0
      ext/asio/asio/detail/impl/throw_error.ipp
  88. 85 0
      ext/asio/asio/detail/impl/timer_queue.ipp
  89. 101 0
      ext/asio/asio/detail/impl/timer_queue_set.ipp
  90. 50 0
      ext/asio/asio/detail/impl/win_event.ipp
  91. 452 0
      ext/asio/asio/detail/impl/win_iocp_handle_service.ipp
  92. 115 0
      ext/asio/asio/detail/impl/win_iocp_io_service.hpp
  93. 496 0
      ext/asio/asio/detail/impl/win_iocp_io_service.ipp
  94. 180 0
      ext/asio/asio/detail/impl/win_iocp_serial_port_service.ipp
  95. 575 0
      ext/asio/asio/detail/impl/win_iocp_socket_service_base.ipp
  96. 78 0
      ext/asio/asio/detail/impl/win_mutex.ipp
  97. 138 0
      ext/asio/asio/detail/impl/win_thread.ipp
  98. 57 0
      ext/asio/asio/detail/impl/win_tss_ptr.ipp
  99. 69 0
      ext/asio/asio/detail/impl/winsock_init.ipp
  100. 0 0
      ext/asio/asio/detail/io_control.hpp

+ 128 - 6
ChangeLog

@@ -1,4 +1,126 @@
-222.	[bug] 		jerry
+238.	[func]		zhang likun
+	Implement the simplest forwarder, which pass everything throught
+	except QID, port number. The response will not be cached.
+	(Trac #598_new, git 8e28187a582820857ef2dae9b13637a3881f13ba)
+
+237.	[bug]		naokikambe
+	Resolved that the stats module wasn't configurable in bindctl in
+	spite of its having configuration items. The configuration part
+	was removed from the original spec file "stats.spec" and was
+	placed in a new spec file "stats-schema.spec". Because it means
+	definitions of statistics items. The command part is still
+	there. Thus stats module currently has no its own configuration,
+	and the items in "stats-schema.spec" are neither visible nor
+	configurable through bindctl. "stats-schema.spec" is shared with
+	stats module and stats-httpd module, and maybe with other
+	statistical modules in future. "stats.spec" has own configuration
+	and commands of stats module, if it requires.
+	(Trac#719, git a234b20dc6617392deb8a1e00eb0eed0ff353c0a)
+
+236.	[func]		jelte
+	C++ client side of configuration now uses BIND10 logging system.
+	It also has improved error handling when communicating with the
+	rest of the system.
+	(Trac #743, git 86632c12308c3ed099d75eb828f740c526dd7ec0)
+
+235.	[func]		jinmei
+	libdns++: added support for TSIG signing and verification.  It can
+	be done using a newly introduced TSIGContext class.
+	Note: we temporarily disabled support for truncated signature
+	and modified some part of the code introduced in #226 accordingly.
+	We plan to fix this pretty soon.
+	(Trac #812, git ebe0c4b1e66d359227bdd1bd47395fee7b957f14)
+	(Trac #871, git 7c54055c0e47c7a0e36fcfab4b47ff180c0ca8c8)
+	(Trac #813, git ffa2f0672084c1f16e5784cdcdd55822f119feaa)
+	(Trac #893, git 5aaa6c0f628ed7c2093ecdbac93a2c8cf6c94349)
+
+234.	[func]		jerry
+	src/bin/xfrin: update xfrin to use TSIG. Currently it only supports
+	sending a signed TSIG request or SOA request.
+	(Trac #815, git a892818fb13a1839c82104523cb6cb359c970e88)
+
+233.	[func]		stephen
+	Added new-style logging statements to the NSAS code.
+	(Trac #745, git ceef68cd1223ae14d8412adbe18af2812ade8c2d)
+
+232.	[func]		stephen
+	To facilitate the writing of extended descriptions in
+	message files, altered the message file format.  The message
+	is now flagged with a "%" as the first non-blank character
+	in the line and the lines in the extended description are
+	no longer preceded by a "+".
+	(Trac #900, git b395258c708b49a5da8d0cffcb48d83294354ba3)
+
+231.	[func]*		vorner
+	The logging interface changed slightly. We use
+	logger.foo(MESSAGE_ID).arg(bar); instead of logger.foo(MESSAGE_ID,
+	bar); internally. The message definitions use '%1,%2,...'
+	instead of '%s,%d', which allows us to cope better with
+	mismatched placeholders and allows reordering of them in
+	case of translation.
+	(Trac901, git 4903410e45670b30d7283f5d69dc28c2069237d6)
+
+230.	[bug]		naokikambe
+	Removed too repeated verbose messages in two cases of:
+	 - when auth sends statistics data to stats
+	 - when stats receives statistics data from other modules
+	(Trac#620, git 0ecb807011196eac01f281d40bc7c9d44565b364)
+
+229.	[doc]		jreed
+	Add manual page for b10-host.
+	(git a437d4e26b81bb07181ff35a625c540703eee845)
+
+228.	[func]*		jreed
+	The host tool is renamed to b10-host. While the utility is
+	a work in progress, it is expected to now be shipped with
+	tarballs. Its initial goal was to be a host(1) clone,
+	rewritten in C++ from scratch and using BIND 10's libdns++.
+	It now supports the -a (any), -c class, -d (verbose) switches
+	and has improved output.
+	(Trac #872, git d846851699d5c76937533adf9ff9d948dfd593ca)
+
+227.	[build]		jreed
+	Add missing libdns++ rdata files for the distribution (this
+	fixes distcheck error). Change three generated libdns++
+	headers to "nodist" so they aren't included in the distribution
+	(they were mistakenly included in last tarball).
+
+226.	[func]*		jelte
+	Introduced an API for cryptographic operations. Currently it only
+	supports HMAC, intended for use with TSIG. The current
+	implementation uses Botan as the backend library.
+	This introduces a new dependency, on Botan.  Currently only Botan
+	1.8.x works; older or newer versions don't.
+	(Trac #781, git 9df42279a47eb617f586144dce8cce680598558a)
+
+225.	[func]		naokikambe
+	Added the HTTP/XML interface(b10-stats-httpd) to the
+	statistics feature in BIND 10. b10-stats-httpd is a standalone
+	HTTP server and it requests statistics data to the stats
+	daemon(b10-stats) and sends it to HTTP clients in XML
+	format. Items of the data collected via b10-stats-httpd
+	are almost equivalent to ones which are collected via
+	bindctl. Since it also can send XSL(Extensible Stylessheet
+	Language) document and XSD(XML Schema definition) document,
+	XML document is human-friendly to view through web browsers
+	and its data types are strictly defined.
+	(Trac #547, git 1cbd51919237a6e65983be46e4f5a63d1877b1d3)
+
+224.	[bug]		jinmei
+	b10-auth, src/lib/datasrc: inconsistency between the hot spot
+	cache and actual data source could cause a crash while query
+	processing.  The crash could happen, e.g., when an sqlite3 DB file
+	is being updated after a zone transfer while b10-auth handles a
+	query using the corresponding sqlite3 data source.
+	(Trac #851, git 2463b96680bb3e9a76e50c38a4d7f1d38d810643)
+
+223.	[bug]		feng
+	If ip address or port isn't usable for name server, name
+	server process won't exist and give end user chance to
+	reconfigure them.
+	(Trac #775, git 572ac2cf62e18f7eb69d670b890e2a3443bfd6e7)
+
+222.	[bug]		jerry
 	src/lib/zonemgr: Fix a bug that xfrin not checking for new copy of
 	zone on startup.  Imposes some random jitters to avoid many zones
 	need to do refresh at the same time.
@@ -13,7 +135,7 @@
 	(potentially) bad packets to a nameserver and prints the responses.
 	(Trac #703, git 1b666838b6c0fe265522b30971e878d9f0d21fde)
 
-219.    [func]          ocean
+219.	[func]		ocean
 	src/lib: move some dns related code out of asiolink library to
 	asiodns library
 	(Trac #751, git 262ac6c6fc61224d54705ed4c700dadb606fcb1c)
@@ -23,9 +145,9 @@
 	(Trac #806, git 4e47d5f6b692c63c907af6681a75024450884a88)
 
 217.	[bug]		jerry
-	src/lib/dns/python: Use a signed version of larger size of integer and
-	perform more strict range checks with PyArg_ParseTuple() in case of
-	overflows.
+	src/lib/dns/python: Use a signed version of larger size of
+	integer and perform more strict range checks with
+	PyArg_ParseTuple() in case of overflows.
 	(Trac #363, git ce281e646be9f0f273229d94ccd75bf7e08d17cf)
 
 216.	[func]		vorner
@@ -1047,7 +1169,7 @@ bind10-devel-20100701 released on July 1, 2010
 55.	[bug]		shane
 	bin/xfrout: xfrout exception on Ctrl-C now no longer generates
 	exception for 'Interrupted system call'
-	(Track #136, svn r2147)
+	(Trac #136, svn r2147)
 
 54.	[bug]		zhanglikun
 	bin/xfrout: Enable b10-xfrout can be launched in source

+ 273 - 177
Makefile.am

@@ -84,214 +84,310 @@ systest:
 
 #### include external sources in the distributed tarball:
 EXTRA_DIST = ext/asio/README
-EXTRA_DIST += ext/asio/asio/local/stream_protocol.hpp
-EXTRA_DIST += ext/asio/asio/local/basic_endpoint.hpp
-EXTRA_DIST += ext/asio/asio/local/datagram_protocol.hpp
-EXTRA_DIST += ext/asio/asio/local/connect_pair.hpp
-EXTRA_DIST += ext/asio/asio/windows/basic_handle.hpp
-EXTRA_DIST += ext/asio/asio/windows/random_access_handle.hpp
-EXTRA_DIST += ext/asio/asio/windows/random_access_handle_service.hpp
-EXTRA_DIST += ext/asio/asio/windows/basic_random_access_handle.hpp
-EXTRA_DIST += ext/asio/asio/windows/overlapped_ptr.hpp
-EXTRA_DIST += ext/asio/asio/windows/stream_handle.hpp
-EXTRA_DIST += ext/asio/asio/windows/stream_handle_service.hpp
-EXTRA_DIST += ext/asio/asio/windows/basic_stream_handle.hpp
-EXTRA_DIST += ext/asio/asio/impl/write.ipp
-EXTRA_DIST += ext/asio/asio/impl/read.ipp
-EXTRA_DIST += ext/asio/asio/impl/serial_port_base.ipp
-EXTRA_DIST += ext/asio/asio/impl/write_at.ipp
-EXTRA_DIST += ext/asio/asio/impl/read_at.ipp
-EXTRA_DIST += ext/asio/asio/impl/error_code.ipp
-EXTRA_DIST += ext/asio/asio/impl/read_until.ipp
-EXTRA_DIST += ext/asio/asio/impl/io_service.ipp
-EXTRA_DIST += ext/asio/asio/detail/win_iocp_serial_port_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/reactive_socket_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/wince_thread.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_event.hpp
-EXTRA_DIST += ext/asio/asio/detail/descriptor_ops.hpp
-EXTRA_DIST += ext/asio/asio/detail/pipe_select_interrupter.hpp
-EXTRA_DIST += ext/asio/asio/detail/task_io_service_fwd.hpp
-EXTRA_DIST += ext/asio/asio/detail/handler_alloc_helpers.hpp
-EXTRA_DIST += ext/asio/asio/detail/pop_options.hpp
-EXTRA_DIST += ext/asio/asio/detail/strand_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/buffer_resize_guard.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_iocp_io_service_fwd.hpp
-EXTRA_DIST += ext/asio/asio/detail/timer_scheduler.hpp
-EXTRA_DIST += ext/asio/asio/detail/kqueue_reactor_fwd.hpp
-EXTRA_DIST += ext/asio/asio/detail/hash_map.hpp
-EXTRA_DIST += ext/asio/asio/detail/event.hpp
-EXTRA_DIST += ext/asio/asio/detail/buffered_stream_storage.hpp
-EXTRA_DIST += ext/asio/asio/detail/posix_mutex.hpp
-EXTRA_DIST += ext/asio/asio/detail/timer_queue_fwd.hpp
-EXTRA_DIST += ext/asio/asio/detail/deadline_timer_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/posix_fd_set_adapter.hpp
-EXTRA_DIST += ext/asio/asio/detail/service_registry.hpp
+EXTRA_DIST += ext/asio/README
+EXTRA_DIST += ext/asio/asio.hpp
+EXTRA_DIST += ext/asio/asio/basic_socket.hpp
+EXTRA_DIST += ext/asio/asio/streambuf.hpp
+EXTRA_DIST += ext/asio/asio/thread.hpp
+EXTRA_DIST += ext/asio/asio/detail/wait_handler.hpp
+EXTRA_DIST += ext/asio/asio/detail/resolve_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/gcc_hppa_fenced_block.hpp
 EXTRA_DIST += ext/asio/asio/detail/null_fenced_block.hpp
+EXTRA_DIST += ext/asio/asio/detail/noncopyable.hpp
+EXTRA_DIST += ext/asio/asio/detail/eventfd_select_interrupter.hpp
 EXTRA_DIST += ext/asio/asio/detail/task_io_service_operation.hpp
-EXTRA_DIST += ext/asio/asio/detail/epoll_reactor.hpp
+EXTRA_DIST += ext/asio/asio/detail/service_base.hpp
+EXTRA_DIST += ext/asio/asio/detail/task_io_service_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/null_buffers_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_handle_write_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/thread.hpp
+EXTRA_DIST += ext/asio/asio/detail/select_reactor_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/event.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_descriptor_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_overlapped_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_socket_recv_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/macos_fenced_block.hpp
+EXTRA_DIST += ext/asio/asio/detail/dev_poll_reactor_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_socket_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/posix_tss_ptr.hpp
 EXTRA_DIST += ext/asio/asio/detail/local_free_on_block_exit.hpp
-EXTRA_DIST += ext/asio/asio/detail/socket_select_interrupter.hpp
-EXTRA_DIST += ext/asio/asio/detail/null_mutex.hpp
-EXTRA_DIST += ext/asio/asio/detail/reactor_op.hpp
-EXTRA_DIST += ext/asio/asio/detail/fenced_block.hpp
-EXTRA_DIST += ext/asio/asio/detail/tss_ptr.hpp
-EXTRA_DIST += ext/asio/asio/detail/timer_queue_set.hpp
-EXTRA_DIST += ext/asio/asio/detail/winsock_init.hpp
-EXTRA_DIST += ext/asio/asio/detail/signal_init.hpp
-EXTRA_DIST += ext/asio/asio/detail/call_stack.hpp
-EXTRA_DIST += ext/asio/asio/detail/operation.hpp
-EXTRA_DIST += ext/asio/asio/detail/posix_signal_blocker.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_iocp_handle_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/fd_set_adapter.hpp
-EXTRA_DIST += ext/asio/asio/detail/io_control.hpp
-EXTRA_DIST += ext/asio/asio/detail/null_signal_blocker.hpp
-EXTRA_DIST += ext/asio/asio/detail/socket_ops.hpp
-EXTRA_DIST += ext/asio/asio/detail/bind_handler.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_iocp_overlapped_ptr.hpp
-EXTRA_DIST += ext/asio/asio/detail/timer_scheduler_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/timer_scheduler.hpp
 EXTRA_DIST += ext/asio/asio/detail/signal_blocker.hpp
-EXTRA_DIST += ext/asio/asio/detail/consuming_buffers.hpp
-EXTRA_DIST += ext/asio/asio/detail/socket_option.hpp
-EXTRA_DIST += ext/asio/asio/detail/reactor.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_fd_set_adapter.hpp
-EXTRA_DIST += ext/asio/asio/detail/select_interrupter.hpp
-EXTRA_DIST += ext/asio/asio/detail/null_buffers_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/resolver_service_base.hpp
 EXTRA_DIST += ext/asio/asio/detail/socket_holder.hpp
-EXTRA_DIST += ext/asio/asio/detail/scoped_lock.hpp
-EXTRA_DIST += ext/asio/asio/detail/service_registry_fwd.hpp
-EXTRA_DIST += ext/asio/asio/detail/base_from_completion_cond.hpp
-EXTRA_DIST += ext/asio/asio/detail/posix_thread.hpp
-EXTRA_DIST += ext/asio/asio/detail/solaris_fenced_block.hpp
-EXTRA_DIST += ext/asio/asio/detail/epoll_reactor_fwd.hpp
-EXTRA_DIST += ext/asio/asio/detail/push_options.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_signal_blocker.hpp
-EXTRA_DIST += ext/asio/asio/detail/eventfd_select_interrupter.hpp
+EXTRA_DIST += ext/asio/asio/detail/dev_poll_reactor.hpp
 EXTRA_DIST += ext/asio/asio/detail/select_reactor.hpp
-EXTRA_DIST += ext/asio/asio/detail/old_win_sdk_compat.hpp
+EXTRA_DIST += ext/asio/asio/detail/gcc_arm_fenced_block.hpp
+EXTRA_DIST += ext/asio/asio/detail/consuming_buffers.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactor_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/base_from_completion_cond.hpp
+EXTRA_DIST += ext/asio/asio/detail/epoll_reactor.hpp
+EXTRA_DIST += ext/asio/asio/detail/bind_handler.hpp
+EXTRA_DIST += ext/asio/asio/detail/strand_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/op_queue.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_mutex.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_operation.hpp
+EXTRA_DIST += ext/asio/asio/detail/pipe_select_interrupter.hpp
+EXTRA_DIST += ext/asio/asio/detail/wince_thread.hpp
+EXTRA_DIST += ext/asio/asio/detail/buffered_stream_storage.hpp
+EXTRA_DIST += ext/asio/asio/detail/mutex.hpp
+EXTRA_DIST += ext/asio/asio/detail/posix_mutex.hpp
 EXTRA_DIST += ext/asio/asio/detail/reactor_op_queue.hpp
-EXTRA_DIST += ext/asio/asio/detail/null_thread.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_event.hpp
+EXTRA_DIST += ext/asio/asio/detail/select_interrupter.hpp
+EXTRA_DIST += ext/asio/asio/detail/io_control.hpp
 EXTRA_DIST += ext/asio/asio/detail/buffer_sequence_adapter.hpp
-EXTRA_DIST += ext/asio/asio/detail/posix_event.hpp
-EXTRA_DIST += ext/asio/asio/detail/thread.hpp
-EXTRA_DIST += ext/asio/asio/detail/handler_invoke_helpers.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_io_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_handle_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_send_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/epoll_reactor_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/operation.hpp
+EXTRA_DIST += ext/asio/asio/detail/descriptor_ops.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactor.hpp
+EXTRA_DIST += ext/asio/asio/detail/shared_ptr.hpp
+EXTRA_DIST += ext/asio/asio/detail/winsock_init.hpp
+EXTRA_DIST += ext/asio/asio/detail/timer_queue_set.hpp
+EXTRA_DIST += ext/asio/asio/detail/completion_handler.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_serial_port_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/fenced_block.hpp
 EXTRA_DIST += ext/asio/asio/detail/null_event.hpp
+EXTRA_DIST += ext/asio/asio/detail/hash_map.hpp
+EXTRA_DIST += ext/asio/asio/detail/gcc_sync_fenced_block.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_tss_ptr.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_fd_set_adapter.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_null_buffers_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/timer_queue_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/old_win_sdk_compat.hpp
+EXTRA_DIST += ext/asio/asio/detail/call_stack.hpp
+EXTRA_DIST += ext/asio/asio/detail/weak_ptr.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_accept_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/gcc_x86_fenced_block.hpp
+EXTRA_DIST += ext/asio/asio/detail/gcc_fenced_block.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/null_mutex.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_socket_recvfrom_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/posix_event.hpp
 EXTRA_DIST += ext/asio/asio/detail/service_id.hpp
-EXTRA_DIST += ext/asio/asio/detail/socket_types.hpp
+EXTRA_DIST += ext/asio/asio/detail/kqueue_reactor.hpp
+EXTRA_DIST += ext/asio/asio/detail/regex_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_socket_sendto_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/push_options.hpp
+EXTRA_DIST += ext/asio/asio/detail/null_thread.hpp
+EXTRA_DIST += ext/asio/asio/detail/socket_select_interrupter.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_service_base.hpp
 EXTRA_DIST += ext/asio/asio/detail/throw_error.hpp
-EXTRA_DIST += ext/asio/asio/detail/timer_op.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_mutex.hpp
-EXTRA_DIST += ext/asio/asio/detail/reactive_descriptor_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/resolver_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/op_queue.hpp
-EXTRA_DIST += ext/asio/asio/detail/dev_poll_reactor.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_thread.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_iocp_operation.hpp
-EXTRA_DIST += ext/asio/asio/detail/service_base.hpp
-EXTRA_DIST += ext/asio/asio/detail/select_reactor_fwd.hpp
-EXTRA_DIST += ext/asio/asio/detail/reactor_fwd.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/null_signal_blocker.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_socket_accept_op.hpp
 EXTRA_DIST += ext/asio/asio/detail/wrapped_handler.hpp
-EXTRA_DIST += ext/asio/asio/detail/mutex.hpp
-EXTRA_DIST += ext/asio/asio/detail/completion_handler.hpp
-EXTRA_DIST += ext/asio/asio/detail/noncopyable.hpp
-EXTRA_DIST += ext/asio/asio/detail/task_io_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/gcc_fenced_block.hpp
+EXTRA_DIST += ext/asio/asio/detail/object_pool.hpp
+EXTRA_DIST += ext/asio/asio/detail/timer_scheduler_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/resolve_endpoint_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/array_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/config.hpp
+EXTRA_DIST += ext/asio/asio/detail/socket_option.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_overlapped_ptr.hpp
 EXTRA_DIST += ext/asio/asio/detail/win_fenced_block.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_tss_ptr.hpp
-EXTRA_DIST += ext/asio/asio/detail/kqueue_reactor.hpp
+EXTRA_DIST += ext/asio/asio/detail/socket_types.hpp
+EXTRA_DIST += ext/asio/asio/detail/null_tss_ptr.hpp
+EXTRA_DIST += ext/asio/asio/detail/handler_invoke_helpers.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_socket_send_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_null_buffers_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/pop_options.hpp
+EXTRA_DIST += ext/asio/asio/detail/resolver_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_socket_service_base.hpp
+EXTRA_DIST += ext/asio/asio/detail/descriptor_read_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactive_socket_connect_op.hpp
 EXTRA_DIST += ext/asio/asio/detail/timer_queue_base.hpp
-EXTRA_DIST += ext/asio/asio/detail/win_iocp_io_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/gcc_x86_fenced_block.hpp
-EXTRA_DIST += ext/asio/asio/detail/posix_tss_ptr.hpp
-EXTRA_DIST += ext/asio/asio/detail/macos_fenced_block.hpp
-EXTRA_DIST += ext/asio/asio/detail/dev_poll_reactor_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/reactor_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_recvfrom_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_serial_port_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/tss_ptr.hpp
+EXTRA_DIST += ext/asio/asio/detail/buffer_resize_guard.hpp
+EXTRA_DIST += ext/asio/asio/detail/kqueue_reactor_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_thread.hpp
+EXTRA_DIST += ext/asio/asio/detail/deadline_timer_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_recv_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/timer_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/posix_thread.hpp
+EXTRA_DIST += ext/asio/asio/detail/signal_init.hpp
+EXTRA_DIST += ext/asio/asio/detail/descriptor_write_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_signal_blocker.hpp
+EXTRA_DIST += ext/asio/asio/detail/impl/reactive_socket_service_base.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/win_mutex.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/posix_event.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/win_iocp_io_service.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/select_reactor.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/posix_tss_ptr.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/task_io_service.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/dev_poll_reactor.hpp
+EXTRA_DIST += ext/asio/asio/detail/impl/select_reactor.hpp
+EXTRA_DIST += ext/asio/asio/detail/impl/eventfd_select_interrupter.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/epoll_reactor.hpp
+EXTRA_DIST += ext/asio/asio/detail/impl/strand_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/impl/winsock_init.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/pipe_select_interrupter.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/win_iocp_serial_port_service.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/dev_poll_reactor.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/win_iocp_io_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/impl/strand_service.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/win_iocp_socket_service_base.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/timer_queue.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/posix_mutex.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/reactive_serial_port_service.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/socket_ops.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/socket_select_interrupter.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/posix_thread.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/reactive_descriptor_service.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/kqueue_reactor.hpp
+EXTRA_DIST += ext/asio/asio/detail/impl/kqueue_reactor.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/win_event.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/timer_queue_set.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/win_tss_ptr.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/win_iocp_handle_service.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/resolver_service_base.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/win_thread.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/task_io_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/impl/throw_error.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/epoll_reactor.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/service_registry.hpp
+EXTRA_DIST += ext/asio/asio/detail/impl/descriptor_ops.ipp
+EXTRA_DIST += ext/asio/asio/detail/impl/service_registry.ipp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_io_service_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/fd_set_adapter.hpp
+EXTRA_DIST += ext/asio/asio/detail/task_io_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/solaris_fenced_block.hpp
 EXTRA_DIST += ext/asio/asio/detail/timer_queue.hpp
-EXTRA_DIST += ext/asio/asio/detail/reactive_serial_port_service.hpp
-EXTRA_DIST += ext/asio/asio/detail/null_tss_ptr.hpp
-EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_stream_service.hpp
-EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_operation.hpp
-EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_init.hpp
-EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_context_service.hpp
-EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_types.hpp
-EXTRA_DIST += ext/asio/asio/ssl/stream.hpp
-EXTRA_DIST += ext/asio/asio/ssl/stream_service.hpp
+EXTRA_DIST += ext/asio/asio/detail/handler_alloc_helpers.hpp
+EXTRA_DIST += ext/asio/asio/detail/scoped_lock.hpp
+EXTRA_DIST += ext/asio/asio/detail/win_iocp_handle_read_op.hpp
+EXTRA_DIST += ext/asio/asio/detail/service_registry_fwd.hpp
+EXTRA_DIST += ext/asio/asio/detail/service_registry.hpp
+EXTRA_DIST += ext/asio/asio/detail/posix_fd_set_adapter.hpp
+EXTRA_DIST += ext/asio/asio/detail/socket_ops.hpp
+EXTRA_DIST += ext/asio/asio/detail/posix_signal_blocker.hpp
+EXTRA_DIST += ext/asio/asio/serial_port_base.hpp
 EXTRA_DIST += ext/asio/asio/ssl/context_base.hpp
 EXTRA_DIST += ext/asio/asio/ssl/context.hpp
 EXTRA_DIST += ext/asio/asio/ssl/context_service.hpp
+EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_types.hpp
+EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_context_service.hpp
+EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_stream_service.hpp
+EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_operation.hpp
+EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_init.hpp
 EXTRA_DIST += ext/asio/asio/ssl/basic_context.hpp
+EXTRA_DIST += ext/asio/asio/ssl/stream_service.hpp
+EXTRA_DIST += ext/asio/asio/ssl/stream.hpp
 EXTRA_DIST += ext/asio/asio/ssl/stream_base.hpp
-EXTRA_DIST += ext/asio/asio/posix/stream_descriptor.hpp
-EXTRA_DIST += ext/asio/asio/posix/stream_descriptor_service.hpp
+EXTRA_DIST += ext/asio/asio/basic_streambuf.hpp
+EXTRA_DIST += ext/asio/asio/serial_port_service.hpp
+EXTRA_DIST += ext/asio/asio/error.hpp
+EXTRA_DIST += ext/asio/asio/handler_alloc_hook.hpp
+EXTRA_DIST += ext/asio/asio/buffers_iterator.hpp
+EXTRA_DIST += ext/asio/asio/is_read_buffered.hpp
+EXTRA_DIST += ext/asio/asio/buffered_stream_fwd.hpp
+EXTRA_DIST += ext/asio/asio/placeholders.hpp
+EXTRA_DIST += ext/asio/asio/local/stream_protocol.hpp
+EXTRA_DIST += ext/asio/asio/local/detail/impl/endpoint.ipp
+EXTRA_DIST += ext/asio/asio/local/detail/endpoint.hpp
+EXTRA_DIST += ext/asio/asio/local/datagram_protocol.hpp
+EXTRA_DIST += ext/asio/asio/local/connect_pair.hpp
+EXTRA_DIST += ext/asio/asio/local/basic_endpoint.hpp
+EXTRA_DIST += ext/asio/asio/buffered_stream.hpp
+EXTRA_DIST += ext/asio/asio/basic_serial_port.hpp
+EXTRA_DIST += ext/asio/asio/datagram_socket_service.hpp
+EXTRA_DIST += ext/asio/asio/socket_base.hpp
+EXTRA_DIST += ext/asio/asio/io_service.hpp
+EXTRA_DIST += ext/asio/asio/ssl.hpp
+EXTRA_DIST += ext/asio/asio/basic_socket_iostream.hpp
+EXTRA_DIST += ext/asio/asio/basic_io_object.hpp
+EXTRA_DIST += ext/asio/asio/basic_socket_streambuf.hpp
+EXTRA_DIST += ext/asio/asio/error_code.hpp
+EXTRA_DIST += ext/asio/asio/basic_stream_socket.hpp
+EXTRA_DIST += ext/asio/asio/read_until.hpp
+EXTRA_DIST += ext/asio/asio/basic_streambuf_fwd.hpp
+EXTRA_DIST += ext/asio/asio/is_write_buffered.hpp
+EXTRA_DIST += ext/asio/asio/basic_datagram_socket.hpp
+EXTRA_DIST += ext/asio/asio/buffered_write_stream_fwd.hpp
+EXTRA_DIST += ext/asio/asio/basic_deadline_timer.hpp
+EXTRA_DIST += ext/asio/asio/socket_acceptor_service.hpp
+EXTRA_DIST += ext/asio/asio/raw_socket_service.hpp
+EXTRA_DIST += ext/asio/asio/buffered_read_stream.hpp
+EXTRA_DIST += ext/asio/asio/time_traits.hpp
+EXTRA_DIST += ext/asio/asio/completion_condition.hpp
 EXTRA_DIST += ext/asio/asio/posix/basic_stream_descriptor.hpp
 EXTRA_DIST += ext/asio/asio/posix/basic_descriptor.hpp
 EXTRA_DIST += ext/asio/asio/posix/descriptor_base.hpp
+EXTRA_DIST += ext/asio/asio/posix/stream_descriptor_service.hpp
+EXTRA_DIST += ext/asio/asio/posix/stream_descriptor.hpp
+EXTRA_DIST += ext/asio/asio/write.hpp
+EXTRA_DIST += ext/asio/asio/write_at.hpp
+EXTRA_DIST += ext/asio/asio/basic_raw_socket.hpp
+EXTRA_DIST += ext/asio/asio/serial_port.hpp
+EXTRA_DIST += ext/asio/asio/windows/basic_stream_handle.hpp
+EXTRA_DIST += ext/asio/asio/windows/basic_handle.hpp
+EXTRA_DIST += ext/asio/asio/windows/random_access_handle.hpp
+EXTRA_DIST += ext/asio/asio/windows/overlapped_ptr.hpp
+EXTRA_DIST += ext/asio/asio/windows/stream_handle.hpp
+EXTRA_DIST += ext/asio/asio/windows/random_access_handle_service.hpp
+EXTRA_DIST += ext/asio/asio/windows/stream_handle_service.hpp
+EXTRA_DIST += ext/asio/asio/windows/basic_random_access_handle.hpp
+EXTRA_DIST += ext/asio/asio/read.hpp
+EXTRA_DIST += ext/asio/asio/deadline_timer_service.hpp
+EXTRA_DIST += ext/asio/asio/buffered_write_stream.hpp
+EXTRA_DIST += ext/asio/asio/buffer.hpp
+EXTRA_DIST += ext/asio/asio/impl/read_until.ipp
+EXTRA_DIST += ext/asio/asio/impl/serial_port_base.hpp
+EXTRA_DIST += ext/asio/asio/impl/read_at.ipp
+EXTRA_DIST += ext/asio/asio/impl/read.ipp
+EXTRA_DIST += ext/asio/asio/impl/error.ipp
+EXTRA_DIST += ext/asio/asio/impl/io_service.ipp
+EXTRA_DIST += ext/asio/asio/impl/io_service.hpp
+EXTRA_DIST += ext/asio/asio/impl/src.hpp
+EXTRA_DIST += ext/asio/asio/impl/src.cpp
+EXTRA_DIST += ext/asio/asio/impl/read_until.hpp
+EXTRA_DIST += ext/asio/asio/impl/serial_port_base.ipp
+EXTRA_DIST += ext/asio/asio/impl/write.hpp
+EXTRA_DIST += ext/asio/asio/impl/write_at.hpp
+EXTRA_DIST += ext/asio/asio/impl/write.ipp
+EXTRA_DIST += ext/asio/asio/impl/read.hpp
+EXTRA_DIST += ext/asio/asio/impl/write_at.ipp
+EXTRA_DIST += ext/asio/asio/impl/error_code.ipp
+EXTRA_DIST += ext/asio/asio/impl/read_at.hpp
+EXTRA_DIST += ext/asio/asio/strand.hpp
+EXTRA_DIST += ext/asio/asio/version.hpp
+EXTRA_DIST += ext/asio/asio/basic_socket_acceptor.hpp
+EXTRA_DIST += ext/asio/asio/ip/basic_resolver_query.hpp
+EXTRA_DIST += ext/asio/asio/ip/address.hpp
+EXTRA_DIST += ext/asio/asio/ip/host_name.hpp
 EXTRA_DIST += ext/asio/asio/ip/detail/socket_option.hpp
+EXTRA_DIST += ext/asio/asio/ip/detail/impl/endpoint.ipp
+EXTRA_DIST += ext/asio/asio/ip/detail/endpoint.hpp
+EXTRA_DIST += ext/asio/asio/ip/udp.hpp
+EXTRA_DIST += ext/asio/asio/ip/basic_resolver_iterator.hpp
 EXTRA_DIST += ext/asio/asio/ip/v6_only.hpp
 EXTRA_DIST += ext/asio/asio/ip/address_v4.hpp
-EXTRA_DIST += ext/asio/asio/ip/address_v6.hpp
-EXTRA_DIST += ext/asio/asio/ip/basic_resolver.hpp
+EXTRA_DIST += ext/asio/asio/ip/resolver_query_base.hpp
 EXTRA_DIST += ext/asio/asio/ip/multicast.hpp
+EXTRA_DIST += ext/asio/asio/ip/address_v6.hpp
+EXTRA_DIST += ext/asio/asio/ip/tcp.hpp
+EXTRA_DIST += ext/asio/asio/ip/basic_resolver_entry.hpp
 EXTRA_DIST += ext/asio/asio/ip/unicast.hpp
-EXTRA_DIST += ext/asio/asio/ip/basic_resolver_iterator.hpp
-EXTRA_DIST += ext/asio/asio/ip/host_name.hpp
-EXTRA_DIST += ext/asio/asio/ip/resolver_query_base.hpp
-EXTRA_DIST += ext/asio/asio/ip/basic_endpoint.hpp
 EXTRA_DIST += ext/asio/asio/ip/resolver_service.hpp
-EXTRA_DIST += ext/asio/asio/ip/basic_resolver_entry.hpp
-EXTRA_DIST += ext/asio/asio/ip/address.hpp
-EXTRA_DIST += ext/asio/asio/ip/tcp.hpp
-EXTRA_DIST += ext/asio/asio/ip/basic_resolver_query.hpp
-EXTRA_DIST += ext/asio/asio/ip/udp.hpp
 EXTRA_DIST += ext/asio/asio/ip/icmp.hpp
-EXTRA_DIST += ext/asio/asio/error.hpp
-EXTRA_DIST += ext/asio/asio/basic_socket.hpp
-EXTRA_DIST += ext/asio/asio/buffered_stream.hpp
-EXTRA_DIST += ext/asio/asio/system_error.hpp
-EXTRA_DIST += ext/asio/asio/basic_io_object.hpp
-EXTRA_DIST += ext/asio/asio/read_at.hpp
-EXTRA_DIST += ext/asio/asio/basic_raw_socket.hpp
-EXTRA_DIST += ext/asio/asio/serial_port_service.hpp
-EXTRA_DIST += ext/asio/asio/basic_stream_socket.hpp
-EXTRA_DIST += ext/asio/asio/placeholders.hpp
-EXTRA_DIST += ext/asio/asio/basic_deadline_timer.hpp
-EXTRA_DIST += ext/asio/asio/thread.hpp
-EXTRA_DIST += ext/asio/asio/buffered_write_stream_fwd.hpp
-EXTRA_DIST += ext/asio/asio/datagram_socket_service.hpp
+EXTRA_DIST += ext/asio/asio/ip/basic_endpoint.hpp
+EXTRA_DIST += ext/asio/asio/ip/basic_resolver.hpp
+EXTRA_DIST += ext/asio/asio/ip/impl/address.hpp
+EXTRA_DIST += ext/asio/asio/ip/impl/address_v4.hpp
+EXTRA_DIST += ext/asio/asio/ip/impl/address_v4.ipp
+EXTRA_DIST += ext/asio/asio/ip/impl/address_v6.hpp
+EXTRA_DIST += ext/asio/asio/ip/impl/address.ipp
+EXTRA_DIST += ext/asio/asio/ip/impl/host_name.ipp
+EXTRA_DIST += ext/asio/asio/ip/impl/basic_endpoint.hpp
+EXTRA_DIST += ext/asio/asio/ip/impl/address_v6.ipp
 EXTRA_DIST += ext/asio/asio/handler_invoke_hook.hpp
-EXTRA_DIST += ext/asio/asio/is_read_buffered.hpp
-EXTRA_DIST += ext/asio/asio/buffer.hpp
-EXTRA_DIST += ext/asio/asio/basic_socket_acceptor.hpp
-EXTRA_DIST += ext/asio/asio/write_at.hpp
-EXTRA_DIST += ext/asio/asio/completion_condition.hpp
-EXTRA_DIST += ext/asio/asio/raw_socket_service.hpp
-EXTRA_DIST += ext/asio/asio/socket_base.hpp
-EXTRA_DIST += ext/asio/asio/serial_port.hpp
-EXTRA_DIST += ext/asio/asio/error_code.hpp
-EXTRA_DIST += ext/asio/asio/basic_serial_port.hpp
-EXTRA_DIST += ext/asio/asio/version.hpp
-EXTRA_DIST += ext/asio/asio/deadline_timer_service.hpp
-EXTRA_DIST += ext/asio/asio/io_service.hpp
-EXTRA_DIST += ext/asio/asio/buffered_read_stream.hpp
-EXTRA_DIST += ext/asio/asio/streambuf.hpp
-EXTRA_DIST += ext/asio/asio/basic_datagram_socket.hpp
-EXTRA_DIST += ext/asio/asio/basic_streambuf.hpp
-EXTRA_DIST += ext/asio/asio/write.hpp
-EXTRA_DIST += ext/asio/asio/strand.hpp
-EXTRA_DIST += ext/asio/asio/basic_socket_iostream.hpp
-EXTRA_DIST += ext/asio/asio/buffered_stream_fwd.hpp
-EXTRA_DIST += ext/asio/asio/basic_socket_streambuf.hpp
-EXTRA_DIST += ext/asio/asio/ssl.hpp
+EXTRA_DIST += ext/asio/asio/read_at.hpp
+EXTRA_DIST += ext/asio/asio/buffered_read_stream_fwd.hpp
+EXTRA_DIST += ext/asio/asio/system_error.hpp
 EXTRA_DIST += ext/asio/asio/deadline_timer.hpp
-EXTRA_DIST += ext/asio/asio/buffers_iterator.hpp
-EXTRA_DIST += ext/asio/asio/handler_alloc_hook.hpp
-EXTRA_DIST += ext/asio/asio/buffered_write_stream.hpp
-EXTRA_DIST += ext/asio/asio/read.hpp
-EXTRA_DIST += ext/asio/asio/serial_port_base.hpp
 EXTRA_DIST += ext/asio/asio/stream_socket_service.hpp
-EXTRA_DIST += ext/asio/asio/time_traits.hpp
-EXTRA_DIST += ext/asio/asio/read_until.hpp
-EXTRA_DIST += ext/asio/asio/is_write_buffered.hpp
-EXTRA_DIST += ext/asio/asio/buffered_read_stream_fwd.hpp
-EXTRA_DIST += ext/asio/asio/socket_acceptor_service.hpp
-EXTRA_DIST += ext/asio/asio.hpp
 EXTRA_DIST += ext/coroutine/coroutine.h

+ 94 - 13
configure.ac

@@ -374,6 +374,79 @@ if test "$lcov" != "no"; then
 fi
 AC_SUBST(USE_LCOV)
 
+# Check for Botan
+botan_path="yes"
+AC_ARG_WITH([botan],
+  AC_HELP_STRING([--with-botan=PATH],
+    [specify exact directory of Botan library]),
+    [botan_path="$withval"])
+if test "${botan_path}" == "no" ; then
+    AC_MSG_ERROR([Need botan for libcryptolink])
+fi
+if test "${botan_path}" != "yes" ; then
+    if test -x "${botan_path}/bin/botan-config" ; then
+        BOTAN_CONFIG="${botan_path}/bin/botan-config"
+    else
+        AC_MSG_ERROR([${botan_path}/bin/botan-config not found])
+    fi
+else
+        AC_PATH_PROG([BOTAN_CONFIG], [botan-config])
+fi
+
+if test -x "${BOTAN_CONFIG}" ; then
+    BOTAN_LDFLAGS=`${BOTAN_CONFIG} --libs`
+    # We expect botan-config --libs to contain -L<path_to_libbotan>, but
+    # this is not always the case.  As a heuristics workaround we add
+    # -L`botan-config --prefix/lib` in this case.  Same for BOTAN_INCLUDES
+    # (but using include instead of lib) below.
+    echo ${BOTAN_LDFLAGS} | grep -- -L > /dev/null || \
+	    BOTAN_LDFLAGS="-L`${BOTAN_CONFIG} --prefix`/lib ${BOTAN_LDFLAGS}"
+    BOTAN_INCLUDES=`${BOTAN_CONFIG} --cflags`
+    echo ${BOTAN_INCLUDES} | grep -- -I > /dev/null || \
+	    BOTAN_INCLUDES="-I`${BOTAN_CONFIG} --prefix`/include ${BOTAN_INCLUDES}"
+    # See python_rpath for some info on why we do this
+    if test $rpath_available = yes; then
+        BOTAN_RPATH=
+        for flag in ${BOTAN_LDFLAGS}; do
+                BOTAN_RPATH="${BOTAN_RPATH} `echo $flag | sed -ne 's/^\(\-L\)/-R/p'`"
+        done
+	AC_SUBST(BOTAN_RPATH)
+
+	# According to the libtool manual, it should be sufficient if we
+	# specify the "-R libdir" in our wrapper library of botan (no other
+	# programs will need libbotan directly); "libdir" should be added to
+	# the program's binary image.  But we've seen in our build environments
+	# that (some versions of?) libtool doesn't propagate -R as documented,
+	# and it caused a linker error at run time.  To work around this, we
+	# also add the rpath to the global LDFLAGS.
+        LDFLAGS="$BOTAN_RPATH $LDFLAGS"
+    fi
+
+    AC_SUBST(BOTAN_LDFLAGS)
+    AC_SUBST(BOTAN_INCLUDES)
+fi
+
+CPPFLAGS_SAVED=$CPPFLAGS
+CPPFLAGS="$BOTAN_INCLUDES $CPPFLAGS"
+LDFLAGS_SAVED="$LDFLAGS"
+LDFLAGS="$BOTAN_LDFLAGS $LDFLAGS"
+
+AC_CHECK_HEADERS([botan/botan.h],,AC_MSG_ERROR([Missing required header files.]))
+AC_LINK_IFELSE(
+        [AC_LANG_PROGRAM([#include <botan/botan.h>
+                          #include <botan/hash.h>
+                         ],
+                         [using namespace Botan;
+                          LibraryInitializer::initialize();
+                          HashFunction *h = get_hash("MD5");
+                         ])],
+        [AC_MSG_RESULT([checking for Botan library... yes])],
+        [AC_MSG_RESULT([checking for Botan library... no])
+         AC_MSG_ERROR([Needs Botan library 1.8 or higher])]
+)
+CPPFLAGS=$CPPFLAGS_SAVED
+LDFLAGS=$LDFLAGS_SAVED
+
 #
 # Configure Boost header path
 #
@@ -613,6 +686,7 @@ AC_CONFIG_FILES([Makefile
                  src/bin/bindctl/tests/Makefile
                  src/bin/cfgmgr/Makefile
                  src/bin/cfgmgr/plugins/Makefile
+                 src/bin/cfgmgr/plugins/tests/Makefile
                  src/bin/cfgmgr/tests/Makefile
                  src/bin/host/Makefile
                  src/bin/loadzone/Makefile
@@ -640,6 +714,7 @@ AC_CONFIG_FILES([Makefile
                  src/bin/stats/tests/isc/config/Makefile
                  src/bin/stats/tests/isc/util/Makefile
                  src/bin/stats/tests/testdata/Makefile
+                 src/bin/stats/tests/http/Makefile
                  src/bin/usermgr/Makefile
                  src/bin/tests/Makefile
                  src/lib/Makefile
@@ -672,11 +747,8 @@ AC_CONFIG_FILES([Makefile
                  src/lib/config/Makefile
                  src/lib/config/tests/Makefile
                  src/lib/config/tests/testdata/Makefile
-                 src/lib/util/Makefile
-                 src/lib/util/io/Makefile
-                 src/lib/util/io/tests/Makefile
-                 src/lib/util/unittests/Makefile
-                 src/lib/util/tests/Makefile
+                 src/lib/cryptolink/Makefile
+                 src/lib/cryptolink/tests/Makefile
                  src/lib/dns/Makefile
                  src/lib/dns/tests/Makefile
                  src/lib/dns/tests/testdata/Makefile
@@ -701,6 +773,11 @@ AC_CONFIG_FILES([Makefile
                  src/lib/cache/tests/Makefile
                  src/lib/server_common/Makefile
                  src/lib/server_common/tests/Makefile
+                 src/lib/util/Makefile
+                 src/lib/util/io/Makefile
+                 src/lib/util/io/tests/Makefile
+                 src/lib/util/unittests/Makefile
+                 src/lib/util/tests/Makefile
                  tests/Makefile
                  tests/system/Makefile
                  tests/tools/Makefile
@@ -729,11 +806,13 @@ AC_OUTPUT([doc/version.ent
            src/bin/zonemgr/tests/zonemgr_test
            src/bin/zonemgr/run_b10-zonemgr.sh
            src/bin/stats/stats.py
-           src/bin/stats/stats_stub.py
-           src/bin/stats/stats.spec.pre
-           src/bin/stats/run_b10-stats.sh
-           src/bin/stats/run_b10-stats_stub.sh
-           src/bin/stats/tests/stats_test
+           src/bin/stats/stats_httpd.py
+           src/bin/stats/stats.spec
+           src/bin/stats/stats-schema.spec
+           src/bin/stats/stats-httpd.spec
+           src/bin/stats/stats-httpd-xml.tpl
+           src/bin/stats/stats-httpd-xsd.tpl
+           src/bin/stats/stats-httpd-xsl.tpl
            src/bin/bind10/bind10.py
            src/bin/bind10/run_bind10.sh
            src/bin/bind10/tests/bind10_test.py
@@ -763,6 +842,7 @@ AC_OUTPUT([doc/version.ent
            src/lib/cc/session_config.h.pre
            src/lib/cc/tests/session_unittests_config.h
            src/lib/log/tests/run_time_init_test.sh
+           src/lib/util/python/mkpywrapper.py
            tests/system/conf.sh
            tests/system/glue/setup.sh
            tests/system/glue/nsx1/b10-config.db
@@ -772,9 +852,6 @@ AC_OUTPUT([doc/version.ent
            chmod +x src/bin/xfrin/run_b10-xfrin.sh
            chmod +x src/bin/xfrout/run_b10-xfrout.sh
            chmod +x src/bin/zonemgr/run_b10-zonemgr.sh
-           chmod +x src/bin/stats/tests/stats_test
-           chmod +x src/bin/stats/run_b10-stats.sh
-           chmod +x src/bin/stats/run_b10-stats_stub.sh
            chmod +x src/bin/bind10/run_bind10.sh
            chmod +x src/bin/cmdctl/tests/cmdctl_test
            chmod +x src/bin/xfrin/tests/xfrin_test
@@ -791,6 +868,7 @@ AC_OUTPUT([doc/version.ent
            chmod +x src/lib/dns/gen-rdatacode.py
            chmod +x src/lib/dns/tests/testdata/gen-wiredata.py
            chmod +x src/lib/log/tests/run_time_init_test.sh
+           chmod +x src/lib/util/python/mkpywrapper.py
            chmod +x tests/system/conf.sh
           ])
 AC_OUTPUT
@@ -813,12 +891,15 @@ Flags:
   DEFS:          $DEFS
   CPPFLAGS:      $CPPFLAGS
   CXXFLAGS:      $CXXFLAGS
+  LDFLAGS:       $LDFLAGS
   B10_CXXFLAGS:  $B10_CXXFLAGS
 dnl includes too
   Python:        ${PYTHON_INCLUDES}
                  ${PYTHON_LDFLAGS}
                  ${PYTHON_LIB}
   Boost:         ${BOOST_INCLUDES}
+  Botan:         ${BOTAN_INCLUDES}
+                 ${BOTAN_LDFLAGS}
   SQLite:        $SQLITE_CFLAGS
                  $SQLITE_LIBS
 

+ 8 - 6
doc/Doxyfile

@@ -568,11 +568,13 @@ WARN_LOGFILE           =
 # directories like "/usr/src/myproject". Separate the files or directories
 # with spaces.
 
-INPUT                  = ../src/lib/cc ../src/lib/config ../src/lib/dns \
-    ../src/lib/exceptions ../src/lib/datasrc ../src/bin/auth \
-    ../src/bin/resolver ../src/lib/bench ../src/lib/log ../src/lib/asiolink/ \
-    ../src/lib/nsas ../src/lib/testutils ../src/lib/cache \
-    ../src/lib/server_common/ ../src/bin/sockcreator/ ../src/lib/util/
+INPUT                  = ../src/lib/cc ../src/lib/config \
+    ../src/lib/cryptolink ../src/lib/dns ../src/lib/datasrc \
+    ../src/bin/auth ../src/bin/resolver ../src/lib/bench \
+    ../src/lib/log ../src/lib/asiolink/ ../src/lib/nsas \
+    ../src/lib/testutils ../src/lib/cache ../src/lib/server_common/ \
+    ../src/bin/sockcreator/ ../src/lib/util/
+    ../src/lib/resolve
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@@ -1163,7 +1165,7 @@ XML_DTD                =
 # and cross-referencing information) to the XML output. Note that
 # enabling this will significantly increase the size of the XML output.
 
-XML_PROGRAMLISTING     = YES
+XML_PROGRAMLISTING     = NO
 
 #---------------------------------------------------------------------------
 # configuration options for the AutoGen Definitions output

+ 7 - 2
ext/asio/README

@@ -1,5 +1,10 @@
 ASIO library header files
-Version 1.4.5 (2010-05-12)
+Version 1.4.8 (2011-04-19)
 Downloaded from http://sourceforge.net/projects/asio/files
 Project page: http://think-async.com/Asio
-No local modifications.
+
+Local modifications:
+Added ASIO_DECL to a number of function definitions
+git commit c32718be9f5409b6f72d98ddcd0b1ccd4c5c2293
+See also the bug report at:
+http://sourceforge.net/tracker/?func=detail&aid=3291113&group_id=122478&atid=694037

+ 1 - 1
ext/asio/asio.hpp

@@ -2,7 +2,7 @@
 // asio.hpp
 // ~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)

+ 5 - 8
ext/asio/asio/basic_datagram_socket.hpp

@@ -2,7 +2,7 @@
 // basic_datagram_socket.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,17 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/basic_socket.hpp"
 #include "asio/datagram_socket_service.hpp"
-#include "asio/error.hpp"
 #include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 

+ 5 - 8
ext/asio/asio/basic_deadline_timer.hpp

@@ -2,7 +2,7 @@
 // basic_deadline_timer.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,17 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/basic_io_object.hpp"
 #include "asio/deadline_timer_service.hpp"
-#include "asio/error.hpp"
 #include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 

+ 5 - 4
ext/asio/asio/basic_io_object.hpp

@@ -2,7 +2,7 @@
 // basic_io_object.hpp
 // ~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,10 +15,11 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/io_service.hpp"
+#include "asio/detail/config.hpp"
 #include "asio/detail/noncopyable.hpp"
+#include "asio/io_service.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 

+ 6 - 9
ext/asio/asio/basic_raw_socket.hpp

@@ -2,7 +2,7 @@
 // basic_raw_socket.hpp
 // ~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,17 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/basic_socket.hpp"
-#include "asio/raw_socket_service.hpp"
-#include "asio/error.hpp"
 #include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+#include "asio/raw_socket_service.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 

+ 9 - 11
ext/asio/asio/basic_serial_port.hpp

@@ -2,7 +2,7 @@
 // basic_serial_port.hpp
 // ~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -16,21 +16,19 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <string>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HAS_SERIAL_PORT) \
+  || defined(GENERATING_DOCUMENTATION)
 
+#include <string>
 #include "asio/basic_io_object.hpp"
+#include "asio/detail/throw_error.hpp"
 #include "asio/error.hpp"
 #include "asio/serial_port_base.hpp"
 #include "asio/serial_port_service.hpp"
-#include "asio/detail/throw_error.hpp"
 
-#if defined(ASIO_HAS_SERIAL_PORT) \
-  || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 
@@ -614,9 +612,9 @@ public:
 
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #endif // defined(ASIO_HAS_SERIAL_PORT)
        //   || defined(GENERATING_DOCUMENTATION)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_BASIC_SERIAL_PORT_HPP

+ 5 - 8
ext/asio/asio/basic_socket.hpp

@@ -2,7 +2,7 @@
 // basic_socket.hpp
 // ~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,16 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/basic_io_object.hpp"
+#include "asio/detail/throw_error.hpp"
 #include "asio/error.hpp"
 #include "asio/socket_base.hpp"
-#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 

+ 5 - 4
ext/asio/asio/basic_socket_acceptor.hpp

@@ -2,7 +2,7 @@
 // basic_socket_acceptor.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,14 +15,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/basic_io_object.hpp"
 #include "asio/basic_socket.hpp"
+#include "asio/detail/throw_error.hpp"
 #include "asio/error.hpp"
 #include "asio/socket_acceptor_service.hpp"
 #include "asio/socket_base.hpp"
-#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 

+ 6 - 11
ext/asio/asio/basic_socket_iostream.hpp

@@ -2,7 +2,7 @@
 // basic_socket_iostream.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,22 +15,15 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if !defined(BOOST_NO_IOSTREAM)
 
-#include "asio/detail/push_options.hpp"
 #include <boost/preprocessor/arithmetic/inc.hpp>
 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
 #include <boost/preprocessor/repetition/enum_params.hpp>
 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
 #include <boost/utility/base_from_member.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/basic_socket_streambuf.hpp"
 #include "asio/stream_socket_service.hpp"
 
@@ -79,6 +72,8 @@
   } \
   /**/
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /// Iostream interface for a socket.
@@ -146,11 +141,11 @@ public:
 
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #undef ASIO_PRIVATE_CTR_DEF
 #undef ASIO_PRIVATE_CONNECT_DEF
 
 #endif // defined(BOOST_NO_IOSTREAM)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_BASIC_SOCKET_IOSTREAM_HPP

+ 7 - 12
ext/asio/asio/basic_socket_streambuf.hpp

@@ -2,7 +2,7 @@
 // basic_socket_streambuf.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,15 +15,10 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if !defined(BOOST_NO_IOSTREAM)
 
-#include "asio/detail/push_options.hpp"
 #include <streambuf>
 #include <boost/array.hpp>
 #include <boost/preprocessor/arithmetic/inc.hpp>
@@ -31,12 +26,10 @@
 #include <boost/preprocessor/repetition/enum_params.hpp>
 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
 #include <boost/utility/base_from_member.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/basic_socket.hpp"
+#include "asio/detail/throw_error.hpp"
 #include "asio/io_service.hpp"
 #include "asio/stream_socket_service.hpp"
-#include "asio/detail/throw_error.hpp"
 
 #if !defined(ASIO_SOCKET_STREAMBUF_MAX_ARITY)
 #define ASIO_SOCKET_STREAMBUF_MAX_ARITY 5
@@ -74,6 +67,8 @@
   } \
   /**/
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /// Iostream streambuf for a socket.
@@ -286,10 +281,10 @@ private:
 
 } // namespace asio
 
+#include "asio/detail/pop_options.hpp"
+
 #undef ASIO_PRIVATE_CONNECT_DEF
 
 #endif // !defined(BOOST_NO_IOSTREAM)
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_BASIC_SOCKET_STREAMBUF_HPP

+ 5 - 8
ext/asio/asio/basic_stream_socket.hpp

@@ -2,7 +2,7 @@
 // basic_stream_socket.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,17 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/basic_socket.hpp"
+#include "asio/detail/throw_error.hpp"
 #include "asio/error.hpp"
 #include "asio/stream_socket_service.hpp"
-#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 

+ 28 - 10
ext/asio/asio/basic_streambuf.hpp

@@ -2,7 +2,7 @@
 // basic_streambuf.hpp
 // ~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,28 +15,23 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if !defined(BOOST_NO_IOSTREAM)
 
-#include "asio/detail/push_options.hpp"
 #include <algorithm>
 #include <cstring>
-#include <memory>
 #include <stdexcept>
 #include <streambuf>
 #include <vector>
 #include <boost/limits.hpp>
 #include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/basic_streambuf_fwd.hpp"
 #include "asio/buffer.hpp"
 #include "asio/detail/noncopyable.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /// Automatically resizable buffer class based on std::streambuf.
@@ -107,7 +102,11 @@ namespace asio {
  * is >> s;
  * @endcode
  */
+#if defined(GENERATING_DOCUMENTATION)
 template <typename Allocator = std::allocator<char> >
+#else
+template <typename Allocator>
+#endif
 class basic_streambuf
   : public std::streambuf,
     private noncopyable
@@ -337,8 +336,27 @@ protected:
 private:
   std::size_t max_size_;
   std::vector<char_type, Allocator> buffer_;
+
+  // Helper function to get the preferred size for reading data.
+  friend std::size_t read_size_helper(
+      basic_streambuf& sb, std::size_t max_size)
+  {
+    return std::min<std::size_t>(
+        std::max<std::size_t>(512, sb.buffer_.capacity() - sb.size()),
+        std::min<std::size_t>(max_size, sb.max_size() - sb.size()));
+  }
 };
 
+// Helper function to get the preferred size for reading data. Used for any
+// user-provided specialisations of basic_streambuf.
+template <typename Allocator>
+inline std::size_t read_size_helper(
+    basic_streambuf<Allocator>& sb, std::size_t max_size)
+{
+  return std::min<std::size_t>(512,
+      std::min<std::size_t>(max_size, sb.max_size() - sb.size()));
+}
+
 } // namespace asio
 
 #include "asio/detail/pop_options.hpp"

+ 33 - 0
ext/asio/asio/basic_streambuf_fwd.hpp

@@ -0,0 +1,33 @@
+//
+// basic_streambuf_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_BASIC_STREAMBUF_FWD_HPP
+#define ASIO_BASIC_STREAMBUF_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+#include <memory>
+
+namespace asio {
+
+template <typename Allocator = std::allocator<char> >
+class basic_streambuf;
+
+} // namespace asio
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+#endif // ASIO_BASIC_STREAMBUF_FWD_HPP

+ 12 - 10
ext/asio/asio/buffer.hpp

@@ -2,7 +2,7 @@
 // buffer.hpp
 // ~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,16 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include <boost/array.hpp>
-#include <boost/type_traits/is_const.hpp>
 #include <string>
 #include <vector>
-#include "asio/detail/pop_options.hpp"
+#include <boost/detail/workaround.hpp>
+#include "asio/detail/array_fwd.hpp"
 
 #if defined(BOOST_MSVC)
 # if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0)
@@ -43,11 +39,17 @@
 #endif // defined(__GNUC__)
 
 #if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-# include "asio/detail/push_options.hpp"
 # include <boost/function.hpp>
-# include "asio/detail/pop_options.hpp"
 #endif // ASIO_ENABLE_BUFFER_DEBUGGING
 
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) \
+  || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
+# include <boost/type_traits/is_const.hpp>
+#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
+       // || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
+
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 class mutable_buffer;

+ 6 - 9
ext/asio/asio/buffered_read_stream.hpp

@@ -2,7 +2,7 @@
 // buffered_read_stream.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,23 +15,20 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
 #include <cstring>
-#include <boost/config.hpp>
 #include <boost/type_traits/remove_reference.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/buffered_read_stream_fwd.hpp"
 #include "asio/buffer.hpp"
-#include "asio/error.hpp"
-#include "asio/io_service.hpp"
 #include "asio/detail/bind_handler.hpp"
 #include "asio/detail/buffer_resize_guard.hpp"
 #include "asio/detail/buffered_stream_storage.hpp"
 #include "asio/detail/noncopyable.hpp"
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 

+ 1 - 5
ext/asio/asio/buffered_read_stream_fwd.hpp

@@ -2,7 +2,7 @@
 // buffered_read_stream_fwd.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,8 +15,6 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
 namespace asio {
 
 template <typename Stream>
@@ -24,6 +22,4 @@ class buffered_read_stream;
 
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_BUFFERED_READ_STREAM_FWD_HPP

+ 5 - 8
ext/asio/asio/buffered_stream.hpp

@@ -2,7 +2,7 @@
 // buffered_stream.hpp
 // ~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,19 +15,16 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/buffered_read_stream.hpp"
 #include "asio/buffered_write_stream.hpp"
 #include "asio/buffered_stream_fwd.hpp"
+#include "asio/detail/noncopyable.hpp"
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
-#include "asio/detail/noncopyable.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 

+ 1 - 5
ext/asio/asio/buffered_stream_fwd.hpp

@@ -2,7 +2,7 @@
 // buffered_stream_fwd.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,8 +15,6 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
 namespace asio {
 
 template <typename Stream>
@@ -24,6 +22,4 @@ class buffered_stream;
 
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_BUFFERED_STREAM_FWD_HPP

+ 7 - 10
ext/asio/asio/buffered_write_stream.hpp

@@ -2,7 +2,7 @@
 // buffered_write_stream.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,24 +15,21 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
 #include <cstring>
-#include <boost/config.hpp>
 #include <boost/type_traits/remove_reference.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/buffered_write_stream_fwd.hpp"
 #include "asio/buffer.hpp"
 #include "asio/completion_condition.hpp"
-#include "asio/error.hpp"
-#include "asio/io_service.hpp"
-#include "asio/write.hpp"
 #include "asio/detail/bind_handler.hpp"
 #include "asio/detail/buffered_stream_storage.hpp"
 #include "asio/detail/noncopyable.hpp"
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/write.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 

+ 1 - 5
ext/asio/asio/buffered_write_stream_fwd.hpp

@@ -2,7 +2,7 @@
 // buffered_write_stream_fwd.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,8 +15,6 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
 namespace asio {
 
 template <typename Stream>
@@ -24,6 +22,4 @@ class buffered_write_stream;
 
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_BUFFERED_WRITE_STREAM_FWD_HPP

+ 13 - 7
ext/asio/asio/buffers_iterator.hpp

@@ -2,7 +2,7 @@
 // buffers_iterator.hpp
 // ~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,20 +15,17 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
 #include <boost/assert.hpp>
-#include <boost/config.hpp>
 #include <boost/detail/workaround.hpp>
 #include <boost/iterator.hpp>
 #include <boost/type_traits/is_convertible.hpp>
 #include <boost/type_traits/add_const.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/buffer.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 namespace detail
@@ -210,6 +207,15 @@ public:
     return tmp;
   }
 
+  /// Addition operator.
+  friend buffers_iterator operator+(std::ptrdiff_t difference,
+      const buffers_iterator& iter)
+  {
+    buffers_iterator tmp(iter);
+    tmp.advance(difference);
+    return tmp;
+  }
+
   /// Subtraction operator.
   friend buffers_iterator operator-(const buffers_iterator& iter,
       std::ptrdiff_t difference)

+ 3 - 5
ext/asio/asio/completion_condition.hpp

@@ -2,7 +2,7 @@
 // completion_condition.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,12 +15,10 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include <cstddef>
 
 #include "asio/detail/push_options.hpp"
-#include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
 
 namespace asio {
 

+ 4 - 8
ext/asio/asio/datagram_socket_service.hpp

@@ -2,7 +2,7 @@
 // datagram_socket_service.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,16 +15,10 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
-#include "asio/detail/service_base.hpp"
 
 #if defined(ASIO_HAS_IOCP)
 # include "asio/detail/win_iocp_socket_service.hpp"
@@ -32,6 +26,8 @@
 # include "asio/detail/reactive_socket_service.hpp"
 #endif
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 
 /// Default service implementation for a datagram socket.

+ 3 - 7
ext/asio/asio/deadline_timer.hpp

@@ -2,7 +2,7 @@
 // deadline_timer.hpp
 // ~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,16 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/detail/socket_types.hpp" // Must come before posix_time.
+#include "asio/basic_deadline_timer.hpp"
 
 #include "asio/detail/push_options.hpp"
 #include <boost/date_time/posix_time/posix_time_types.hpp>
 #include "asio/detail/pop_options.hpp"
 
-#include "asio/basic_deadline_timer.hpp"
-
 namespace asio {
 
 /// Typedef for the typical usage of timer. Uses a UTC clock.
@@ -32,6 +30,4 @@ typedef basic_deadline_timer<boost::posix_time::ptime> deadline_timer;
 
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DEADLINE_TIMER_HPP

+ 5 - 9
ext/asio/asio/deadline_timer_service.hpp

@@ -2,7 +2,7 @@
 // deadline_timer_service.hpp
 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,17 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/deadline_timer_service.hpp"
 #include "asio/io_service.hpp"
 #include "asio/time_traits.hpp"
-#include "asio/detail/deadline_timer_service.hpp"
-#include "asio/detail/service_base.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 

+ 25 - 0
ext/asio/asio/detail/array_fwd.hpp

@@ -0,0 +1,25 @@
+//
+// detail/array_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_ARRAY_FWD_HPP
+#define ASIO_DETAIL_ARRAY_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+namespace boost {
+
+template<class T, std::size_t N>
+class array;
+
+} // namespace boost
+
+#endif // ASIO_DETAIL_ARRAY_FWD_HPP

+ 10 - 7
ext/asio/asio/detail/base_from_completion_cond.hpp

@@ -1,8 +1,8 @@
 //
-// base_from_completion_cond.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/base_from_completion_cond.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,10 +15,11 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/completion_condition.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -31,7 +32,8 @@ protected:
   {
   }
 
-  std::size_t check(const asio::error_code& ec,
+  std::size_t check_for_completion(
+      const asio::error_code& ec,
       std::size_t total_transferred)
   {
     return detail::adapt_completion_condition_result(
@@ -50,7 +52,8 @@ protected:
   {
   }
 
-  static std::size_t check(const asio::error_code& ec,
+  static std::size_t check_for_completion(
+      const asio::error_code& ec,
       std::size_t total_transferred)
   {
     return transfer_all_t()(ec, total_transferred);

+ 21 - 10
ext/asio/asio/detail/bind_handler.hpp

@@ -1,8 +1,8 @@
 //
-// bind_handler.hpp
-// ~~~~~~~~~~~~~~~~
+// detail/bind_handler.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,11 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/detail/handler_alloc_helpers.hpp"
 #include "asio/detail/handler_invoke_helpers.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -35,7 +36,7 @@ public:
 
   void operator()()
   {
-    handler_(arg1_);
+    handler_(static_cast<const Arg1&>(arg1_));
   }
 
   void operator()() const
@@ -92,7 +93,8 @@ public:
 
   void operator()()
   {
-    handler_(arg1_, arg2_);
+    handler_(static_cast<const Arg1&>(arg1_),
+        static_cast<const Arg2&>(arg2_));
   }
 
   void operator()() const
@@ -152,7 +154,9 @@ public:
 
   void operator()()
   {
-    handler_(arg1_, arg2_, arg3_);
+    handler_(static_cast<const Arg1&>(arg1_),
+        static_cast<const Arg2&>(arg2_),
+        static_cast<const Arg3&>(arg3_));
   }
 
   void operator()() const
@@ -216,7 +220,10 @@ public:
 
   void operator()()
   {
-    handler_(arg1_, arg2_, arg3_, arg4_);
+    handler_(static_cast<const Arg1&>(arg1_),
+        static_cast<const Arg2&>(arg2_),
+        static_cast<const Arg3&>(arg3_),
+        static_cast<const Arg4&>(arg4_));
   }
 
   void operator()() const
@@ -287,7 +294,11 @@ public:
 
   void operator()()
   {
-    handler_(arg1_, arg2_, arg3_, arg4_, arg5_);
+    handler_(static_cast<const Arg1&>(arg1_),
+        static_cast<const Arg2&>(arg2_),
+        static_cast<const Arg3&>(arg3_),
+        static_cast<const Arg4&>(arg4_),
+        static_cast<const Arg5&>(arg5_));
   }
 
   void operator()() const

+ 5 - 7
ext/asio/asio/detail/buffer_resize_guard.hpp

@@ -1,8 +1,8 @@
 //
-// buffer_resize_guard.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~
+// detail/buffer_resize_guard.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,12 +15,10 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include <boost/limits.hpp>
 
 #include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include <boost/limits.hpp>
-#include "asio/detail/pop_options.hpp"
 
 namespace asio {
 namespace detail {

+ 11 - 9
ext/asio/asio/detail/buffer_sequence_adapter.hpp

@@ -1,8 +1,8 @@
 //
-// buffer_sequence_adapter.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/buffer_sequence_adapter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,9 +15,11 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/buffer.hpp"
+#include "asio/detail/socket_types.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -32,14 +34,14 @@ protected:
       const asio::mutable_buffer& buffer)
   {
     buf.buf = asio::buffer_cast<char*>(buffer);
-    buf.len = asio::buffer_size(buffer);
+    buf.len = static_cast<ULONG>(asio::buffer_size(buffer));
   }
 
   static void init_native_buffer(WSABUF& buf,
       const asio::const_buffer& buffer)
   {
     buf.buf = const_cast<char*>(asio::buffer_cast<const char*>(buffer));
-    buf.len = asio::buffer_size(buffer);
+    buf.len = static_cast<ULONG>(asio::buffer_size(buffer));
   }
 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
   typedef iovec native_buffer_type;
@@ -158,7 +160,7 @@ public:
   explicit buffer_sequence_adapter(
       const asio::mutable_buffers_1& buffers)
   {
-    init_native_buffer(buffer_, buffers);
+    init_native_buffer(buffer_, Buffer(buffers));
     total_buffer_size_ = asio::buffer_size(buffers);
   }
 
@@ -205,7 +207,7 @@ public:
   explicit buffer_sequence_adapter(
       const asio::const_buffers_1& buffers)
   {
-    init_native_buffer(buffer_, buffers);
+    init_native_buffer(buffer_, Buffer(buffers));
     total_buffer_size_ = asio::buffer_size(buffers);
   }
 

+ 6 - 8
ext/asio/asio/detail/buffered_stream_storage.hpp

@@ -1,8 +1,8 @@
 //
-// buffered_stream_storage.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/buffered_stream_storage.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,15 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
+#include "asio/detail/config.hpp"
 #include <cassert>
 #include <cstddef>
 #include <cstring>
 #include <vector>
-#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {

+ 6 - 5
ext/asio/asio/detail/call_stack.hpp

@@ -1,8 +1,8 @@
 //
-// call_stack.hpp
-// ~~~~~~~~~~~~~~
+// detail/call_stack.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,11 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/detail/noncopyable.hpp"
 #include "asio/detail/tss_ptr.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 

+ 19 - 15
ext/asio/asio/detail/completion_handler.hpp

@@ -1,8 +1,8 @@
 //
-// completion_handler.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~
+// detail/completion_handler.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,13 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/detail/fenced_block.hpp"
 #include "asio/detail/handler_alloc_helpers.hpp"
 #include "asio/detail/handler_invoke_helpers.hpp"
 #include "asio/detail/operation.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -29,6 +30,8 @@ template <typename Handler>
 class completion_handler : public operation
 {
 public:
+  ASIO_DEFINE_HANDLER_PTR(completion_handler);
+
   completion_handler(Handler h)
     : operation(&completion_handler::do_complete),
       handler_(h)
@@ -40,20 +43,21 @@ public:
   {
     // Take ownership of the handler object.
     completion_handler* h(static_cast<completion_handler*>(base));
-    typedef handler_alloc_traits<Handler, completion_handler> alloc_traits;
-    handler_ptr<alloc_traits> ptr(h->handler_, h);
+    ptr p = { boost::addressof(h->handler_), h, h };
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    Handler handler(h->handler_);
+    p.h = boost::addressof(handler);
+    p.reset();
 
     // Make the upcall if required.
     if (owner)
     {
-      // Make a copy of the handler so that the memory can be deallocated
-      // before the upcall is made. Even if we're not about to make an
-      // upcall, a sub-object of the handler may be the true owner of the
-      // memory associated with the handler. Consequently, a local copy of
-      // the handler is required to ensure that any owning sub-object remains
-      // valid until after we have deallocated the memory here.
-      Handler handler(h->handler_);
-      ptr.reset();
       asio::detail::fenced_block b;
       asio_handler_invoke_helpers::invoke(handler, handler);
     }

+ 205 - 0
ext/asio/asio/detail/config.hpp

@@ -0,0 +1,205 @@
+//
+// detail/config.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_CONFIG_HPP
+#define ASIO_DETAIL_CONFIG_HPP
+
+#include <boost/config.hpp>
+
+// Default to a header-only implementation. The user must specifically request
+// separate compilation by defining either ASIO_SEPARATE_COMPILATION or
+// ASIO_DYN_LINK (as a DLL/shared library implies separate compilation).
+#if !defined(ASIO_HEADER_ONLY)
+# if !defined(ASIO_SEPARATE_COMPILATION)
+#  if !defined(ASIO_DYN_LINK)
+#   define ASIO_HEADER_ONLY
+#  endif // !defined(ASIO_DYN_LINK)
+# endif // !defined(ASIO_SEPARATE_COMPILATION)
+#endif // !defined(ASIO_HEADER_ONLY)
+
+#if defined(ASIO_HEADER_ONLY)
+# define ASIO_DECL inline
+#else // defined(ASIO_HEADER_ONLY)
+# if defined(BOOST_HAS_DECLSPEC)
+// We need to import/export our code only if the user has specifically asked
+// for it by defining ASIO_DYN_LINK.
+#  if defined(ASIO_DYN_LINK)
+// Export if this is our own source, otherwise import.
+#   if defined(ASIO_SOURCE)
+#    define ASIO_DECL __declspec(dllexport)
+#   else // defined(ASIO_SOURCE)
+#    define ASIO_DECL __declspec(dllimport)
+#   endif // defined(ASIO_SOURCE)
+#  endif // defined(ASIO_DYN_LINK)
+# endif // defined(BOOST_HAS_DECLSPEC)
+#endif // defined(ASIO_HEADER_ONLY)
+
+// If ASIO_DECL isn't defined yet define it now.
+#if !defined(ASIO_DECL)
+# define ASIO_DECL
+#endif // !defined(ASIO_DECL)
+
+// Windows: target OS version.
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
+#  if defined(_MSC_VER) || defined(__BORLANDC__)
+#   pragma message( \
+  "Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:\n"\
+  "- add -D_WIN32_WINNT=0x0501 to the compiler command line; or\n"\
+  "- add _WIN32_WINNT=0x0501 to your project's Preprocessor Definitions.\n"\
+  "Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target).")
+#  else // defined(_MSC_VER) || defined(__BORLANDC__)
+#   warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately.
+#   warning For example, add -D_WIN32_WINNT=0x0501 to the compiler command line.
+#   warning Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target).
+#  endif // defined(_MSC_VER) || defined(__BORLANDC__)
+#  define _WIN32_WINNT 0x0501
+# endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
+# if defined(_MSC_VER)
+#  if defined(_WIN32) && !defined(WIN32)
+#   if !defined(_WINSOCK2API_)
+#    define WIN32 // Needed for correct types in winsock2.h
+#   else // !defined(_WINSOCK2API_)
+#    error Please define the macro WIN32 in your compiler options
+#   endif // !defined(_WINSOCK2API_)
+#  endif // defined(_WIN32) && !defined(WIN32)
+# endif // defined(_MSC_VER)
+# if defined(__BORLANDC__)
+#  if defined(__WIN32__) && !defined(WIN32)
+#   if !defined(_WINSOCK2API_)
+#    define WIN32 // Needed for correct types in winsock2.h
+#   else // !defined(_WINSOCK2API_)
+#    error Please define the macro WIN32 in your compiler options
+#   endif // !defined(_WINSOCK2API_)
+#  endif // defined(__WIN32__) && !defined(WIN32)
+# endif // defined(__BORLANDC__)
+# if defined(__CYGWIN__)
+#  if !defined(__USE_W32_SOCKETS)
+#   error You must add -D__USE_W32_SOCKETS to your compiler options.
+#  endif // !defined(__USE_W32_SOCKETS)
+# endif // defined(__CYGWIN__)
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+// Windows: minimise header inclusion.
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if !defined(ASIO_NO_WIN32_LEAN_AND_MEAN)
+#  if !defined(WIN32_LEAN_AND_MEAN)
+#   define WIN32_LEAN_AND_MEAN
+#  endif // !defined(WIN32_LEAN_AND_MEAN)
+# endif // !defined(ASIO_NO_WIN32_LEAN_AND_MEAN)
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+// Windows: suppress definition of "min" and "max" macros.
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if !defined(ASIO_NO_NOMINMAX)
+#  if !defined(NOMINMAX)
+#   define NOMINMAX 1
+#  endif // !defined(NOMINMAX)
+# endif // !defined(ASIO_NO_NOMINMAX)
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+// Windows: IO Completion Ports.
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
+#  if !defined(UNDER_CE)
+#   if !defined(ASIO_DISABLE_IOCP)
+#    define ASIO_HAS_IOCP 1
+#   endif // !defined(ASIO_DISABLE_IOCP)
+#  endif // !defined(UNDER_CE)
+# endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+// Linux: epoll, eventfd and timerfd.
+#if defined(__linux__)
+# include <linux/version.h>
+# if !defined(ASIO_DISABLE_EPOLL)
+#  if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45)
+#   define ASIO_HAS_EPOLL 1
+#  endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45)
+# endif // !defined(ASIO_DISABLE_EVENTFD)
+# if !defined(ASIO_DISABLE_EVENTFD)
+#  if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+#   define ASIO_HAS_EVENTFD 1
+#  endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+# endif // !defined(ASIO_DISABLE_EVENTFD)
+# if defined(ASIO_HAS_EPOLL)
+#  if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8)
+#   define ASIO_HAS_TIMERFD 1
+#  endif // (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8)
+# endif // defined(ASIO_HAS_EPOLL)
+#endif // defined(__linux__)
+
+// Mac OS X, FreeBSD, NetBSD, OpenBSD: kqueue.
+#if (defined(__MACH__) && defined(__APPLE__)) \
+  || defined(__FreeBSD__) \
+  || defined(__NetBSD__) \
+  || defined(__OpenBSD__)
+# if !defined(ASIO_DISABLE_KQUEUE)
+#  define ASIO_HAS_KQUEUE 1
+# endif // !defined(ASIO_DISABLE_KQUEUE)
+#endif // (defined(__MACH__) && defined(__APPLE__))
+       //   || defined(__FreeBSD__)
+       //   || defined(__NetBSD__)
+       //   || defined(__OpenBSD__)
+
+// Solaris: /dev/poll.
+#if defined(__sun)
+# if !defined(ASIO_DISABLE_DEV_POLL)
+#  define ASIO_HAS_DEV_POLL 1
+# endif // !defined(ASIO_DISABLE_DEV_POLL)
+#endif // defined(__sun)
+
+// Serial ports.
+#if defined(ASIO_HAS_IOCP) \
+   || !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+# if !defined(__SYMBIAN32__)
+#  if !defined(ASIO_DISABLE_SERIAL_PORT)
+#   define ASIO_HAS_SERIAL_PORT 1
+#  endif // !defined(ASIO_DISABLE_SERIAL_PORT)
+# endif // !defined(__SYMBIAN32__)
+#endif // defined(ASIO_HAS_IOCP)
+       //   || !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+// Windows: stream handles.
+#if !defined(ASIO_DISABLE_WINDOWS_STREAM_HANDLE)
+# if defined(ASIO_HAS_IOCP)
+#  define ASIO_HAS_WINDOWS_STREAM_HANDLE 1
+# endif // defined(ASIO_HAS_IOCP)
+#endif // !defined(ASIO_DISABLE_WINDOWS_STREAM_HANDLE)
+
+// Windows: random access handles.
+#if !defined(ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE)
+# if defined(ASIO_HAS_IOCP)
+#  define ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE 1
+# endif // defined(ASIO_HAS_IOCP)
+#endif // !defined(ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE)
+
+// Windows: OVERLAPPED wrapper.
+#if !defined(ASIO_DISABLE_WINDOWS_OVERLAPPED_PTR)
+# if defined(ASIO_HAS_IOCP)
+#  define ASIO_HAS_WINDOWS_OVERLAPPED_PTR 1
+# endif // defined(ASIO_HAS_IOCP)
+#endif // !defined(ASIO_DISABLE_WINDOWS_OVERLAPPED_PTR)
+
+// POSIX: stream-oriented file descriptors.
+#if !defined(ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR)
+# if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#  define ASIO_HAS_POSIX_STREAM_DESCRIPTOR 1
+# endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#endif // !defined(ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR)
+
+// UNIX domain sockets.
+#if !defined(ASIO_DISABLE_LOCAL_SOCKETS)
+# if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#  define ASIO_HAS_LOCAL_SOCKETS 1
+# endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#endif // !defined(ASIO_DISABLE_LOCAL_SOCKETS)
+
+#endif // ASIO_DETAIL_CONFIG_HPP

+ 9 - 11
ext/asio/asio/detail/consuming_buffers.hpp

@@ -1,8 +1,8 @@
 //
-// consuming_buffers.hpp
-// ~~~~~~~~~~~~~~~~~~~~~
+// detail/consuming_buffers.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,18 +15,14 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <algorithm>
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
 #include <boost/iterator.hpp>
 #include <boost/limits.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/buffer.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -156,12 +152,14 @@ public:
   consuming_buffers(const Buffers& buffers)
     : buffers_(buffers),
       at_end_(buffers_.begin() == buffers_.end()),
-      first_(*buffers_.begin()),
       begin_remainder_(buffers_.begin()),
       max_size_((std::numeric_limits<std::size_t>::max)())
   {
     if (!at_end_)
+    {
+      first_ = *buffers_.begin();
       ++begin_remainder_;
+    }
   }
 
   // Copy constructor.

+ 20 - 56
ext/asio/asio/detail/deadline_timer_service.hpp

@@ -1,8 +1,8 @@
 //
-// deadline_timer_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/deadline_timer_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,14 +15,8 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cstddef>
-#include <boost/config.hpp>
-#include <boost/date_time/posix_time/posix_time_types.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/error.hpp"
 #include "asio/io_service.hpp"
 #include "asio/detail/bind_handler.hpp"
@@ -33,6 +27,13 @@
 #include "asio/detail/timer_op.hpp"
 #include "asio/detail/timer_queue.hpp"
 #include "asio/detail/timer_scheduler.hpp"
+#include "asio/detail/wait_handler.hpp"
+
+#include "asio/detail/push_options.hpp"
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -54,6 +55,7 @@ public:
   {
     time_type expiry;
     bool might_have_pending_waits;
+    typename timer_queue<Time_Traits>::per_timer_data timer_data;
   };
 
   // Constructor.
@@ -97,7 +99,7 @@ public:
       ec = asio::error_code();
       return 0;
     }
-    std::size_t count = scheduler_.cancel_timer(timer_queue_, &impl);
+    std::size_t count = scheduler_.cancel_timer(timer_queue_, impl.timer_data);
     impl.might_have_pending_waits = false;
     ec = asio::error_code();
     return count;
@@ -151,59 +153,21 @@ public:
     ec = asio::error_code();
   }
 
-  template <typename Handler>
-  class wait_handler : public timer_op
-  {
-  public:
-    wait_handler(Handler handler)
-      : timer_op(&wait_handler::do_complete),
-        handler_(handler)
-    {
-    }
-
-    static void do_complete(io_service_impl* owner, operation* base,
-        asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
-    {
-      // Take ownership of the handler object.
-      wait_handler* h(static_cast<wait_handler*>(base));
-      typedef handler_alloc_traits<Handler, wait_handler> alloc_traits;
-      handler_ptr<alloc_traits> ptr(h->handler_, h);
-
-      // Make the upcall if required.
-      if (owner)
-      {
-        // Make a copy of the handler so that the memory can be deallocated
-        // before the upcall is made. Even if we're not about to make an
-        // upcall, a sub-object of the handler may be the true owner of the
-        // memory associated with the handler. Consequently, a local copy of
-        // the handler is required to ensure that any owning sub-object remains
-        // valid until after we have deallocated the memory here.
-        detail::binder1<Handler, asio::error_code>
-          handler(h->handler_, h->ec_);
-        ptr.reset();
-        asio::detail::fenced_block b;
-        asio_handler_invoke_helpers::invoke(handler, handler);
-      }
-    }
-
-  private:
-    Handler handler_;
-  };
-
   // Start an asynchronous wait on the timer.
   template <typename Handler>
   void async_wait(implementation_type& impl, Handler handler)
   {
     // Allocate and construct an operation to wrap the handler.
-    typedef wait_handler<Handler> value_type;
-    typedef handler_alloc_traits<Handler, value_type> alloc_traits;
-    raw_handler_ptr<alloc_traits> raw_ptr(handler);
-    handler_ptr<alloc_traits> ptr(raw_ptr, handler);
+    typedef wait_handler<Handler> op;
+    typename op::ptr p = { boost::addressof(handler),
+      asio_handler_alloc_helpers::allocate(
+        sizeof(op), handler), 0 };
+    p.p = new (p.v) op(handler);
 
     impl.might_have_pending_waits = true;
 
-    scheduler_.schedule_timer(timer_queue_, impl.expiry, ptr.get(), &impl);
-    ptr.release();
+    scheduler_.schedule_timer(timer_queue_, impl.expiry, impl.timer_data, p.p);
+    p.v = p.p = 0;
   }
 
 private:

+ 50 - 121
ext/asio/asio/detail/descriptor_ops.hpp

@@ -1,8 +1,8 @@
 //
-// descriptor_ops.hpp
-// ~~~~~~~~~~~~~~~~~~
+// detail/descriptor_ops.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,27 +15,34 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include <cerrno>
-#include "asio/detail/pop_options.hpp"
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
 
-#include "asio/error.hpp"
+#include <cstddef>
+#include "asio/error_code.hpp"
 #include "asio/detail/socket_types.hpp"
 
-#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
 namespace descriptor_ops {
 
-inline void clear_error(asio::error_code& ec)
+// Descriptor state bits.
+enum
 {
-  errno = 0;
-  ec = asio::error_code();
-}
+  // The user wants a non-blocking descriptor.
+  user_set_non_blocking = 1,
+
+  // The descriptor has been set non-blocking.
+  internal_non_blocking = 2,
+
+  // Helper "state" used to determine whether the descriptor is non-blocking.
+  non_blocking = user_set_non_blocking | internal_non_blocking
+};
+
+typedef unsigned char state_type;
 
 template <typename ReturnType>
 inline ReturnType error_wrapper(ReturnType return_value,
@@ -46,131 +53,53 @@ inline ReturnType error_wrapper(ReturnType return_value,
   return return_value;
 }
 
-inline int open(const char* path, int flags, asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(::open(path, flags), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL int open(const char* path, int flags,
+    asio::error_code& ec);
 
-inline int close(int d, asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(::close(d), ec);
-  if (result == 0)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL int close(int d, state_type& state,
+    asio::error_code& ec);
 
-inline void init_buf_iov_base(void*& base, void* addr)
-{
-  base = addr;
-}
-
-template <typename T>
-inline void init_buf_iov_base(T& base, void* addr)
-{
-  base = static_cast<T>(addr);
-}
+ASIO_DECL bool set_internal_non_blocking(int d,
+    state_type& state, asio::error_code& ec);
 
 typedef iovec buf;
 
-inline void init_buf(buf& b, void* data, size_t size)
-{
-  init_buf_iov_base(b.iov_base, data);
-  b.iov_len = size;
-}
+ASIO_DECL std::size_t sync_read(int d, state_type state, buf* bufs,
+    std::size_t count, bool all_empty, asio::error_code& ec);
 
-inline void init_buf(buf& b, const void* data, size_t size)
-{
-  init_buf_iov_base(b.iov_base, const_cast<void*>(data));
-  b.iov_len = size;
-}
+ASIO_DECL bool non_blocking_read(int d, buf* bufs, std::size_t count,
+    asio::error_code& ec, std::size_t& bytes_transferred);
 
-inline int scatter_read(int d, buf* bufs, size_t count,
-    asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(::readv(d, bufs, static_cast<int>(count)), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL std::size_t sync_write(int d, state_type state,
+    const buf* bufs, std::size_t count, bool all_empty,
+    asio::error_code& ec);
 
-inline int gather_write(int d, const buf* bufs, size_t count,
-    asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(::writev(d, bufs, static_cast<int>(count)), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL bool non_blocking_write(int d,
+    const buf* bufs, std::size_t count,
+    asio::error_code& ec, std::size_t& bytes_transferred);
 
-inline int ioctl(int d, long cmd, ioctl_arg_type* arg,
-    asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(::ioctl(d, cmd, arg), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL int ioctl(int d, state_type& state, long cmd,
+    ioctl_arg_type* arg, asio::error_code& ec);
 
-inline int fcntl(int d, long cmd, asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(::fcntl(d, cmd), ec);
-  if (result != -1)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL int fcntl(int d, long cmd, asio::error_code& ec);
 
-inline int fcntl(int d, long cmd, long arg, asio::error_code& ec)
-{
-  clear_error(ec);
-  int result = error_wrapper(::fcntl(d, cmd, arg), ec);
-  if (result != -1)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL int fcntl(int d, long cmd,
+    long arg, asio::error_code& ec);
 
-inline int poll_read(int d, asio::error_code& ec)
-{
-  clear_error(ec);
-  pollfd fds;
-  fds.fd = d;
-  fds.events = POLLIN;
-  fds.revents = 0;
-  clear_error(ec);
-  int result = error_wrapper(::poll(&fds, 1, -1), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL int poll_read(int d, asio::error_code& ec);
 
-inline int poll_write(int d, asio::error_code& ec)
-{
-  clear_error(ec);
-  pollfd fds;
-  fds.fd = d;
-  fds.events = POLLOUT;
-  fds.revents = 0;
-  clear_error(ec);
-  int result = error_wrapper(::poll(&fds, 1, -1), ec);
-  if (result >= 0)
-    clear_error(ec);
-  return result;
-}
+ASIO_DECL int poll_write(int d, asio::error_code& ec);
 
 } // namespace descriptor_ops
 } // namespace detail
 } // namespace asio
 
-#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/descriptor_ops.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
 #endif // ASIO_DETAIL_DESCRIPTOR_OPS_HPP

+ 114 - 0
ext/asio/asio/detail/descriptor_read_op.hpp

@@ -0,0 +1,114 @@
+//
+// detail/descriptor_read_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_DESCRIPTOR_READ_OP_HPP
+#define ASIO_DETAIL_DESCRIPTOR_READ_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/descriptor_ops.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/reactor_op.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence>
+class descriptor_read_op_base : public reactor_op
+{
+public:
+  descriptor_read_op_base(int descriptor,
+      const MutableBufferSequence& buffers, func_type complete_func)
+    : reactor_op(&descriptor_read_op_base::do_perform, complete_func),
+      descriptor_(descriptor),
+      buffers_(buffers)
+  {
+  }
+
+  static bool do_perform(reactor_op* base)
+  {
+    descriptor_read_op_base* o(static_cast<descriptor_read_op_base*>(base));
+
+    buffer_sequence_adapter<asio::mutable_buffer,
+        MutableBufferSequence> bufs(o->buffers_);
+
+    return descriptor_ops::non_blocking_read(o->descriptor_,
+        bufs.buffers(), bufs.count(), o->ec_, o->bytes_transferred_);
+  }
+
+private:
+  int descriptor_;
+  MutableBufferSequence buffers_;
+};
+
+template <typename MutableBufferSequence, typename Handler>
+class descriptor_read_op
+  : public descriptor_read_op_base<MutableBufferSequence>
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(descriptor_read_op);
+
+  descriptor_read_op(int descriptor,
+      const MutableBufferSequence& buffers, Handler handler)
+    : descriptor_read_op_base<MutableBufferSequence>(
+        descriptor, buffers, &descriptor_read_op::do_complete),
+      handler_(handler)
+  {
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+  {
+    // Take ownership of the handler object.
+    descriptor_read_op* o(static_cast<descriptor_read_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder2<Handler, asio::error_code, std::size_t>
+      handler(o->handler_, o->ec_, o->bytes_transferred_);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#endif // ASIO_DETAIL_DESCRIPTOR_READ_OP_HPP

+ 114 - 0
ext/asio/asio/detail/descriptor_write_op.hpp

@@ -0,0 +1,114 @@
+//
+// detail/descriptor_write_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_DESCRIPTOR_WRITE_OP_HPP
+#define ASIO_DETAIL_DESCRIPTOR_WRITE_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/descriptor_ops.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/reactor_op.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename ConstBufferSequence>
+class descriptor_write_op_base : public reactor_op
+{
+public:
+  descriptor_write_op_base(int descriptor,
+      const ConstBufferSequence& buffers, func_type complete_func)
+    : reactor_op(&descriptor_write_op_base::do_perform, complete_func),
+      descriptor_(descriptor),
+      buffers_(buffers)
+  {
+  }
+
+  static bool do_perform(reactor_op* base)
+  {
+    descriptor_write_op_base* o(static_cast<descriptor_write_op_base*>(base));
+
+    buffer_sequence_adapter<asio::const_buffer,
+        ConstBufferSequence> bufs(o->buffers_);
+
+    return descriptor_ops::non_blocking_write(o->descriptor_,
+        bufs.buffers(), bufs.count(), o->ec_, o->bytes_transferred_);
+  }
+
+private:
+  int descriptor_;
+  ConstBufferSequence buffers_;
+};
+
+template <typename ConstBufferSequence, typename Handler>
+class descriptor_write_op
+  : public descriptor_write_op_base<ConstBufferSequence>
+{
+public:
+  ASIO_DEFINE_HANDLER_PTR(descriptor_write_op);
+
+  descriptor_write_op(int descriptor,
+      const ConstBufferSequence& buffers, Handler handler)
+    : descriptor_write_op_base<ConstBufferSequence>(
+        descriptor, buffers, &descriptor_write_op::do_complete),
+      handler_(handler)
+  {
+  }
+
+  static void do_complete(io_service_impl* owner, operation* base,
+      asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+  {
+    // Take ownership of the handler object.
+    descriptor_write_op* o(static_cast<descriptor_write_op*>(base));
+    ptr p = { boost::addressof(o->handler_), o, o };
+
+    // Make a copy of the handler so that the memory can be deallocated before
+    // the upcall is made. Even if we're not about to make an upcall, a
+    // sub-object of the handler may be the true owner of the memory associated
+    // with the handler. Consequently, a local copy of the handler is required
+    // to ensure that any owning sub-object remains valid until after we have
+    // deallocated the memory here.
+    detail::binder2<Handler, asio::error_code, std::size_t>
+      handler(o->handler_, o->ec_, o->bytes_transferred_);
+    p.h = boost::addressof(handler.handler_);
+    p.reset();
+
+    // Make the upcall if required.
+    if (owner)
+    {
+      asio::detail::fenced_block b;
+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+    }
+  }
+
+private:
+  Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#endif // ASIO_DETAIL_DESCRIPTOR_WRITE_OP_HPP

+ 49 - 317
ext/asio/asio/detail/dev_poll_reactor.hpp

@@ -1,8 +1,8 @@
 //
-// dev_poll_reactor.hpp
-// ~~~~~~~~~~~~~~~~~~~~
+// detail/dev_poll_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,36 +15,28 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/dev_poll_reactor_fwd.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_DEV_POLL)
 
-#include "asio/detail/push_options.hpp"
 #include <cstddef>
 #include <vector>
-#include <boost/config.hpp>
-#include <boost/date_time/posix_time/posix_time_types.hpp>
-#include <boost/throw_exception.hpp>
 #include <sys/devpoll.h>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/io_service.hpp"
-#include "asio/system_error.hpp"
+#include "asio/detail/dev_poll_reactor_fwd.hpp"
 #include "asio/detail/hash_map.hpp"
 #include "asio/detail/mutex.hpp"
 #include "asio/detail/op_queue.hpp"
 #include "asio/detail/reactor_op.hpp"
 #include "asio/detail/reactor_op_queue.hpp"
 #include "asio/detail/select_interrupter.hpp"
-#include "asio/detail/service_base.hpp"
 #include "asio/detail/socket_types.hpp"
 #include "asio/detail/timer_op.hpp"
 #include "asio/detail/timer_queue_base.hpp"
 #include "asio/detail/timer_queue_fwd.hpp"
 #include "asio/detail/timer_queue_set.hpp"
+#include "asio/io_service.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -62,358 +54,93 @@ public:
   };
 
   // Constructor.
-  dev_poll_reactor(asio::io_service& io_service)
-    : asio::detail::service_base<dev_poll_reactor>(io_service),
-      io_service_(use_service<io_service_impl>(io_service)),
-      mutex_(),
-      dev_poll_fd_(do_dev_poll_create()),
-      interrupter_(),
-      shutdown_(false)
-  {
-    // Add the interrupter's descriptor to /dev/poll.
-    ::pollfd ev = { 0 };
-    ev.fd = interrupter_.read_descriptor();
-    ev.events = POLLIN | POLLERR;
-    ev.revents = 0;
-    ::write(dev_poll_fd_, &ev, sizeof(ev));
-  }
+  ASIO_DECL dev_poll_reactor(asio::io_service& io_service);
 
   // Destructor.
-  ~dev_poll_reactor()
-  {
-    shutdown_service();
-    ::close(dev_poll_fd_);
-  }
+  ASIO_DECL ~dev_poll_reactor();
 
   // Destroy all user-defined handler objects owned by the service.
-  void shutdown_service()
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    shutdown_ = true;
-    lock.unlock();
-
-    op_queue<operation> ops;
-
-    for (int i = 0; i < max_ops; ++i)
-      op_queue_[i].get_all_operations(ops);
-
-    timer_queues_.get_all_timers(ops);
-  } 
+  ASIO_DECL void shutdown_service();
 
   // Initialise the task.
-  void init_task()
-  {
-    io_service_.init_task();
-  }
+  ASIO_DECL void init_task();
 
   // Register a socket with the reactor. Returns 0 on success, system error
   // code on failure.
-  int register_descriptor(socket_type, per_descriptor_data&)
+  ASIO_DECL int register_descriptor(socket_type, per_descriptor_data&);
+
+  // Post a reactor operation for immediate completion.
+  void post_immediate_completion(reactor_op* op)
   {
-    return 0;
+    io_service_.post_immediate_completion(op);
   }
 
   // Start a new operation. The reactor operation will be performed when the
   // given descriptor is flagged as ready, or an error has occurred.
-  void start_op(int op_type, socket_type descriptor,
-      per_descriptor_data&, reactor_op* op, bool allow_speculative)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-
-    if (shutdown_)
-      return;
-
-    if (allow_speculative)
-    {
-      if (op_type != read_op || !op_queue_[except_op].has_operation(descriptor))
-      {
-        if (!op_queue_[op_type].has_operation(descriptor))
-        {
-          if (op->perform())
-          {
-            lock.unlock();
-            io_service_.post_immediate_completion(op);
-            return;
-          }
-        }
-      }
-    }
-
-    bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
-    io_service_.work_started();
-    if (first)
-    {
-      ::pollfd& ev = add_pending_event_change(descriptor);
-      ev.events = POLLERR | POLLHUP;
-      if (op_type == read_op
-          || op_queue_[read_op].has_operation(descriptor))
-        ev.events |= POLLIN;
-      if (op_type == write_op
-          || op_queue_[write_op].has_operation(descriptor))
-        ev.events |= POLLOUT;
-      if (op_type == except_op
-          || op_queue_[except_op].has_operation(descriptor))
-        ev.events |= POLLPRI;
-      interrupter_.interrupt();
-    }
-  }
+  ASIO_DECL void start_op(int op_type, socket_type descriptor,
+      per_descriptor_data&, reactor_op* op, bool allow_speculative);
 
   // Cancel all operations associated with the given descriptor. The
   // handlers associated with the descriptor will be invoked with the
   // operation_aborted error.
-  void cancel_ops(socket_type descriptor, per_descriptor_data&)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
-  }
+  ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data&);
 
   // Cancel any operations that are running against the descriptor and remove
   // its registration from the reactor.
-  void close_descriptor(socket_type descriptor, per_descriptor_data&)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-
-    // Remove the descriptor from /dev/poll.
-    ::pollfd& ev = add_pending_event_change(descriptor);
-    ev.events = POLLREMOVE;
-    interrupter_.interrupt();
-
-    // Cancel any outstanding operations associated with the descriptor.
-    cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
-  }
+  ASIO_DECL void close_descriptor(
+      socket_type descriptor, per_descriptor_data&);
 
   // Add a new timer queue to the reactor.
   template <typename Time_Traits>
-  void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    timer_queues_.insert(&timer_queue);
-  }
+  void add_timer_queue(timer_queue<Time_Traits>& queue);
 
   // Remove a timer queue from the reactor.
   template <typename Time_Traits>
-  void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    timer_queues_.erase(&timer_queue);
-  }
+  void remove_timer_queue(timer_queue<Time_Traits>& queue);
 
   // Schedule a new operation in the given timer queue to expire at the
   // specified absolute time.
   template <typename Time_Traits>
-  void schedule_timer(timer_queue<Time_Traits>& timer_queue,
-      const typename Time_Traits::time_type& time, timer_op* op, void* token)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    if (!shutdown_)
-    {
-      bool earliest = timer_queue.enqueue_timer(time, op, token);
-      io_service_.work_started();
-      if (earliest)
-        interrupter_.interrupt();
-    }
-  }
+  void schedule_timer(timer_queue<Time_Traits>& queue,
+      const typename Time_Traits::time_type& time,
+      typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op);
 
   // Cancel the timer operations associated with the given token. Returns the
   // number of operations that have been posted or dispatched.
   template <typename Time_Traits>
-  std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-    op_queue<operation> ops;
-    std::size_t n = timer_queue.cancel_timer(token, ops);
-    lock.unlock();
-    io_service_.post_deferred_completions(ops);
-    return n;
-  }
+  std::size_t cancel_timer(timer_queue<Time_Traits>& queue,
+      typename timer_queue<Time_Traits>::per_timer_data& timer);
 
   // Run /dev/poll once until interrupted or events are ready to be dispatched.
-  void run(bool block, op_queue<operation>& ops)
-  {
-    asio::detail::mutex::scoped_lock lock(mutex_);
-
-    // We can return immediately if there's no work to do and the reactor is
-    // not supposed to block.
-    if (!block && op_queue_[read_op].empty() && op_queue_[write_op].empty()
-        && op_queue_[except_op].empty() && timer_queues_.all_empty())
-      return;
-
-    // Write the pending event registration changes to the /dev/poll descriptor.
-    std::size_t events_size = sizeof(::pollfd) * pending_event_changes_.size();
-    if (events_size > 0)
-    {
-      errno = 0;
-      int result = ::write(dev_poll_fd_,
-          &pending_event_changes_[0], events_size);
-      if (result != static_cast<int>(events_size))
-      {
-        asio::error_code ec = asio::error_code(
-            errno, asio::error::get_system_category());
-        for (std::size_t i = 0; i < pending_event_changes_.size(); ++i)
-        {
-          int descriptor = pending_event_changes_[i].fd;
-          for (int j = 0; j < max_ops; ++j)
-            op_queue_[j].cancel_operations(descriptor, ops, ec);
-        }
-      }
-      pending_event_changes_.clear();
-      pending_event_change_index_.clear();
-    }
-
-    int timeout = block ? get_timeout() : 0;
-    lock.unlock();
-
-    // Block on the /dev/poll descriptor.
-    ::pollfd events[128] = { { 0 } };
-    ::dvpoll dp = { 0 };
-    dp.dp_fds = events;
-    dp.dp_nfds = 128;
-    dp.dp_timeout = timeout;
-    int num_events = ::ioctl(dev_poll_fd_, DP_POLL, &dp);
-
-    lock.lock();
-
-    // Dispatch the waiting events.
-    for (int i = 0; i < num_events; ++i)
-    {
-      int descriptor = events[i].fd;
-      if (descriptor == interrupter_.read_descriptor())
-      {
-        interrupter_.reset();
-      }
-      else
-      {
-        bool more_reads = false;
-        bool more_writes = false;
-        bool more_except = false;
-
-        // Exception operations must be processed first to ensure that any
-        // out-of-band data is read before normal data.
-        if (events[i].events & (POLLPRI | POLLERR | POLLHUP))
-          more_except =
-            op_queue_[except_op].perform_operations(descriptor, ops);
-        else
-          more_except = op_queue_[except_op].has_operation(descriptor);
-
-        if (events[i].events & (POLLIN | POLLERR | POLLHUP))
-          more_reads = op_queue_[read_op].perform_operations(descriptor, ops);
-        else
-          more_reads = op_queue_[read_op].has_operation(descriptor);
-
-        if (events[i].events & (POLLOUT | POLLERR | POLLHUP))
-          more_writes = op_queue_[write_op].perform_operations(descriptor, ops);
-        else
-          more_writes = op_queue_[write_op].has_operation(descriptor);
-
-        if ((events[i].events & (POLLERR | POLLHUP)) != 0
-              && !more_except && !more_reads && !more_writes)
-        {
-          // If we have an event and no operations associated with the
-          // descriptor then we need to delete the descriptor from /dev/poll.
-          // The poll operation can produce POLLHUP or POLLERR events when there
-          // is no operation pending, so if we do not remove the descriptor we
-          // can end up in a tight polling loop.
-          ::pollfd ev = { 0 };
-          ev.fd = descriptor;
-          ev.events = POLLREMOVE;
-          ev.revents = 0;
-          ::write(dev_poll_fd_, &ev, sizeof(ev));
-        }
-        else
-        {
-          ::pollfd ev = { 0 };
-          ev.fd = descriptor;
-          ev.events = POLLERR | POLLHUP;
-          if (more_reads)
-            ev.events |= POLLIN;
-          if (more_writes)
-            ev.events |= POLLOUT;
-          if (more_except)
-            ev.events |= POLLPRI;
-          ev.revents = 0;
-          int result = ::write(dev_poll_fd_, &ev, sizeof(ev));
-          if (result != sizeof(ev))
-          {
-            asio::error_code ec(errno,
-                asio::error::get_system_category());
-            for (int j = 0; j < max_ops; ++j)
-              op_queue_[j].cancel_operations(descriptor, ops, ec);
-          }
-        }
-      }
-    }
-    timer_queues_.get_ready_timers(ops);
-  }
+  ASIO_DECL void run(bool block, op_queue<operation>& ops);
 
   // Interrupt the select loop.
-  void interrupt()
-  {
-    interrupter_.interrupt();
-  }
+  ASIO_DECL void interrupt();
 
 private:
   // Create the /dev/poll file descriptor. Throws an exception if the descriptor
   // cannot be created.
-  static int do_dev_poll_create()
-  {
-    int fd = ::open("/dev/poll", O_RDWR);
-    if (fd == -1)
-    {
-      boost::throw_exception(
-          asio::system_error(
-            asio::error_code(errno,
-              asio::error::get_system_category()),
-            "/dev/poll"));
-    }
-    return fd;
-  }
+  ASIO_DECL static int do_dev_poll_create();
+
+  // Helper function to add a new timer queue.
+  ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);
+
+  // Helper function to remove a timer queue.
+  ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);
 
   // Get the timeout value for the /dev/poll DP_POLL operation. The timeout
   // value is returned as a number of milliseconds. A return value of -1
   // indicates that the poll should block indefinitely.
-  int get_timeout()
-  {
-    // By default we will wait no longer than 5 minutes. This will ensure that
-    // any changes to the system clock are detected after no longer than this.
-    return timer_queues_.wait_duration_msec(5 * 60 * 1000);
-  }
+  ASIO_DECL int get_timeout();
 
   // Cancel all operations associated with the given descriptor. The do_cancel
   // function of the handler objects will be invoked. This function does not
   // acquire the dev_poll_reactor's mutex.
-  void cancel_ops_unlocked(socket_type descriptor,
-      const asio::error_code& ec)
-  {
-    bool need_interrupt = false;
-    op_queue<operation> ops;
-    for (int i = 0; i < max_ops; ++i)
-      need_interrupt = op_queue_[i].cancel_operations(
-          descriptor, ops, ec) || need_interrupt;
-    io_service_.post_deferred_completions(ops);
-    if (need_interrupt)
-      interrupter_.interrupt();
-  }
+  ASIO_DECL void cancel_ops_unlocked(socket_type descriptor,
+      const asio::error_code& ec);
 
   // Add a pending event entry for the given descriptor.
-  ::pollfd& add_pending_event_change(int descriptor)
-  {
-    hash_map<int, std::size_t>::iterator iter
-      = pending_event_change_index_.find(descriptor);
-    if (iter == pending_event_change_index_.end())
-    {
-      std::size_t index = pending_event_changes_.size();
-      pending_event_changes_.reserve(pending_event_changes_.size() + 1);
-      pending_event_change_index_.insert(std::make_pair(descriptor, index));
-      pending_event_changes_.push_back(::pollfd());
-      pending_event_changes_[index].fd = descriptor;
-      pending_event_changes_[index].revents = 0;
-      return pending_event_changes_[index];
-    }
-    else
-    {
-      return pending_event_changes_[iter->second];
-    }
-  }
+  ASIO_DECL ::pollfd& add_pending_event_change(int descriptor);
 
   // The io_service implementation used to post completions.
   io_service_impl& io_service_;
@@ -446,8 +173,13 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(ASIO_HAS_DEV_POLL)
-
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/detail/impl/dev_poll_reactor.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/dev_poll_reactor.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_DEV_POLL)
+
 #endif // ASIO_DETAIL_DEV_POLL_REACTOR_HPP

+ 6 - 13
ext/asio/asio/detail/dev_poll_reactor_fwd.hpp

@@ -1,8 +1,8 @@
 //
-// dev_poll_reactor_fwd.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/dev_poll_reactor_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,13 +15,9 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#if !defined(ASIO_DISABLE_DEV_POLL)
-#if defined(__sun) // This service is only supported on Solaris.
-
-// Define this to indicate that /dev/poll is supported on the target platform.
-#define ASIO_HAS_DEV_POLL 1
+#if defined(ASIO_HAS_DEV_POLL)
 
 namespace asio {
 namespace detail {
@@ -31,9 +27,6 @@ class dev_poll_reactor;
 } // namespace detail
 } // namespace asio
 
-#endif // defined(__sun)
-#endif // !defined(ASIO_DISABLE_DEV_POLL)
-
-#include "asio/detail/pop_options.hpp"
+#endif // defined(ASIO_HAS_DEV_POLL)
 
 #endif // ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP

+ 58 - 368
ext/asio/asio/detail/epoll_reactor.hpp

@@ -1,8 +1,8 @@
 //
-// epoll_reactor.hpp
-// ~~~~~~~~~~~~~~~~~
+// detail/epoll_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,43 +15,24 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/epoll_reactor_fwd.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_EPOLL)
 
-#include "asio/detail/push_options.hpp"
-#include <cstddef>
-#include <sys/epoll.h>
-#include <boost/config.hpp>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
 #include "asio/io_service.hpp"
-#include "asio/system_error.hpp"
-#include "asio/detail/hash_map.hpp"
+#include "asio/detail/epoll_reactor_fwd.hpp"
 #include "asio/detail/mutex.hpp"
+#include "asio/detail/object_pool.hpp"
 #include "asio/detail/op_queue.hpp"
 #include "asio/detail/reactor_op.hpp"
 #include "asio/detail/select_interrupter.hpp"
-#include "asio/detail/service_base.hpp"
 #include "asio/detail/socket_types.hpp"
 #include "asio/detail/timer_op.hpp"
 #include "asio/detail/timer_queue_base.hpp"
 #include "asio/detail/timer_queue_fwd.hpp"
 #include "asio/detail/timer_queue_set.hpp"
 
-#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8)
-# define ASIO_HAS_TIMERFD 1
-#endif // (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8)
-
-#if defined(ASIO_HAS_TIMERFD)
-# include "asio/detail/push_options.hpp"
-# include <sys/timerfd.h>
-# include "asio/detail/pop_options.hpp"
-#endif // defined(ASIO_HAS_TIMERFD)
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
@@ -64,357 +45,86 @@ public:
     connect_op = 1, except_op = 2, max_ops = 3 };
 
   // Per-descriptor queues.
-  struct descriptor_state
+  class descriptor_state
   {
-    descriptor_state() {}
-    descriptor_state(const descriptor_state&) {}
-    void operator=(const descriptor_state&) {}
-
+    friend class epoll_reactor;
+    friend class object_pool_access;
     mutex mutex_;
     op_queue<reactor_op> op_queue_[max_ops];
     bool shutdown_;
+    descriptor_state* next_;
+    descriptor_state* prev_;
   };
 
   // Per-descriptor data.
   typedef descriptor_state* per_descriptor_data;
 
   // Constructor.
-  epoll_reactor(asio::io_service& io_service)
-    : asio::detail::service_base<epoll_reactor>(io_service),
-      io_service_(use_service<io_service_impl>(io_service)),
-      mutex_(),
-      epoll_fd_(do_epoll_create()),
-#if defined(ASIO_HAS_TIMERFD)
-      timer_fd_(timerfd_create(CLOCK_MONOTONIC, 0)),
-#else // defined(ASIO_HAS_TIMERFD)
-      timer_fd_(-1),
-#endif // defined(ASIO_HAS_TIMERFD)
-      interrupter_(),
-      shutdown_(false)
-  {
-    // Add the interrupter's descriptor to epoll.
-    epoll_event ev = { 0, { 0 } };
-    ev.events = EPOLLIN | EPOLLERR | EPOLLET;
-    ev.data.ptr = &interrupter_;
-    epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev);
-    interrupter_.interrupt();
-
-    // Add the timer descriptor to epoll.
-    if (timer_fd_ != -1)
-    {
-      ev.events = EPOLLIN | EPOLLERR;
-      ev.data.ptr = &timer_fd_;
-      epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev);
-    }
-  }
+  ASIO_DECL epoll_reactor(asio::io_service& io_service);
 
   // Destructor.
-  ~epoll_reactor()
-  {
-    close(epoll_fd_);
-    if (timer_fd_ != -1)
-      close(timer_fd_);
-  }
+  ASIO_DECL ~epoll_reactor();
 
   // Destroy all user-defined handler objects owned by the service.
-  void shutdown_service()
-  {
-    mutex::scoped_lock lock(mutex_);
-    shutdown_ = true;
-    lock.unlock();
-
-    op_queue<operation> ops;
-
-    descriptor_map::iterator iter = registered_descriptors_.begin();
-    descriptor_map::iterator end = registered_descriptors_.end();
-    while (iter != end)
-    {
-      for (int i = 0; i < max_ops; ++i)
-        ops.push(iter->second.op_queue_[i]);
-      iter->second.shutdown_ = true;
-      ++iter;
-    }
-
-    timer_queues_.get_all_timers(ops);
-  }
+  ASIO_DECL void shutdown_service();
 
   // Initialise the task.
-  void init_task()
-  {
-    io_service_.init_task();
-  }
+  ASIO_DECL void init_task();
 
   // Register a socket with the reactor. Returns 0 on success, system error
   // code on failure.
-  int register_descriptor(socket_type descriptor,
-      per_descriptor_data& descriptor_data)
-  {
-    mutex::scoped_lock lock(registered_descriptors_mutex_);
-
-    descriptor_map::iterator new_entry = registered_descriptors_.insert(
-          std::make_pair(descriptor, descriptor_state())).first;
-    descriptor_data = &new_entry->second;
-
-    epoll_event ev = { 0, { 0 } };
-    ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLOUT | EPOLLPRI | EPOLLET;
-    ev.data.ptr = descriptor_data;
-    int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
-    if (result != 0)
-      return errno;
-
-    descriptor_data->shutdown_ = false;
+  ASIO_DECL int register_descriptor(socket_type descriptor,
+      per_descriptor_data& descriptor_data);
 
-    return 0;
+  // Post a reactor operation for immediate completion.
+  void post_immediate_completion(reactor_op* op)
+  {
+    io_service_.post_immediate_completion(op);
   }
 
   // Start a new operation. The reactor operation will be performed when the
   // given descriptor is flagged as ready, or an error has occurred.
-  void start_op(int op_type, socket_type descriptor,
+  ASIO_DECL void start_op(int op_type, socket_type descriptor,
       per_descriptor_data& descriptor_data,
-      reactor_op* op, bool allow_speculative)
-  {
-    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
-    if (descriptor_data->shutdown_)
-      return;
-
-    if (descriptor_data->op_queue_[op_type].empty())
-    {
-      if (allow_speculative
-          && (op_type != read_op
-            || descriptor_data->op_queue_[except_op].empty()))
-      {
-        if (op->perform())
-        {
-          descriptor_lock.unlock();
-          io_service_.post_immediate_completion(op);
-          return;
-        }
-      }
-      else
-      {
-        epoll_event ev = { 0, { 0 } };
-        ev.events = EPOLLIN | EPOLLERR | EPOLLHUP
-          | EPOLLOUT | EPOLLPRI | EPOLLET;
-        ev.data.ptr = descriptor_data;
-        epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
-      }
-    }
-
-    descriptor_data->op_queue_[op_type].push(op);
-    io_service_.work_started();
-  }
+      reactor_op* op, bool allow_speculative);
 
   // Cancel all operations associated with the given descriptor. The
   // handlers associated with the descriptor will be invoked with the
   // operation_aborted error.
-  void cancel_ops(socket_type, per_descriptor_data& descriptor_data)
-  {
-    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
-
-    op_queue<operation> ops;
-    for (int i = 0; i < max_ops; ++i)
-    {
-      while (reactor_op* op = descriptor_data->op_queue_[i].front())
-      {
-        op->ec_ = asio::error::operation_aborted;
-        descriptor_data->op_queue_[i].pop();
-        ops.push(op);
-      }
-    }
-
-    descriptor_lock.unlock();
-
-    io_service_.post_deferred_completions(ops);
-  }
+  ASIO_DECL void cancel_ops(socket_type descriptor,
+      per_descriptor_data& descriptor_data);
 
   // Cancel any operations that are running against the descriptor and remove
   // its registration from the reactor.
-  void close_descriptor(socket_type descriptor,
-      per_descriptor_data& descriptor_data)
-  {
-    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
-    mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
-
-    // Remove the descriptor from the set of known descriptors. The descriptor
-    // will be automatically removed from the epoll set when it is closed.
-    descriptor_data->shutdown_ = true;
-
-    op_queue<operation> ops;
-    for (int i = 0; i < max_ops; ++i)
-    {
-      while (reactor_op* op = descriptor_data->op_queue_[i].front())
-      {
-        op->ec_ = asio::error::operation_aborted;
-        descriptor_data->op_queue_[i].pop();
-        ops.push(op);
-      }
-    }
-
-    descriptor_lock.unlock();
-
-    registered_descriptors_.erase(descriptor);
-
-    descriptors_lock.unlock();
-
-    io_service_.post_deferred_completions(ops);
-  }
+  ASIO_DECL void close_descriptor(socket_type descriptor,
+      per_descriptor_data& descriptor_data);
 
   // Add a new timer queue to the reactor.
   template <typename Time_Traits>
-  void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
-  {
-    mutex::scoped_lock lock(mutex_);
-    timer_queues_.insert(&timer_queue);
-  }
+  void add_timer_queue(timer_queue<Time_Traits>& timer_queue);
 
   // Remove a timer queue from the reactor.
   template <typename Time_Traits>
-  void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
-  {
-    mutex::scoped_lock lock(mutex_);
-    timer_queues_.erase(&timer_queue);
-  }
+  void remove_timer_queue(timer_queue<Time_Traits>& timer_queue);
 
   // Schedule a new operation in the given timer queue to expire at the
   // specified absolute time.
   template <typename Time_Traits>
-  void schedule_timer(timer_queue<Time_Traits>& timer_queue,
-      const typename Time_Traits::time_type& time, timer_op* op, void* token)
-  {
-    mutex::scoped_lock lock(mutex_);
-    if (!shutdown_)
-    {
-      bool earliest = timer_queue.enqueue_timer(time, op, token);
-      io_service_.work_started();
-      if (earliest)
-      {
-#if defined(ASIO_HAS_TIMERFD)
-        if (timer_fd_ != -1)
-        {
-          itimerspec new_timeout;
-          itimerspec old_timeout;
-          int flags = get_timeout(new_timeout);
-          timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);
-          return;
-        }
-#endif // defined(ASIO_HAS_TIMERFD)
-        interrupter_.interrupt();
-      }
-    }
-  }
+  void schedule_timer(timer_queue<Time_Traits>& queue,
+      const typename Time_Traits::time_type& time,
+      typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op);
 
   // Cancel the timer operations associated with the given token. Returns the
   // number of operations that have been posted or dispatched.
   template <typename Time_Traits>
-  std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
-  {
-    mutex::scoped_lock lock(mutex_);
-    op_queue<operation> ops;
-    std::size_t n = timer_queue.cancel_timer(token, ops);
-    lock.unlock();
-    io_service_.post_deferred_completions(ops);
-    return n;
-  }
+  std::size_t cancel_timer(timer_queue<Time_Traits>& queue,
+      typename timer_queue<Time_Traits>::per_timer_data& timer);
 
   // Run epoll once until interrupted or events are ready to be dispatched.
-  void run(bool block, op_queue<operation>& ops)
-  {
-    // Calculate a timeout only if timerfd is not used.
-    int timeout;
-    if (timer_fd_ != -1)
-      timeout = block ? -1 : 0;
-    else
-    {
-      mutex::scoped_lock lock(mutex_);
-      timeout = block ? get_timeout() : 0;
-    }
-
-    // Block on the epoll descriptor.
-    epoll_event events[128];
-    int num_events = epoll_wait(epoll_fd_, events, 128, timeout);
-
-#if defined(ASIO_HAS_TIMERFD)
-    bool check_timers = (timer_fd_ == -1);
-#else // defined(ASIO_HAS_TIMERFD)
-    bool check_timers = true;
-#endif // defined(ASIO_HAS_TIMERFD)
-
-    // Dispatch the waiting events.
-    for (int i = 0; i < num_events; ++i)
-    {
-      void* ptr = events[i].data.ptr;
-      if (ptr == &interrupter_)
-      {
-        // No need to reset the interrupter since we're leaving the descriptor
-        // in a ready-to-read state and relying on edge-triggered notifications
-        // to make it so that we only get woken up when the descriptor's epoll
-        // registration is updated.
-
-#if defined(ASIO_HAS_TIMERFD)
-        if (timer_fd_ == -1)
-          check_timers = true;
-#else // defined(ASIO_HAS_TIMERFD)
-        check_timers = true;
-#endif // defined(ASIO_HAS_TIMERFD)
-      }
-#if defined(ASIO_HAS_TIMERFD)
-      else if (ptr == &timer_fd_)
-      {
-        check_timers = true;
-      }
-#endif // defined(ASIO_HAS_TIMERFD)
-      else
-      {
-        descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);
-        mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
-
-        // Exception operations must be processed first to ensure that any
-        // out-of-band data is read before normal data.
-        static const int flag[max_ops] = { EPOLLIN, EPOLLOUT, EPOLLPRI };
-        for (int j = max_ops - 1; j >= 0; --j)
-        {
-          if (events[i].events & (flag[j] | EPOLLERR | EPOLLHUP))
-          {
-            while (reactor_op* op = descriptor_data->op_queue_[j].front())
-            {
-              if (op->perform())
-              {
-                descriptor_data->op_queue_[j].pop();
-                ops.push(op);
-              }
-              else
-                break;
-            }
-          }
-        }
-      }
-    }
-
-    if (check_timers)
-    {
-      mutex::scoped_lock common_lock(mutex_);
-      timer_queues_.get_ready_timers(ops);
-
-#if defined(ASIO_HAS_TIMERFD)
-      if (timer_fd_ != -1)
-      {
-        itimerspec new_timeout;
-        itimerspec old_timeout;
-        int flags = get_timeout(new_timeout);
-        timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);
-      }
-#endif // defined(ASIO_HAS_TIMERFD)
-    }
-  }
+  ASIO_DECL void run(bool block, op_queue<operation>& ops);
 
   // Interrupt the select loop.
-  void interrupt()
-  {
-    epoll_event ev = { 0, { 0 } };
-    ev.events = EPOLLIN | EPOLLERR | EPOLLET;
-    ev.data.ptr = &interrupter_;
-    epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, interrupter_.read_descriptor(), &ev);
-  }
+  ASIO_DECL void interrupt();
 
 private:
   // The hint to pass to epoll_create to size its data structures.
@@ -422,44 +132,26 @@ private:
 
   // Create the epoll file descriptor. Throws an exception if the descriptor
   // cannot be created.
-  static int do_epoll_create()
-  {
-    int fd = epoll_create(epoll_size);
-    if (fd == -1)
-    {
-      boost::throw_exception(
-          asio::system_error(
-            asio::error_code(errno,
-              asio::error::get_system_category()),
-            "epoll"));
-    }
-    return fd;
-  }
+  ASIO_DECL static int do_epoll_create();
+
+  // Helper function to add a new timer queue.
+  ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);
+
+  // Helper function to remove a timer queue.
+  ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);
+
+  // Called to recalculate and update the timeout.
+  ASIO_DECL void update_timeout();
 
   // Get the timeout value for the epoll_wait call. The timeout value is
   // returned as a number of milliseconds. A return value of -1 indicates
   // that epoll_wait should block indefinitely.
-  int get_timeout()
-  {
-    // By default we will wait no longer than 5 minutes. This will ensure that
-    // any changes to the system clock are detected after no longer than this.
-    return timer_queues_.wait_duration_msec(5 * 60 * 1000);
-  }
+  ASIO_DECL int get_timeout();
 
 #if defined(ASIO_HAS_TIMERFD)
   // Get the timeout value for the timer descriptor. The return value is the
   // flag argument to be used when calling timerfd_settime.
-  int get_timeout(itimerspec& ts)
-  {
-    ts.it_interval.tv_sec = 0;
-    ts.it_interval.tv_nsec = 0;
-
-    long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
-    ts.it_value.tv_sec = usec / 1000000;
-    ts.it_value.tv_nsec = usec ? (usec % 1000000) * 1000 : 1;
-
-    return usec ? 0 : TFD_TIMER_ABSTIME;
-  }
+  ASIO_DECL int get_timeout(itimerspec& ts);
 #endif // defined(ASIO_HAS_TIMERFD)
 
   // The io_service implementation used to post completions.
@@ -486,22 +178,20 @@ private:
   // Mutex to protect access to the registered descriptors.
   mutex registered_descriptors_mutex_;
 
-  // Keep track of all registered descriptors. This code relies on the fact that
-  // the hash_map implementation pools deleted nodes, meaning that we can assume
-  // our descriptor_state pointer remains valid even after the entry is removed.
-  // Technically this is not true for C++98, as that standard says that spliced
-  // elements in a list are invalidated. However, C++0x fixes this shortcoming
-  // so we'll just assume that C++98 std::list implementations will do the right
-  // thing anyway.
-  typedef detail::hash_map<socket_type, descriptor_state> descriptor_map;
-  descriptor_map registered_descriptors_;
+  // Keep track of all registered descriptors.
+  object_pool<descriptor_state> registered_descriptors_;
 };
 
 } // namespace detail
 } // namespace asio
 
-#endif // defined(ASIO_HAS_EPOLL)
-
 #include "asio/detail/pop_options.hpp"
 
+#include "asio/detail/impl/epoll_reactor.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/epoll_reactor.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_EPOLL)
+
 #endif // ASIO_DETAIL_EPOLL_REACTOR_HPP

+ 6 - 20
ext/asio/asio/detail/epoll_reactor_fwd.hpp

@@ -1,8 +1,8 @@
 //
-// epoll_reactor_fwd.hpp
-// ~~~~~~~~~~~~~~~~~~~~~
+// detail/epoll_reactor_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,19 +15,9 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#if !defined(ASIO_DISABLE_EPOLL)
-#if defined(__linux__) // This service is only supported on Linux.
-
-#include "asio/detail/push_options.hpp"
-#include <linux/version.h>
-#include "asio/detail/pop_options.hpp"
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION (2,5,45) // Only kernels >= 2.5.45.
-
-// Define this to indicate that epoll is supported on the target platform.
-#define ASIO_HAS_EPOLL 1
+#if defined(ASIO_HAS_EPOLL)
 
 namespace asio {
 namespace detail {
@@ -37,10 +27,6 @@ class epoll_reactor;
 } // namespace detail
 } // namespace asio
 
-#endif // LINUX_VERSION_CODE >= KERNEL_VERSION (2,5,45)
-#endif // defined(__linux__)
-#endif // !defined(ASIO_DISABLE_EPOLL)
-
-#include "asio/detail/pop_options.hpp"
+#endif // defined(ASIO_HAS_EPOLL)
 
 #endif // ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP

+ 4 - 10
ext/asio/asio/detail/event.hpp

@@ -1,8 +1,8 @@
 //
-// event.hpp
-// ~~~~~~~~~
+// detail/event.hpp
+// ~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,11 +15,7 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
 # include "asio/detail/null_event.hpp"
@@ -45,6 +41,4 @@ typedef posix_event event;
 } // namespace detail
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_EVENT_HPP

+ 14 - 106
ext/asio/asio/detail/eventfd_select_interrupter.hpp

@@ -1,8 +1,8 @@
 //
-// eventfd_select_interrupter.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/eventfd_select_interrupter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 // Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com)
 //
 // Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -16,36 +16,11 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#if defined(__linux__)
-# if !defined(ASIO_DISABLE_EVENTFD)
-#  include <linux/version.h>
-#  if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
-#   define ASIO_HAS_EVENTFD
-#  endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
-# endif // !defined(ASIO_DISABLE_EVENTFD)
-#endif // defined(__linux__)
+#include "asio/detail/config.hpp"
 
 #if defined(ASIO_HAS_EVENTFD)
 
 #include "asio/detail/push_options.hpp"
-#include <fcntl.h>
-#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
-# include <asm/unistd.h>
-#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
-# include <sys/eventfd.h>
-#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
-#include "asio/detail/socket_types.hpp"
 
 namespace asio {
 namespace detail {
@@ -54,87 +29,16 @@ class eventfd_select_interrupter
 {
 public:
   // Constructor.
-  eventfd_select_interrupter()
-  {
-#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
-    write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0);
-#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
-    write_descriptor_ = read_descriptor_ = ::eventfd(0, 0);
-#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
-    if (read_descriptor_ != -1)
-    {
-      ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
-    }
-    else
-    {
-      int pipe_fds[2];
-      if (pipe(pipe_fds) == 0)
-      {
-        read_descriptor_ = pipe_fds[0];
-        ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
-        write_descriptor_ = pipe_fds[1];
-        ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
-      }
-      else
-      {
-        asio::error_code ec(errno,
-            asio::error::get_system_category());
-        asio::system_error e(ec, "eventfd_select_interrupter");
-        boost::throw_exception(e);
-      }
-    }
-  }
+  ASIO_DECL eventfd_select_interrupter();
 
   // Destructor.
-  ~eventfd_select_interrupter()
-  {
-    if (write_descriptor_ != -1 && write_descriptor_ != read_descriptor_)
-      ::close(write_descriptor_);
-    if (read_descriptor_ != -1)
-      ::close(read_descriptor_);
-  }
+  ASIO_DECL ~eventfd_select_interrupter();
 
   // Interrupt the select call.
-  void interrupt()
-  {
-    uint64_t counter(1UL);
-    int result = ::write(write_descriptor_, &counter, sizeof(uint64_t));
-    (void)result;
-  }
+  ASIO_DECL void interrupt();
 
   // Reset the select interrupt. Returns true if the call was interrupted.
-  bool reset()
-  {
-    if (write_descriptor_ == read_descriptor_)
-    {
-      for (;;)
-      {
-        // Only perform one read. The kernel maintains an atomic counter.
-        uint64_t counter(0);
-        errno = 0;
-        int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t));
-        if (bytes_read < 0 && errno == EINTR)
-          continue;
-        bool was_interrupted = (bytes_read > 0);
-        return was_interrupted;
-      }
-    }
-    else
-    {
-      for (;;)
-      {
-        // Clear all data from the pipe.
-        char data[1024];
-        int bytes_read = ::read(read_descriptor_, data, sizeof(data));
-        if (bytes_read < 0 && errno == EINTR)
-          continue;
-        bool was_interrupted = (bytes_read > 0);
-        while (bytes_read == sizeof(data))
-          bytes_read = ::read(read_descriptor_, data, sizeof(data));
-        return was_interrupted;
-      }
-    }
-  }
+  ASIO_DECL bool reset();
 
   // Get the read descriptor to be passed to select.
   int read_descriptor() const
@@ -159,8 +63,12 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(ASIO_HAS_EVENTFD)
-
 #include "asio/detail/pop_options.hpp"
 
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/eventfd_select_interrupter.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_EVENTFD)
+
 #endif // ASIO_DETAIL_EVENTFD_SELECT_INTERRUPTER_HPP

+ 4 - 11
ext/asio/asio/detail/fd_set_adapter.hpp

@@ -1,8 +1,8 @@
 //
-// fd_set_adapter.hpp
-// ~~~~~~~~~~~~~~~~~~
+// detail/fd_set_adapter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,12 +15,7 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/config.hpp"
 #include "asio/detail/posix_fd_set_adapter.hpp"
 #include "asio/detail/win_fd_set_adapter.hpp"
 
@@ -36,6 +31,4 @@ typedef posix_fd_set_adapter fd_set_adapter;
 } // namespace detail
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_FD_SET_ADAPTER_HPP

+ 20 - 14
ext/asio/asio/detail/fenced_block.hpp

@@ -1,8 +1,8 @@
 //
-// fenced_block.hpp
-// ~~~~~~~~~~~~~~~~
+// detail/fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,23 +15,25 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+#if !defined(BOOST_HAS_THREADS) \
+  || defined(ASIO_DISABLE_THREADS) \
+  || defined(ASIO_DISABLE_FENCED_BLOCK)
 # include "asio/detail/null_fenced_block.hpp"
 #elif defined(__MACH__) && defined(__APPLE__)
 # include "asio/detail/macos_fenced_block.hpp"
 #elif defined(__sun)
 # include "asio/detail/solaris_fenced_block.hpp"
+#elif defined(__GNUC__) && defined(__arm__)
+# include "asio/detail/gcc_arm_fenced_block.hpp"
+#elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))
+# include "asio/detail/gcc_hppa_fenced_block.hpp"
 #elif defined(__GNUC__) \
   && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \
   && !defined(__INTEL_COMPILER) && !defined(__ICL) \
   && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)
-# include "asio/detail/gcc_fenced_block.hpp"
+# include "asio/detail/gcc_sync_fenced_block.hpp"
 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
 # include "asio/detail/gcc_x86_fenced_block.hpp"
 #elif defined(BOOST_WINDOWS) && !defined(UNDER_CE)
@@ -43,17 +45,23 @@
 namespace asio {
 namespace detail {
 
-#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+#if !defined(BOOST_HAS_THREADS) \
+  || defined(ASIO_DISABLE_THREADS) \
+  || defined(ASIO_DISABLE_FENCED_BLOCK)
 typedef null_fenced_block fenced_block;
 #elif defined(__MACH__) && defined(__APPLE__)
 typedef macos_fenced_block fenced_block;
 #elif defined(__sun)
 typedef solaris_fenced_block fenced_block;
+#elif defined(__GNUC__) && defined(__arm__)
+typedef gcc_arm_fenced_block fenced_block;
+#elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))
+typedef gcc_hppa_fenced_block fenced_block;
 #elif defined(__GNUC__) \
   && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \
   && !defined(__INTEL_COMPILER) && !defined(__ICL) \
   && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)
-typedef gcc_fenced_block fenced_block;
+typedef gcc_sync_fenced_block fenced_block;
 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
 typedef gcc_x86_fenced_block fenced_block;
 #elif defined(BOOST_WINDOWS) && !defined(UNDER_CE)
@@ -65,6 +73,4 @@ typedef null_fenced_block fenced_block;
 } // namespace detail
 } // namespace asio
 
-#include "asio/detail/pop_options.hpp"
-
 #endif // ASIO_DETAIL_FENCED_BLOCK_HPP

+ 76 - 0
ext/asio/asio/detail/gcc_arm_fenced_block.hpp

@@ -0,0 +1,76 @@
+//
+// detail/gcc_arm_fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_GCC_ARM_FENCED_BLOCK_HPP
+#define ASIO_DETAIL_GCC_ARM_FENCED_BLOCK_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(__GNUC__) && defined(__arm__)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class gcc_arm_fenced_block
+  : private noncopyable
+{
+public:
+  // Constructor.
+  gcc_arm_fenced_block()
+  {
+    barrier();
+  }
+
+  // Destructor.
+  ~gcc_arm_fenced_block()
+  {
+    barrier();
+  }
+
+private:
+  static void barrier()
+  {
+#if defined(__ARM_ARCH_4__) \
+    || defined(__ARM_ARCH_4T__) \
+    || defined(__ARM_ARCH_5__) \
+    || defined(__ARM_ARCH_5E__) \
+    || defined(__ARM_ARCH_5T__) \
+    || defined(__ARM_ARCH_5TE__) \
+    || defined(__ARM_ARCH_5TEJ__) \
+    || defined(__ARM_ARCH_6__) \
+    || defined(__ARM_ARCH_6J__) \
+    || defined(__ARM_ARCH_6K__) \
+    || defined(__ARM_ARCH_6Z__) \
+    || defined(__ARM_ARCH_6ZK__) \
+    || defined(__ARM_ARCH_6T2__)
+    int a = 0, b = 0;
+    __asm__ __volatile__ ("swp %0, %1, [%2]"
+        : "=&r"(a) : "r"(1), "r"(&b) : "memory", "cc");
+#else
+    // ARMv7 and later.
+    __asm__ __volatile__ ("dmb" : : : "memory");
+#endif
+  }
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(__GNUC__) && defined(__arm__)
+
+#endif // ASIO_DETAIL_GCC_ARM_FENCED_BLOCK_HPP

+ 58 - 0
ext/asio/asio/detail/gcc_hppa_fenced_block.hpp

@@ -0,0 +1,58 @@
+//
+// detail/gcc_hppa_fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_GCC_HPPA_FENCED_BLOCK_HPP
+#define ASIO_DETAIL_GCC_HPPA_FENCED_BLOCK_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class gcc_hppa_fenced_block
+  : private noncopyable
+{
+public:
+  // Constructor.
+  gcc_hppa_fenced_block()
+  {
+    barrier();
+  }
+
+  // Destructor.
+  ~gcc_hppa_fenced_block()
+  {
+    barrier();
+  }
+
+private:
+  static void barrier()
+  {
+    // This is just a placeholder and almost certainly not sufficient.
+    __asm__ __volatile__ ("" : : : "memory");
+  }
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))
+
+#endif // ASIO_DETAIL_GCC_HPPA_FENCED_BLOCK_HPP

+ 61 - 0
ext/asio/asio/detail/gcc_sync_fenced_block.hpp

@@ -0,0 +1,61 @@
+//
+// detail/gcc_sync_fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_GCC_SYNC_FENCED_BLOCK_HPP
+#define ASIO_DETAIL_GCC_SYNC_FENCED_BLOCK_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(__GNUC__) \
+  && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \
+  && !defined(__INTEL_COMPILER) && !defined(__ICL) \
+  && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class gcc_sync_fenced_block
+  : private noncopyable
+{
+public:
+  // Constructor.
+  gcc_sync_fenced_block()
+    : value_(0)
+  {
+    __sync_lock_test_and_set(&value_, 1);
+  }
+
+  // Destructor.
+  ~gcc_sync_fenced_block()
+  {
+    __sync_lock_release(&value_);
+  }
+
+private:
+  int value_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(__GNUC__)
+       // && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4))
+       // && !defined(__INTEL_COMPILER) && !defined(__ICL)
+       // && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)
+
+#endif // ASIO_DETAIL_GCC_SYNC_FENCED_BLOCK_HPP

+ 8 - 10
ext/asio/asio/detail/gcc_x86_fenced_block.hpp

@@ -1,8 +1,8 @@
 //
-// gcc_x86_fenced_block.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/gcc_x86_fenced_block.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,14 +15,12 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
 
 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
 
+#include "asio/detail/push_options.hpp"
+
 namespace asio {
 namespace detail {
 
@@ -54,8 +52,8 @@ private:
 } // namespace detail
 } // namespace asio
 
-#endif // defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-
 #include "asio/detail/pop_options.hpp"
 
+#endif // defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+
 #endif // ASIO_DETAIL_GCC_X86_FENCED_BLOCK_HPP

+ 32 - 206
ext/asio/asio/detail/handler_alloc_helpers.hpp

@@ -1,8 +1,8 @@
 //
-// handler_alloc_helpers.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/handler_alloc_helpers.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,15 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <boost/detail/workaround.hpp>
 #include <boost/utility/addressof.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/handler_alloc_hook.hpp"
 #include "asio/detail/noncopyable.hpp"
+#include "asio/handler_alloc_hook.hpp"
+
+#include "asio/detail/push_options.hpp"
 
 // Calls to asio_handler_allocate and asio_handler_deallocate must be made from
 // a namespace that does not contain any overloads of these functions. The
@@ -56,203 +54,31 @@ inline void deallocate(void* p, std::size_t s, Handler& h)
 
 } // namespace asio_handler_alloc_helpers
 
-namespace asio {
-namespace detail {
-
-// Traits for handler allocation.
-template <typename Handler, typename Object>
-struct handler_alloc_traits
-{
-  typedef Handler handler_type;
-  typedef Object value_type;
-  typedef Object* pointer_type;
-  BOOST_STATIC_CONSTANT(std::size_t, value_size = sizeof(Object));
-};
-
-template <typename Alloc_Traits>
-class handler_ptr;
-
-// Helper class to provide RAII on uninitialised handler memory.
-template <typename Alloc_Traits>
-class raw_handler_ptr
-  : private noncopyable
-{
-public:
-  typedef typename Alloc_Traits::handler_type handler_type;
-  typedef typename Alloc_Traits::value_type value_type;
-  typedef typename Alloc_Traits::pointer_type pointer_type;
-  BOOST_STATIC_CONSTANT(std::size_t, value_size = Alloc_Traits::value_size);
-
-  // Constructor allocates the memory.
-  raw_handler_ptr(handler_type& handler)
-    : handler_(handler),
-      pointer_(static_cast<pointer_type>(
-            asio_handler_alloc_helpers::allocate(value_size, handler_)))
-  {
-  }
-
-  // Destructor automatically deallocates memory, unless it has been stolen by
-  // a handler_ptr object.
-  ~raw_handler_ptr()
-  {
-    if (pointer_)
-      asio_handler_alloc_helpers::deallocate(
-          pointer_, value_size, handler_);
-  }
-
-private:
-  friend class handler_ptr<Alloc_Traits>;
-  handler_type& handler_;
-  pointer_type pointer_;
-};
-
-// Helper class to provide RAII on uninitialised handler memory.
-template <typename Alloc_Traits>
-class handler_ptr
-  : private noncopyable
-{
-public:
-  typedef typename Alloc_Traits::handler_type handler_type;
-  typedef typename Alloc_Traits::value_type value_type;
-  typedef typename Alloc_Traits::pointer_type pointer_type;
-  BOOST_STATIC_CONSTANT(std::size_t, value_size = Alloc_Traits::value_size);
-  typedef raw_handler_ptr<Alloc_Traits> raw_ptr_type;
-
-  // Take ownership of existing memory.
-  handler_ptr(handler_type& handler, pointer_type pointer)
-    : handler_(handler),
-      pointer_(pointer)
-  {
-  }
-
-  // Construct object in raw memory and take ownership if construction succeeds.
-  handler_ptr(raw_ptr_type& raw_ptr)
-    : handler_(raw_ptr.handler_),
-      pointer_(new (raw_ptr.pointer_) value_type)
-  {
-    raw_ptr.pointer_ = 0;
-  }
-
-  // Construct object in raw memory and take ownership if construction succeeds.
-  template <typename Arg1>
-  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1)
-    : handler_(raw_ptr.handler_),
-      pointer_(new (raw_ptr.pointer_) value_type(a1))
-  {
-    raw_ptr.pointer_ = 0;
-  }
-
-  // Construct object in raw memory and take ownership if construction succeeds.
-  template <typename Arg1, typename Arg2>
-  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2)
-    : handler_(raw_ptr.handler_),
-      pointer_(new (raw_ptr.pointer_) value_type(a1, a2))
-  {
-    raw_ptr.pointer_ = 0;
-  }
-
-  // Construct object in raw memory and take ownership if construction succeeds.
-  template <typename Arg1, typename Arg2, typename Arg3>
-  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3)
-    : handler_(raw_ptr.handler_),
-      pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3))
-  {
-    raw_ptr.pointer_ = 0;
-  }
-
-  // Construct object in raw memory and take ownership if construction succeeds.
-  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
-  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4)
-    : handler_(raw_ptr.handler_),
-      pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4))
-  {
-    raw_ptr.pointer_ = 0;
-  }
-
-  // Construct object in raw memory and take ownership if construction succeeds.
-  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
-      typename Arg5>
-  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
-      Arg5& a5)
-    : handler_(raw_ptr.handler_),
-      pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5))
-  {
-    raw_ptr.pointer_ = 0;
-  }
-
-  // Construct object in raw memory and take ownership if construction succeeds.
-  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
-      typename Arg5, typename Arg6>
-  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
-      Arg5& a5, Arg6& a6)
-    : handler_(raw_ptr.handler_),
-      pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5, a6))
-  {
-    raw_ptr.pointer_ = 0;
-  }
-
-  // Construct object in raw memory and take ownership if construction succeeds.
-  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
-      typename Arg5, typename Arg6, typename Arg7>
-  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
-      Arg5& a5, Arg6& a6, Arg7& a7)
-    : handler_(raw_ptr.handler_),
-      pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5, a6, a7))
-  {
-    raw_ptr.pointer_ = 0;
-  }
-
-  // Construct object in raw memory and take ownership if construction succeeds.
-  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
-      typename Arg5, typename Arg6, typename Arg7, typename Arg8>
-  handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
-      Arg5& a5, Arg6& a6, Arg7& a7, Arg8& a8)
-    : handler_(raw_ptr.handler_),
-      pointer_(new (raw_ptr.pointer_) value_type(
-            a1, a2, a3, a4, a5, a6, a7, a8))
-  {
-    raw_ptr.pointer_ = 0;
-  }
-
-  // Destructor automatically deallocates memory, unless it has been released.
-  ~handler_ptr()
-  {
-    reset();
-  }
-
-  // Get the memory.
-  pointer_type get() const
-  {
-    return pointer_;
-  }
-
-  // Release ownership of the memory.
-  pointer_type release()
-  {
-    pointer_type tmp = pointer_;
-    pointer_ = 0;
-    return tmp;
-  }
-
-  // Explicitly destroy and deallocate the memory.
-  void reset()
-  {
-    if (pointer_)
-    {
-      pointer_->value_type::~value_type();
-      asio_handler_alloc_helpers::deallocate(
-          pointer_, value_size, handler_);
-      pointer_ = 0;
-    }
-  }
-
-private:
-  handler_type& handler_;
-  pointer_type pointer_;
-};
-
-} // namespace detail
-} // namespace asio
+#define ASIO_DEFINE_HANDLER_PTR(op) \
+  struct ptr \
+  { \
+    Handler* h; \
+    void* v; \
+    op* p; \
+    ~ptr() \
+    { \
+      reset(); \
+    } \
+    void reset() \
+    { \
+      if (p) \
+      { \
+        p->~op(); \
+        p = 0; \
+      } \
+      if (v) \
+      { \
+        asio_handler_alloc_helpers::deallocate(v, sizeof(op), *h); \
+        v = 0; \
+      } \
+    } \
+  } \
+  /**/
 
 #include "asio/detail/pop_options.hpp"
 

+ 6 - 8
ext/asio/asio/detail/handler_invoke_helpers.hpp

@@ -1,8 +1,8 @@
 //
-// handler_invoke_helpers.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/handler_invoke_helpers.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,15 +15,13 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <boost/detail/workaround.hpp>
 #include <boost/utility/addressof.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/handler_invoke_hook.hpp"
 
+#include "asio/detail/push_options.hpp"
+
 // Calls to asio_handler_invoke must be made from a namespace that does not
 // contain overloads of this function. The asio_handler_invoke_helpers
 // namespace is defined here for that purpose.

+ 20 - 15
ext/asio/asio/detail/hash_map.hpp

@@ -1,8 +1,8 @@
 //
-// hash_map.hpp
-// ~~~~~~~~~~~~
+// detail/hash_map.hpp
+// ~~~~~~~~~~~~~~~~~~~
 //
-// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2011 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)
@@ -15,33 +15,38 @@
 # pragma once
 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
 #include <cassert>
 #include <list>
 #include <utility>
-#include <boost/functional/hash.hpp>
-#include "asio/detail/pop_options.hpp"
-
 #include "asio/detail/noncopyable.hpp"
-#include "asio/detail/socket_types.hpp"
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# include "asio/detail/socket_types.hpp"
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#include "asio/detail/push_options.hpp"
 
 namespace asio {
 namespace detail {
 
-template <typename T>
-inline std::size_t calculate_hash_value(const T& t)
+inline std::size_t calculate_hash_value(int i)
+{
+  return static_cast<std::size_t>(i);
+}
+
+inline std::size_t calculate_hash_value(void* p)
 {
-  return boost::hash_value(t);
+  return reinterpret_cast<std::size_t>(p)
+    + (reinterpret_cast<std::size_t>(p) >> 3);
 }
 
-#if defined(_WIN64)
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
 inline std::size_t calculate_hash_value(SOCKET s)
 {
   return static_cast<std::size_t>(s);
 }
-#endif // defined(_WIN64)
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
 
 // Note: assumes K and V are POD types.
 template <typename K, typename V>

+ 382 - 0
ext/asio/asio/detail/impl/descriptor_ops.ipp

@@ -0,0 +1,382 @@
+//
+// detail/impl/descriptor_ops.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
+#define ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <cerrno>
+#include "asio/detail/descriptor_ops.hpp"
+#include "asio/error.hpp"
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+namespace descriptor_ops {
+
+ASIO_DECL
+int open(const char* path, int flags, asio::error_code& ec)
+{
+  errno = 0;
+  int result = error_wrapper(::open(path, flags), ec);
+  if (result >= 0)
+    ec = asio::error_code();
+  return result;
+}
+
+ASIO_DECL
+int close(int d, state_type& state, asio::error_code& ec)
+{
+  int result = 0;
+  if (d != -1)
+  {
+    if (state & internal_non_blocking)
+    {
+#if defined(__SYMBIAN32__)
+      int flags = ::fcntl(d, F_GETFL, 0);
+      if (flags >= 0)
+        ::fcntl(d, F_SETFL, flags & ~O_NONBLOCK);
+#else // defined(__SYMBIAN32__)
+      ioctl_arg_type arg = 0;
+      ::ioctl(d, FIONBIO, &arg);
+#endif // defined(__SYMBIAN32__)
+      state &= ~internal_non_blocking;
+    }
+
+    errno = 0;
+    result = error_wrapper(::close(d), ec);
+  }
+
+  if (result == 0)
+    ec = asio::error_code();
+  return result;
+}
+
+ASIO_DECL
+bool set_internal_non_blocking(int d,
+    state_type& state, asio::error_code& ec)
+{
+  if (d == -1)
+  {
+    ec = asio::error::bad_descriptor;
+    return false;
+  }
+
+  errno = 0;
+#if defined(__SYMBIAN32__)
+  int result = error_wrapper(::fcntl(d, F_GETFL, 0), ec);
+  if (result >= 0)
+  {
+    errno = 0;
+    result = error_wrapper(::fcntl(d, F_SETFL, result | O_NONBLOCK), ec);
+  }
+#else // defined(__SYMBIAN32__)
+  ioctl_arg_type arg = 1;
+  int result = error_wrapper(::ioctl(d, FIONBIO, &arg), ec);
+#endif // defined(__SYMBIAN32__)
+
+  if (result >= 0)
+  {
+    ec = asio::error_code();
+    state |= internal_non_blocking;
+    return true;
+  }
+
+  return false;
+}
+
+ASIO_DECL
+std::size_t sync_read(int d, state_type state, buf* bufs,
+    std::size_t count, bool all_empty, asio::error_code& ec)
+{
+  if (d == -1)
+  {
+    ec = asio::error::bad_descriptor;
+    return 0;
+  }
+
+  // A request to read 0 bytes on a stream is a no-op.
+  if (all_empty)
+  {
+    ec = asio::error_code();
+    return 0;
+  }
+
+  // Read some data.
+  for (;;)
+  {
+    // Try to complete the operation without blocking.
+    errno = 0;
+    int bytes = error_wrapper(::readv(d, bufs, static_cast<int>(count)), ec);
+
+    // Check if operation succeeded.
+    if (bytes > 0)
+      return bytes;
+
+    // Check for EOF.
+    if (bytes == 0)
+    {
+      ec = asio::error::eof;
+      return 0;
+    }
+
+    // Operation failed.
+    if ((state & user_set_non_blocking)
+        || (ec != asio::error::would_block
+          && ec != asio::error::try_again))
+      return 0;
+
+    // Wait for descriptor to become ready.
+    if (descriptor_ops::poll_read(d, ec) < 0)
+      return 0;
+  }
+}
+
+ASIO_DECL
+bool non_blocking_read(int d, buf* bufs, std::size_t count,
+    asio::error_code& ec, std::size_t& bytes_transferred)
+{
+  for (;;)
+  {
+    // Read some data.
+    errno = 0;
+    int bytes = error_wrapper(::readv(d, bufs, static_cast<int>(count)), ec);
+
+    // Check for end of stream.
+    if (bytes == 0)
+    {
+      ec = asio::error::eof;
+      return true;
+    }
+
+    // Retry operation if interrupted by signal.
+    if (ec == asio::error::interrupted)
+      continue;
+
+    // Check if we need to run the operation again.
+    if (ec == asio::error::would_block
+        || ec == asio::error::try_again)
+      return false;
+
+    // Operation is complete.
+    if (bytes > 0)
+    {
+      ec = asio::error_code();
+      bytes_transferred = bytes;
+    }
+    else
+      bytes_transferred = 0;
+
+    return true;
+  }
+}
+
+ASIO_DECL
+std::size_t sync_write(int d, state_type state, const buf* bufs,
+    std::size_t count, bool all_empty, asio::error_code& ec)
+{
+  if (d == -1)
+  {
+    ec = asio::error::bad_descriptor;
+    return 0;
+  }
+
+  // A request to write 0 bytes on a stream is a no-op.
+  if (all_empty)
+  {
+    ec = asio::error_code();
+    return 0;
+  }
+
+  // Write some data.
+  for (;;)
+  {
+    // Try to complete the operation without blocking.
+    errno = 0;
+    int bytes = error_wrapper(::writev(d, bufs, static_cast<int>(count)), ec);
+
+    // Check if operation succeeded.
+    if (bytes > 0)
+      return bytes;
+
+    // Operation failed.
+    if ((state & user_set_non_blocking)
+        || (ec != asio::error::would_block
+          && ec != asio::error::try_again))
+      return 0;
+
+    // Wait for descriptor to become ready.
+    if (descriptor_ops::poll_write(d, ec) < 0)
+      return 0;
+  }
+}
+
+ASIO_DECL
+bool non_blocking_write(int d, const buf* bufs, std::size_t count,
+    asio::error_code& ec, std::size_t& bytes_transferred)
+{
+  for (;;)
+  {
+    // Write some data.
+    errno = 0;
+    int bytes = error_wrapper(::writev(d, bufs, static_cast<int>(count)), ec);
+
+    // Retry operation if interrupted by signal.
+    if (ec == asio::error::interrupted)
+      continue;
+
+    // Check if we need to run the operation again.
+    if (ec == asio::error::would_block
+        || ec == asio::error::try_again)
+      return false;
+
+    // Operation is complete.
+    if (bytes >= 0)
+    {
+      ec = asio::error_code();
+      bytes_transferred = bytes;
+    }
+    else
+      bytes_transferred = 0;
+
+    return true;
+  }
+}
+
+ASIO_DECL
+int ioctl(int d, state_type& state, long cmd,
+    ioctl_arg_type* arg, asio::error_code& ec)
+{
+  if (d == -1)
+  {
+    ec = asio::error::bad_descriptor;
+    return -1;
+  }
+
+  errno = 0;
+  int result = error_wrapper(::ioctl(d, cmd, arg), ec);
+
+  if (result >= 0)
+  {
+    ec = asio::error_code();
+
+    // When updating the non-blocking mode we always perform the ioctl syscall,
+    // even if the flags would otherwise indicate that the descriptor is
+    // already in the correct state. This ensures that the underlying
+    // descriptor is put into the state that has been requested by the user. If
+    // the ioctl syscall was successful then we need to update the flags to
+    // match.
+    if (cmd == static_cast<long>(FIONBIO))
+    {
+      if (*arg)
+      {
+        state |= user_set_non_blocking;
+      }
+      else
+      {
+        // Clearing the non-blocking mode always overrides any internally-set
+        // non-blocking flag. Any subsequent asynchronous operations will need
+        // to re-enable non-blocking I/O.
+        state &= ~(user_set_non_blocking | internal_non_blocking);
+      }
+    }
+  }
+
+  return result;
+}
+
+ASIO_DECL
+int fcntl(int d, long cmd, asio::error_code& ec)
+{
+  if (d == -1)
+  {
+    ec = asio::error::bad_descriptor;
+    return -1;
+  }
+
+  errno = 0;
+  int result = error_wrapper(::fcntl(d, cmd), ec);
+  if (result != -1)
+    ec = asio::error_code();
+  return result;
+}
+
+ASIO_DECL
+int fcntl(int d, long cmd, long arg, asio::error_code& ec)
+{
+  if (d == -1)
+  {
+    ec = asio::error::bad_descriptor;
+    return -1;
+  }
+
+  errno = 0;
+  int result = error_wrapper(::fcntl(d, cmd, arg), ec);
+  if (result != -1)
+    ec = asio::error_code();
+  return result;
+}
+
+ASIO_DECL
+int poll_read(int d, asio::error_code& ec)
+{
+  if (d == -1)
+  {
+    ec = asio::error::bad_descriptor;
+    return -1;
+  }
+
+  pollfd fds;
+  fds.fd = d;
+  fds.events = POLLIN;
+  fds.revents = 0;
+  errno = 0;
+  int result = error_wrapper(::poll(&fds, 1, -1), ec);
+  if (result >= 0)
+    ec = asio::error_code();
+  return result;
+}
+
+ASIO_DECL
+int poll_write(int d, asio::error_code& ec)
+{
+  if (d == -1)
+  {
+    ec = asio::error::bad_descriptor;
+    return -1;
+  }
+
+  pollfd fds;
+  fds.fd = d;
+  fds.events = POLLOUT;
+  fds.revents = 0;
+  errno = 0;
+  int result = error_wrapper(::poll(&fds, 1, -1), ec);
+  if (result >= 0)
+    ec = asio::error_code();
+  return result;
+}
+
+} // namespace descriptor_ops
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#endif // ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP

+ 77 - 0
ext/asio/asio/detail/impl/dev_poll_reactor.hpp

@@ -0,0 +1,77 @@
+//
+// detail/impl/dev_poll_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_HPP
+#define ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_DEV_POLL)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Time_Traits>
+void dev_poll_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)
+{
+  do_add_timer_queue(queue);
+}
+
+template <typename Time_Traits>
+void dev_poll_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue)
+{
+  do_remove_timer_queue(queue);
+}
+
+template <typename Time_Traits>
+void dev_poll_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
+    const typename Time_Traits::time_type& time,
+    typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  if (shutdown_)
+  {
+    io_service_.post_immediate_completion(op);
+    return;
+  }
+
+  bool earliest = queue.enqueue_timer(time, timer, op);
+  io_service_.work_started();
+  if (earliest)
+    interrupter_.interrupt();
+}
+
+template <typename Time_Traits>
+std::size_t dev_poll_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
+    typename timer_queue<Time_Traits>::per_timer_data& timer)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  op_queue<operation> ops;
+  std::size_t n = queue.cancel_timer(timer, ops);
+  lock.unlock();
+  io_service_.post_deferred_completions(ops);
+  return n;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_DEV_POLL)
+
+#endif // ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_HPP

+ 338 - 0
ext/asio/asio/detail/impl/dev_poll_reactor.ipp

@@ -0,0 +1,338 @@
+//
+// detail/impl/dev_poll_reactor.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_IPP
+#define ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_DEV_POLL)
+
+#include "asio/detail/dev_poll_reactor.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+dev_poll_reactor::dev_poll_reactor(asio::io_service& io_service)
+  : asio::detail::service_base<dev_poll_reactor>(io_service),
+    io_service_(use_service<io_service_impl>(io_service)),
+    mutex_(),
+    dev_poll_fd_(do_dev_poll_create()),
+    interrupter_(),
+    shutdown_(false)
+{
+  // Add the interrupter's descriptor to /dev/poll.
+  ::pollfd ev = { 0 };
+  ev.fd = interrupter_.read_descriptor();
+  ev.events = POLLIN | POLLERR;
+  ev.revents = 0;
+  ::write(dev_poll_fd_, &ev, sizeof(ev));
+}
+
+dev_poll_reactor::~dev_poll_reactor()
+{
+  shutdown_service();
+  ::close(dev_poll_fd_);
+}
+
+void dev_poll_reactor::shutdown_service()
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  shutdown_ = true;
+  lock.unlock();
+
+  op_queue<operation> ops;
+
+  for (int i = 0; i < max_ops; ++i)
+    op_queue_[i].get_all_operations(ops);
+
+  timer_queues_.get_all_timers(ops);
+} 
+
+void dev_poll_reactor::init_task()
+{
+  io_service_.init_task();
+}
+
+int dev_poll_reactor::register_descriptor(socket_type, per_descriptor_data&)
+{
+  return 0;
+}
+
+void dev_poll_reactor::start_op(int op_type, socket_type descriptor,
+    dev_poll_reactor::per_descriptor_data&,
+    reactor_op* op, bool allow_speculative)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  if (shutdown_)
+  {
+    post_immediate_completion(op);
+    return;
+  }
+
+  if (allow_speculative)
+  {
+    if (op_type != read_op || !op_queue_[except_op].has_operation(descriptor))
+    {
+      if (!op_queue_[op_type].has_operation(descriptor))
+      {
+        if (op->perform())
+        {
+          lock.unlock();
+          io_service_.post_immediate_completion(op);
+          return;
+        }
+      }
+    }
+  }
+
+  bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
+  io_service_.work_started();
+  if (first)
+  {
+    ::pollfd& ev = add_pending_event_change(descriptor);
+    ev.events = POLLERR | POLLHUP;
+    if (op_type == read_op
+        || op_queue_[read_op].has_operation(descriptor))
+      ev.events |= POLLIN;
+    if (op_type == write_op
+        || op_queue_[write_op].has_operation(descriptor))
+      ev.events |= POLLOUT;
+    if (op_type == except_op
+        || op_queue_[except_op].has_operation(descriptor))
+      ev.events |= POLLPRI;
+    interrupter_.interrupt();
+  }
+}
+
+void dev_poll_reactor::cancel_ops(socket_type descriptor,
+    dev_poll_reactor::per_descriptor_data&)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
+}
+
+void dev_poll_reactor::close_descriptor(socket_type descriptor,
+    dev_poll_reactor::per_descriptor_data&)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  // Remove the descriptor from /dev/poll.
+  ::pollfd& ev = add_pending_event_change(descriptor);
+  ev.events = POLLREMOVE;
+  interrupter_.interrupt();
+
+  // Cancel any outstanding operations associated with the descriptor.
+  cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
+}
+
+void dev_poll_reactor::run(bool block, op_queue<operation>& ops)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  // We can return immediately if there's no work to do and the reactor is
+  // not supposed to block.
+  if (!block && op_queue_[read_op].empty() && op_queue_[write_op].empty()
+      && op_queue_[except_op].empty() && timer_queues_.all_empty())
+    return;
+
+  // Write the pending event registration changes to the /dev/poll descriptor.
+  std::size_t events_size = sizeof(::pollfd) * pending_event_changes_.size();
+  if (events_size > 0)
+  {
+    errno = 0;
+    int result = ::write(dev_poll_fd_,
+        &pending_event_changes_[0], events_size);
+    if (result != static_cast<int>(events_size))
+    {
+      asio::error_code ec = asio::error_code(
+          errno, asio::error::get_system_category());
+      for (std::size_t i = 0; i < pending_event_changes_.size(); ++i)
+      {
+        int descriptor = pending_event_changes_[i].fd;
+        for (int j = 0; j < max_ops; ++j)
+          op_queue_[j].cancel_operations(descriptor, ops, ec);
+      }
+    }
+    pending_event_changes_.clear();
+    pending_event_change_index_.clear();
+  }
+
+  int timeout = block ? get_timeout() : 0;
+  lock.unlock();
+
+  // Block on the /dev/poll descriptor.
+  ::pollfd events[128] = { { 0 } };
+  ::dvpoll dp = { 0 };
+  dp.dp_fds = events;
+  dp.dp_nfds = 128;
+  dp.dp_timeout = timeout;
+  int num_events = ::ioctl(dev_poll_fd_, DP_POLL, &dp);
+
+  lock.lock();
+
+  // Dispatch the waiting events.
+  for (int i = 0; i < num_events; ++i)
+  {
+    int descriptor = events[i].fd;
+    if (descriptor == interrupter_.read_descriptor())
+    {
+      interrupter_.reset();
+    }
+    else
+    {
+      bool more_reads = false;
+      bool more_writes = false;
+      bool more_except = false;
+
+      // Exception operations must be processed first to ensure that any
+      // out-of-band data is read before normal data.
+      if (events[i].events & (POLLPRI | POLLERR | POLLHUP))
+        more_except =
+          op_queue_[except_op].perform_operations(descriptor, ops);
+      else
+        more_except = op_queue_[except_op].has_operation(descriptor);
+
+      if (events[i].events & (POLLIN | POLLERR | POLLHUP))
+        more_reads = op_queue_[read_op].perform_operations(descriptor, ops);
+      else
+        more_reads = op_queue_[read_op].has_operation(descriptor);
+
+      if (events[i].events & (POLLOUT | POLLERR | POLLHUP))
+        more_writes = op_queue_[write_op].perform_operations(descriptor, ops);
+      else
+        more_writes = op_queue_[write_op].has_operation(descriptor);
+
+      if ((events[i].events & (POLLERR | POLLHUP)) != 0
+            && !more_except && !more_reads && !more_writes)
+      {
+        // If we have an event and no operations associated with the
+        // descriptor then we need to delete the descriptor from /dev/poll.
+        // The poll operation can produce POLLHUP or POLLERR events when there
+        // is no operation pending, so if we do not remove the descriptor we
+        // can end up in a tight polling loop.
+        ::pollfd ev = { 0 };
+        ev.fd = descriptor;
+        ev.events = POLLREMOVE;
+        ev.revents = 0;
+        ::write(dev_poll_fd_, &ev, sizeof(ev));
+      }
+      else
+      {
+        ::pollfd ev = { 0 };
+        ev.fd = descriptor;
+        ev.events = POLLERR | POLLHUP;
+        if (more_reads)
+          ev.events |= POLLIN;
+        if (more_writes)
+          ev.events |= POLLOUT;
+        if (more_except)
+          ev.events |= POLLPRI;
+        ev.revents = 0;
+        int result = ::write(dev_poll_fd_, &ev, sizeof(ev));
+        if (result != sizeof(ev))
+        {
+          asio::error_code ec(errno,
+              asio::error::get_system_category());
+          for (int j = 0; j < max_ops; ++j)
+            op_queue_[j].cancel_operations(descriptor, ops, ec);
+        }
+      }
+    }
+  }
+  timer_queues_.get_ready_timers(ops);
+}
+
+void dev_poll_reactor::interrupt()
+{
+  interrupter_.interrupt();
+}
+
+int dev_poll_reactor::do_dev_poll_create()
+{
+  int fd = ::open("/dev/poll", O_RDWR);
+  if (fd == -1)
+  {
+    asio::error_code ec(errno,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "/dev/poll");
+  }
+  return fd;
+}
+
+void dev_poll_reactor::do_add_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(mutex_);
+  timer_queues_.insert(&queue);
+}
+
+void dev_poll_reactor::do_remove_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(mutex_);
+  timer_queues_.erase(&queue);
+}
+
+int dev_poll_reactor::get_timeout()
+{
+  // By default we will wait no longer than 5 minutes. This will ensure that
+  // any changes to the system clock are detected after no longer than this.
+  return timer_queues_.wait_duration_msec(5 * 60 * 1000);
+}
+
+void dev_poll_reactor::cancel_ops_unlocked(socket_type descriptor,
+    const asio::error_code& ec)
+{
+  bool need_interrupt = false;
+  op_queue<operation> ops;
+  for (int i = 0; i < max_ops; ++i)
+    need_interrupt = op_queue_[i].cancel_operations(
+        descriptor, ops, ec) || need_interrupt;
+  io_service_.post_deferred_completions(ops);
+  if (need_interrupt)
+    interrupter_.interrupt();
+}
+
+::pollfd& dev_poll_reactor::add_pending_event_change(int descriptor)
+{
+  hash_map<int, std::size_t>::iterator iter
+    = pending_event_change_index_.find(descriptor);
+  if (iter == pending_event_change_index_.end())
+  {
+    std::size_t index = pending_event_changes_.size();
+    pending_event_changes_.reserve(pending_event_changes_.size() + 1);
+    pending_event_change_index_.insert(std::make_pair(descriptor, index));
+    pending_event_changes_.push_back(::pollfd());
+    pending_event_changes_[index].fd = descriptor;
+    pending_event_changes_[index].revents = 0;
+    return pending_event_changes_[index];
+  }
+  else
+  {
+    return pending_event_changes_[iter->second];
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_DEV_POLL)
+
+#endif // ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_IPP

+ 75 - 0
ext/asio/asio/detail/impl/epoll_reactor.hpp

@@ -0,0 +1,75 @@
+//
+// detail/impl/epoll_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_EPOLL_REACTOR_HPP
+#define ASIO_DETAIL_IMPL_EPOLL_REACTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#if defined(ASIO_HAS_EPOLL)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Time_Traits>
+void epoll_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)
+{
+  do_add_timer_queue(queue);
+}
+
+template <typename Time_Traits>
+void epoll_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue)
+{
+  do_remove_timer_queue(queue);
+}
+
+template <typename Time_Traits>
+void epoll_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
+    const typename Time_Traits::time_type& time,
+    typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
+{
+  mutex::scoped_lock lock(mutex_);
+
+  if (shutdown_)
+  {
+    io_service_.post_immediate_completion(op);
+    return;
+  }
+
+  bool earliest = queue.enqueue_timer(time, timer, op);
+  io_service_.work_started();
+  if (earliest)
+    update_timeout();
+}
+
+template <typename Time_Traits>
+std::size_t epoll_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
+    typename timer_queue<Time_Traits>::per_timer_data& timer)
+{
+  mutex::scoped_lock lock(mutex_);
+  op_queue<operation> ops;
+  std::size_t n = queue.cancel_timer(timer, ops);
+  lock.unlock();
+  io_service_.post_deferred_completions(ops);
+  return n;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_EPOLL)
+
+#endif // ASIO_DETAIL_IMPL_EPOLL_REACTOR_HPP

+ 390 - 0
ext/asio/asio/detail/impl/epoll_reactor.ipp

@@ -0,0 +1,390 @@
+//
+// detail/impl/epoll_reactor.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP
+#define ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_EPOLL)
+
+#include <cstddef>
+#include <sys/epoll.h>
+#include "asio/detail/epoll_reactor.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#if defined(ASIO_HAS_TIMERFD)
+# include <sys/timerfd.h>
+#endif // defined(ASIO_HAS_TIMERFD)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+epoll_reactor::epoll_reactor(asio::io_service& io_service)
+  : asio::detail::service_base<epoll_reactor>(io_service),
+    io_service_(use_service<io_service_impl>(io_service)),
+    mutex_(),
+    epoll_fd_(do_epoll_create()),
+#if defined(ASIO_HAS_TIMERFD)
+    timer_fd_(timerfd_create(CLOCK_MONOTONIC, 0)),
+#else // defined(ASIO_HAS_TIMERFD)
+    timer_fd_(-1),
+#endif // defined(ASIO_HAS_TIMERFD)
+    interrupter_(),
+    shutdown_(false)
+{
+  // Add the interrupter's descriptor to epoll.
+  epoll_event ev = { 0, { 0 } };
+  ev.events = EPOLLIN | EPOLLERR | EPOLLET;
+  ev.data.ptr = &interrupter_;
+  epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev);
+  interrupter_.interrupt();
+
+  // Add the timer descriptor to epoll.
+  if (timer_fd_ != -1)
+  {
+    ev.events = EPOLLIN | EPOLLERR;
+    ev.data.ptr = &timer_fd_;
+    epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev);
+  }
+}
+
+epoll_reactor::~epoll_reactor()
+{
+  close(epoll_fd_);
+  if (timer_fd_ != -1)
+    close(timer_fd_);
+}
+
+void epoll_reactor::shutdown_service()
+{
+  mutex::scoped_lock lock(mutex_);
+  shutdown_ = true;
+  lock.unlock();
+
+  op_queue<operation> ops;
+
+  while (descriptor_state* state = registered_descriptors_.first())
+  {
+    for (int i = 0; i < max_ops; ++i)
+      ops.push(state->op_queue_[i]);
+    state->shutdown_ = true;
+    registered_descriptors_.free(state);
+  }
+
+  timer_queues_.get_all_timers(ops);
+}
+
+void epoll_reactor::init_task()
+{
+  io_service_.init_task();
+}
+
+int epoll_reactor::register_descriptor(socket_type descriptor,
+    epoll_reactor::per_descriptor_data& descriptor_data)
+{
+  mutex::scoped_lock lock(registered_descriptors_mutex_);
+
+  descriptor_data = registered_descriptors_.alloc();
+  descriptor_data->shutdown_ = false;
+
+  lock.unlock();
+
+  epoll_event ev = { 0, { 0 } };
+  ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLOUT | EPOLLPRI | EPOLLET;
+  ev.data.ptr = descriptor_data;
+  int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
+  if (result != 0)
+    return errno;
+
+  return 0;
+}
+
+void epoll_reactor::start_op(int op_type, socket_type descriptor,
+    epoll_reactor::per_descriptor_data& descriptor_data,
+    reactor_op* op, bool allow_speculative)
+{
+  if (!descriptor_data)
+  {
+    op->ec_ = asio::error::bad_descriptor;
+    post_immediate_completion(op);
+    return;
+  }
+
+  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
+  if (descriptor_data->shutdown_)
+  {
+    post_immediate_completion(op);
+    return;
+  }
+
+  if (descriptor_data->op_queue_[op_type].empty())
+  {
+    if (allow_speculative
+        && (op_type != read_op
+          || descriptor_data->op_queue_[except_op].empty()))
+    {
+      if (op->perform())
+      {
+        descriptor_lock.unlock();
+        io_service_.post_immediate_completion(op);
+        return;
+      }
+    }
+    else
+    {
+      epoll_event ev = { 0, { 0 } };
+      ev.events = EPOLLIN | EPOLLERR | EPOLLHUP
+        | EPOLLOUT | EPOLLPRI | EPOLLET;
+      ev.data.ptr = descriptor_data;
+      epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
+    }
+  }
+
+  descriptor_data->op_queue_[op_type].push(op);
+  io_service_.work_started();
+}
+
+void epoll_reactor::cancel_ops(socket_type,
+    epoll_reactor::per_descriptor_data& descriptor_data)
+{
+  if (!descriptor_data)
+    return;
+
+  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
+  op_queue<operation> ops;
+  for (int i = 0; i < max_ops; ++i)
+  {
+    while (reactor_op* op = descriptor_data->op_queue_[i].front())
+    {
+      op->ec_ = asio::error::operation_aborted;
+      descriptor_data->op_queue_[i].pop();
+      ops.push(op);
+    }
+  }
+
+  descriptor_lock.unlock();
+
+  io_service_.post_deferred_completions(ops);
+}
+
+void epoll_reactor::close_descriptor(socket_type,
+    epoll_reactor::per_descriptor_data& descriptor_data)
+{
+  if (!descriptor_data)
+    return;
+
+  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+  mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
+
+  if (!descriptor_data->shutdown_)
+  {
+    // Remove the descriptor from the set of known descriptors. The descriptor
+    // will be automatically removed from the epoll set when it is closed.
+
+    op_queue<operation> ops;
+    for (int i = 0; i < max_ops; ++i)
+    {
+      while (reactor_op* op = descriptor_data->op_queue_[i].front())
+      {
+        op->ec_ = asio::error::operation_aborted;
+        descriptor_data->op_queue_[i].pop();
+        ops.push(op);
+      }
+    }
+
+    descriptor_data->shutdown_ = true;
+
+    descriptor_lock.unlock();
+
+    registered_descriptors_.free(descriptor_data);
+    descriptor_data = 0;
+
+    descriptors_lock.unlock();
+
+    io_service_.post_deferred_completions(ops);
+  }
+}
+
+void epoll_reactor::run(bool block, op_queue<operation>& ops)
+{
+  // Calculate a timeout only if timerfd is not used.
+  int timeout;
+  if (timer_fd_ != -1)
+    timeout = block ? -1 : 0;
+  else
+  {
+    mutex::scoped_lock lock(mutex_);
+    timeout = block ? get_timeout() : 0;
+  }
+
+  // Block on the epoll descriptor.
+  epoll_event events[128];
+  int num_events = epoll_wait(epoll_fd_, events, 128, timeout);
+
+#if defined(ASIO_HAS_TIMERFD)
+  bool check_timers = (timer_fd_ == -1);
+#else // defined(ASIO_HAS_TIMERFD)
+  bool check_timers = true;
+#endif // defined(ASIO_HAS_TIMERFD)
+
+  // Dispatch the waiting events.
+  for (int i = 0; i < num_events; ++i)
+  {
+    void* ptr = events[i].data.ptr;
+    if (ptr == &interrupter_)
+    {
+      // No need to reset the interrupter since we're leaving the descriptor
+      // in a ready-to-read state and relying on edge-triggered notifications
+      // to make it so that we only get woken up when the descriptor's epoll
+      // registration is updated.
+
+#if defined(ASIO_HAS_TIMERFD)
+      if (timer_fd_ == -1)
+        check_timers = true;
+#else // defined(ASIO_HAS_TIMERFD)
+      check_timers = true;
+#endif // defined(ASIO_HAS_TIMERFD)
+    }
+#if defined(ASIO_HAS_TIMERFD)
+    else if (ptr == &timer_fd_)
+    {
+      check_timers = true;
+    }
+#endif // defined(ASIO_HAS_TIMERFD)
+    else
+    {
+      descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);
+      mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
+      // Exception operations must be processed first to ensure that any
+      // out-of-band data is read before normal data.
+      static const int flag[max_ops] = { EPOLLIN, EPOLLOUT, EPOLLPRI };
+      for (int j = max_ops - 1; j >= 0; --j)
+      {
+        if (events[i].events & (flag[j] | EPOLLERR | EPOLLHUP))
+        {
+          while (reactor_op* op = descriptor_data->op_queue_[j].front())
+          {
+            if (op->perform())
+            {
+              descriptor_data->op_queue_[j].pop();
+              ops.push(op);
+            }
+            else
+              break;
+          }
+        }
+      }
+    }
+  }
+
+  if (check_timers)
+  {
+    mutex::scoped_lock common_lock(mutex_);
+    timer_queues_.get_ready_timers(ops);
+
+#if defined(ASIO_HAS_TIMERFD)
+    if (timer_fd_ != -1)
+    {
+      itimerspec new_timeout;
+      itimerspec old_timeout;
+      int flags = get_timeout(new_timeout);
+      timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);
+    }
+#endif // defined(ASIO_HAS_TIMERFD)
+  }
+}
+
+void epoll_reactor::interrupt()
+{
+  epoll_event ev = { 0, { 0 } };
+  ev.events = EPOLLIN | EPOLLERR | EPOLLET;
+  ev.data.ptr = &interrupter_;
+  epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, interrupter_.read_descriptor(), &ev);
+}
+
+int epoll_reactor::do_epoll_create()
+{
+  int fd = epoll_create(epoll_size);
+  if (fd == -1)
+  {
+    asio::error_code ec(errno,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "epoll");
+  }
+  return fd;
+}
+
+void epoll_reactor::do_add_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(mutex_);
+  timer_queues_.insert(&queue);
+}
+
+void epoll_reactor::do_remove_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(mutex_);
+  timer_queues_.erase(&queue);
+}
+
+void epoll_reactor::update_timeout()
+{
+#if defined(ASIO_HAS_TIMERFD)
+  if (timer_fd_ != -1)
+  {
+    itimerspec new_timeout;
+    itimerspec old_timeout;
+    int flags = get_timeout(new_timeout);
+    timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);
+    return;
+  }
+#endif // defined(ASIO_HAS_TIMERFD)
+  interrupt();
+}
+
+int epoll_reactor::get_timeout()
+{
+  // By default we will wait no longer than 5 minutes. This will ensure that
+  // any changes to the system clock are detected after no longer than this.
+  return timer_queues_.wait_duration_msec(5 * 60 * 1000);
+}
+
+#if defined(ASIO_HAS_TIMERFD)
+int epoll_reactor::get_timeout(itimerspec& ts)
+{
+  ts.it_interval.tv_sec = 0;
+  ts.it_interval.tv_nsec = 0;
+
+  long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
+  ts.it_value.tv_sec = usec / 1000000;
+  ts.it_value.tv_nsec = usec ? (usec % 1000000) * 1000 : 1;
+
+  return usec ? 0 : TFD_TIMER_ABSTIME;
+}
+#endif // defined(ASIO_HAS_TIMERFD)
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_EPOLL)
+
+#endif // ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP

+ 125 - 0
ext/asio/asio/detail/impl/eventfd_select_interrupter.ipp

@@ -0,0 +1,125 @@
+//
+// detail/impl/eventfd_select_interrupter.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Roelof Naude (roelof.naude at gmail 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP
+#define ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_EVENTFD)
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+# include <asm/unistd.h>
+#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+# include <sys/eventfd.h>
+#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+#include "asio/detail/eventfd_select_interrupter.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+eventfd_select_interrupter::eventfd_select_interrupter()
+{
+#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+  write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0);
+#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+  write_descriptor_ = read_descriptor_ = ::eventfd(0, 0);
+#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
+  if (read_descriptor_ != -1)
+  {
+    ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
+  }
+  else
+  {
+    int pipe_fds[2];
+    if (pipe(pipe_fds) == 0)
+    {
+      read_descriptor_ = pipe_fds[0];
+      ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
+      write_descriptor_ = pipe_fds[1];
+      ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
+    }
+    else
+    {
+      asio::error_code ec(errno,
+          asio::error::get_system_category());
+      asio::detail::throw_error(ec, "eventfd_select_interrupter");
+    }
+  }
+}
+
+eventfd_select_interrupter::~eventfd_select_interrupter()
+{
+  if (write_descriptor_ != -1 && write_descriptor_ != read_descriptor_)
+    ::close(write_descriptor_);
+  if (read_descriptor_ != -1)
+    ::close(read_descriptor_);
+}
+
+void eventfd_select_interrupter::interrupt()
+{
+  uint64_t counter(1UL);
+  int result = ::write(write_descriptor_, &counter, sizeof(uint64_t));
+  (void)result;
+}
+
+bool eventfd_select_interrupter::reset()
+{
+  if (write_descriptor_ == read_descriptor_)
+  {
+    for (;;)
+    {
+      // Only perform one read. The kernel maintains an atomic counter.
+      uint64_t counter(0);
+      errno = 0;
+      int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t));
+      if (bytes_read < 0 && errno == EINTR)
+        continue;
+      bool was_interrupted = (bytes_read > 0);
+      return was_interrupted;
+    }
+  }
+  else
+  {
+    for (;;)
+    {
+      // Clear all data from the pipe.
+      char data[1024];
+      int bytes_read = ::read(read_descriptor_, data, sizeof(data));
+      if (bytes_read < 0 && errno == EINTR)
+        continue;
+      bool was_interrupted = (bytes_read > 0);
+      while (bytes_read == sizeof(data))
+        bytes_read = ::read(read_descriptor_, data, sizeof(data));
+      return was_interrupted;
+    }
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_EVENTFD)
+
+#endif // ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP

+ 79 - 0
ext/asio/asio/detail/impl/kqueue_reactor.hpp

@@ -0,0 +1,79 @@
+//
+// detail/impl/kqueue_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005 Stefan Arentz (stefan at soze 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_KQUEUE_REACTOR_HPP
+#define ASIO_DETAIL_IMPL_KQUEUE_REACTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_KQUEUE)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Time_Traits>
+void kqueue_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)
+{
+  do_add_timer_queue(queue);
+}
+
+// Remove a timer queue from the reactor.
+template <typename Time_Traits>
+void kqueue_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue)
+{
+  do_remove_timer_queue(queue);
+}
+
+template <typename Time_Traits>
+void kqueue_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
+    const typename Time_Traits::time_type& time,
+    typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  if (shutdown_)
+  {
+    io_service_.post_immediate_completion(op);
+    return;
+  }
+
+  bool earliest = queue.enqueue_timer(time, timer, op);
+  io_service_.work_started();
+  if (earliest)
+    interrupt();
+}
+
+template <typename Time_Traits>
+std::size_t kqueue_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
+    typename timer_queue<Time_Traits>::per_timer_data& timer)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  op_queue<operation> ops;
+  std::size_t n = queue.cancel_timer(timer, ops);
+  lock.unlock();
+  io_service_.post_deferred_completions(ops);
+  return n;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_KQUEUE)
+
+#endif // ASIO_DETAIL_IMPL_KQUEUE_REACTOR_HPP

+ 385 - 0
ext/asio/asio/detail/impl/kqueue_reactor.ipp

@@ -0,0 +1,385 @@
+//
+// detail/impl/kqueue_reactor.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005 Stefan Arentz (stefan at soze 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_KQUEUE_REACTOR_IPP
+#define ASIO_DETAIL_IMPL_KQUEUE_REACTOR_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_KQUEUE)
+
+#include "asio/detail/kqueue_reactor.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+#if defined(__NetBSD__)
+# define ASIO_KQUEUE_EV_SET(ev, ident, filt, flags, fflags, data, udata) \
+    EV_SET(ev, ident, filt, flags, fflags, \
+      data, reinterpret_cast<intptr_t>(udata))
+#else
+# define ASIO_KQUEUE_EV_SET(ev, ident, filt, flags, fflags, data, udata) \
+    EV_SET(ev, ident, filt, flags, fflags, data, udata)
+#endif
+
+namespace asio {
+namespace detail {
+
+kqueue_reactor::kqueue_reactor(asio::io_service& io_service)
+  : asio::detail::service_base<kqueue_reactor>(io_service),
+    io_service_(use_service<io_service_impl>(io_service)),
+    mutex_(),
+    kqueue_fd_(do_kqueue_create()),
+    interrupter_(),
+    shutdown_(false)
+{
+  // The interrupter is put into a permanently readable state. Whenever we
+  // want to interrupt the blocked kevent call we register a one-shot read
+  // operation against the descriptor.
+  interrupter_.interrupt();
+}
+
+kqueue_reactor::~kqueue_reactor()
+{
+  close(kqueue_fd_);
+}
+
+void kqueue_reactor::shutdown_service()
+{
+  mutex::scoped_lock lock(mutex_);
+  shutdown_ = true;
+  lock.unlock();
+
+  op_queue<operation> ops;
+
+  while (descriptor_state* state = registered_descriptors_.first())
+  {
+    for (int i = 0; i < max_ops; ++i)
+      ops.push(state->op_queue_[i]);
+    state->shutdown_ = true;
+    registered_descriptors_.free(state);
+  }
+
+  timer_queues_.get_all_timers(ops);
+}
+
+void kqueue_reactor::init_task()
+{
+  io_service_.init_task();
+}
+
+int kqueue_reactor::register_descriptor(socket_type,
+    kqueue_reactor::per_descriptor_data& descriptor_data)
+{
+  mutex::scoped_lock lock(registered_descriptors_mutex_);
+
+  descriptor_data = registered_descriptors_.alloc();
+  descriptor_data->shutdown_ = false;
+
+  return 0;
+}
+
+void kqueue_reactor::start_op(int op_type, socket_type descriptor,
+    kqueue_reactor::per_descriptor_data& descriptor_data,
+    reactor_op* op, bool allow_speculative)
+{
+  if (!descriptor_data)
+  {
+    op->ec_ = asio::error::bad_descriptor;
+    post_immediate_completion(op);
+    return;
+  }
+
+  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
+  if (descriptor_data->shutdown_)
+  {
+    post_immediate_completion(op);
+    return;
+  }
+
+  bool first = descriptor_data->op_queue_[op_type].empty();
+  if (first)
+  {
+    if (allow_speculative)
+    {
+      if (op_type != read_op || descriptor_data->op_queue_[except_op].empty())
+      {
+        if (op->perform())
+        {
+          descriptor_lock.unlock();
+          io_service_.post_immediate_completion(op);
+          return;
+        }
+      }
+    }
+  }
+
+  descriptor_data->op_queue_[op_type].push(op);
+  io_service_.work_started();
+
+  if (first)
+  {
+    struct kevent event;
+    switch (op_type)
+    {
+    case read_op:
+      ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
+          EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
+      break;
+    case write_op:
+      ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_WRITE,
+          EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
+      break;
+    case except_op:
+      if (!descriptor_data->op_queue_[read_op].empty())
+        return; // Already registered for read events.
+      ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
+          EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data);
+      break;
+    }
+
+    if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
+    {
+      op->ec_ = asio::error_code(errno,
+          asio::error::get_system_category());
+      descriptor_data->op_queue_[op_type].pop();
+      io_service_.post_deferred_completion(op);
+    }
+  }
+}
+
+void kqueue_reactor::cancel_ops(socket_type,
+    kqueue_reactor::per_descriptor_data& descriptor_data)
+{
+  if (!descriptor_data)
+    return;
+
+  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
+  op_queue<operation> ops;
+  for (int i = 0; i < max_ops; ++i)
+  {
+    while (reactor_op* op = descriptor_data->op_queue_[i].front())
+    {
+      op->ec_ = asio::error::operation_aborted;
+      descriptor_data->op_queue_[i].pop();
+      ops.push(op);
+    }
+  }
+
+  descriptor_lock.unlock();
+
+  io_service_.post_deferred_completions(ops);
+}
+
+void kqueue_reactor::close_descriptor(socket_type,
+    kqueue_reactor::per_descriptor_data& descriptor_data)
+{
+  if (!descriptor_data)
+    return;
+
+  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+  mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
+
+  if (!descriptor_data->shutdown_)
+  {
+    // Remove the descriptor from the set of known descriptors. The descriptor
+    // will be automatically removed from the kqueue set when it is closed.
+
+    op_queue<operation> ops;
+    for (int i = 0; i < max_ops; ++i)
+    {
+      while (reactor_op* op = descriptor_data->op_queue_[i].front())
+      {
+        op->ec_ = asio::error::operation_aborted;
+        descriptor_data->op_queue_[i].pop();
+        ops.push(op);
+      }
+    }
+
+    descriptor_data->shutdown_ = true;
+
+    descriptor_lock.unlock();
+
+    registered_descriptors_.free(descriptor_data);
+    descriptor_data = 0;
+
+    descriptors_lock.unlock();
+
+    io_service_.post_deferred_completions(ops);
+  }
+}
+
+void kqueue_reactor::run(bool block, op_queue<operation>& ops)
+{
+  mutex::scoped_lock lock(mutex_);
+
+  // Determine how long to block while waiting for events.
+  timespec timeout_buf = { 0, 0 };
+  timespec* timeout = block ? get_timeout(timeout_buf) : &timeout_buf;
+
+  lock.unlock();
+
+  // Block on the kqueue descriptor.
+  struct kevent events[128];
+  int num_events = kevent(kqueue_fd_, 0, 0, events, 128, timeout);
+
+  // Dispatch the waiting events.
+  for (int i = 0; i < num_events; ++i)
+  {
+    int descriptor = events[i].ident;
+    void* ptr = reinterpret_cast<void*>(events[i].udata);
+    if (ptr == &interrupter_)
+    {
+      // No need to reset the interrupter since we're leaving the descriptor
+      // in a ready-to-read state and relying on one-shot notifications.
+    }
+    else
+    {
+      descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);
+      mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
+
+      // Exception operations must be processed first to ensure that any
+      // out-of-band data is read before normal data.
+#if defined(__NetBSD__)
+      static const unsigned int filter[max_ops] =
+#else
+      static const int filter[max_ops] =
+#endif
+        { EVFILT_READ, EVFILT_WRITE, EVFILT_READ };
+      for (int j = max_ops - 1; j >= 0; --j)
+      {
+        if (events[i].filter == filter[j])
+        {
+          if (j != except_op || events[i].flags & EV_OOBAND)
+          {
+            while (reactor_op* op = descriptor_data->op_queue_[j].front())
+            {
+              if (events[i].flags & EV_ERROR)
+              {
+                op->ec_ = asio::error_code(events[i].data,
+                    asio::error::get_system_category());
+                descriptor_data->op_queue_[j].pop();
+                ops.push(op);
+              }
+              if (op->perform())
+              {
+                descriptor_data->op_queue_[j].pop();
+                ops.push(op);
+              }
+              else
+                break;
+            }
+          }
+        }
+      }
+
+      // Renew registration for event notifications.
+      struct kevent event;
+      switch (events[i].filter)
+      {
+      case EVFILT_READ:
+        if (!descriptor_data->op_queue_[read_op].empty())
+          ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
+              EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
+        else if (!descriptor_data->op_queue_[except_op].empty())
+          ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
+              EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data);
+        else
+          continue;
+      case EVFILT_WRITE:
+        if (!descriptor_data->op_queue_[write_op].empty())
+          ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_WRITE,
+              EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
+        else
+          continue;
+      default:
+        break;
+      }
+      if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
+      {
+        asio::error_code error(errno,
+            asio::error::get_system_category());
+        for (int j = 0; j < max_ops; ++j)
+        {
+          while (reactor_op* op = descriptor_data->op_queue_[j].front())
+          {
+            op->ec_ = error;
+            descriptor_data->op_queue_[j].pop();
+            ops.push(op);
+          }
+        }
+      }
+    }
+  }
+
+  lock.lock();
+  timer_queues_.get_ready_timers(ops);
+}
+
+void kqueue_reactor::interrupt()
+{
+  struct kevent event;
+  ASIO_KQUEUE_EV_SET(&event, interrupter_.read_descriptor(),
+      EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &interrupter_);
+  ::kevent(kqueue_fd_, &event, 1, 0, 0, 0);
+}
+
+int kqueue_reactor::do_kqueue_create()
+{
+  int fd = ::kqueue();
+  if (fd == -1)
+  {
+    asio::error_code ec(errno,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "kqueue");
+  }
+  return fd;
+}
+
+void kqueue_reactor::do_add_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(mutex_);
+  timer_queues_.insert(&queue);
+}
+
+void kqueue_reactor::do_remove_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(mutex_);
+  timer_queues_.erase(&queue);
+}
+
+timespec* kqueue_reactor::get_timeout(timespec& ts)
+{
+  // By default we will wait no longer than 5 minutes. This will ensure that
+  // any changes to the system clock are detected after no longer than this.
+  long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
+  ts.tv_sec = usec / 1000000;
+  ts.tv_nsec = (usec % 1000000) * 1000;
+  return &ts;
+}
+
+} // namespace detail
+} // namespace asio
+
+#undef ASIO_KQUEUE_EV_SET
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_KQUEUE)
+
+#endif // ASIO_DETAIL_IMPL_KQUEUE_REACTOR_IPP

+ 96 - 0
ext/asio/asio/detail/impl/pipe_select_interrupter.ipp

@@ -0,0 +1,96 @@
+//
+// detail/impl/pipe_select_interrupter.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP
+#define ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if !defined(BOOST_WINDOWS)
+#if !defined(__CYGWIN__)
+#if !defined(__SYMBIAN32__)
+#if !defined(ASIO_HAS_EVENTFD)
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include "asio/detail/pipe_select_interrupter.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+pipe_select_interrupter::pipe_select_interrupter()
+{
+  int pipe_fds[2];
+  if (pipe(pipe_fds) == 0)
+  {
+    read_descriptor_ = pipe_fds[0];
+    ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
+    write_descriptor_ = pipe_fds[1];
+    ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
+  }
+  else
+  {
+    asio::error_code ec(errno,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "pipe_select_interrupter");
+  }
+}
+
+pipe_select_interrupter::~pipe_select_interrupter()
+{
+  if (read_descriptor_ != -1)
+    ::close(read_descriptor_);
+  if (write_descriptor_ != -1)
+    ::close(write_descriptor_);
+}
+
+void pipe_select_interrupter::interrupt()
+{
+  char byte = 0;
+  int result = ::write(write_descriptor_, &byte, 1);
+  (void)result;
+}
+
+bool pipe_select_interrupter::reset()
+{
+  for (;;)
+  {
+    char data[1024];
+    int bytes_read = ::read(read_descriptor_, data, sizeof(data));
+    if (bytes_read < 0 && errno == EINTR)
+      continue;
+    bool was_interrupted = (bytes_read > 0);
+    while (bytes_read == sizeof(data))
+      bytes_read = ::read(read_descriptor_, data, sizeof(data));
+    return was_interrupted;
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(ASIO_HAS_EVENTFD)
+#endif // !defined(__SYMBIAN32__)
+#endif // !defined(__CYGWIN__)
+#endif // !defined(BOOST_WINDOWS)
+
+#endif // ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP

+ 46 - 0
ext/asio/asio/detail/impl/posix_event.ipp

@@ -0,0 +1,46 @@
+//
+// detail/impl/posix_event.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_POSIX_EVENT_IPP
+#define ASIO_DETAIL_IMPL_POSIX_EVENT_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
+#include "asio/detail/posix_event.hpp"
+#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+posix_event::posix_event()
+  : signalled_(false)
+{
+  int error = ::pthread_cond_init(&cond_, 0);
+  asio::error_code ec(error,
+      asio::error::get_system_category());
+  asio::detail::throw_error(ec, "event");
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
+#endif // ASIO_DETAIL_IMPL_POSIX_EVENT_IPP

+ 46 - 0
ext/asio/asio/detail/impl/posix_mutex.ipp

@@ -0,0 +1,46 @@
+//
+// detail/impl/posix_mutex.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_POSIX_MUTEX_IPP
+#define ASIO_DETAIL_IMPL_POSIX_MUTEX_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
+#include "asio/detail/posix_mutex.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+posix_mutex::posix_mutex()
+{
+  int error = ::pthread_mutex_init(&mutex_, 0);
+  asio::error_code ec(error,
+      asio::error::get_system_category());
+  asio::detail::throw_error(ec, "mutex");
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
+#endif // ASIO_DETAIL_IMPL_POSIX_MUTEX_IPP

+ 74 - 0
ext/asio/asio/detail/impl/posix_thread.ipp

@@ -0,0 +1,74 @@
+//
+// detail/impl/posix_thread.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_POSIX_THREAD_IPP
+#define ASIO_DETAIL_IMPL_POSIX_THREAD_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
+#include "asio/detail/posix_thread.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+posix_thread::~posix_thread()
+{
+  if (!joined_)
+    ::pthread_detach(thread_);
+}
+
+void posix_thread::join()
+{
+  if (!joined_)
+  {
+    ::pthread_join(thread_, 0);
+    joined_ = true;
+  }
+}
+
+void posix_thread::start_thread(func_base* arg)
+{
+  int error = ::pthread_create(&thread_, 0,
+        asio_detail_posix_thread_function, arg);
+  if (error != 0)
+  {
+    delete arg;
+    asio::error_code ec(error,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "thread");
+  }
+}
+
+void* asio_detail_posix_thread_function(void* arg)
+{
+  posix_thread::auto_func_base_ptr func = {
+      static_cast<posix_thread::func_base*>(arg) };
+  func.ptr->run();
+  return 0;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
+#endif // ASIO_DETAIL_IMPL_POSIX_THREAD_IPP

+ 46 - 0
ext/asio/asio/detail/impl/posix_tss_ptr.ipp

@@ -0,0 +1,46 @@
+//
+// detail/impl/posix_tss_ptr.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_POSIX_TSS_PTR_IPP
+#define ASIO_DETAIL_IMPL_POSIX_TSS_PTR_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
+#include "asio/detail/posix_tss_ptr.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+void posix_tss_ptr_create(pthread_key_t& key)
+{
+  int error = ::pthread_key_create(&key, 0);
+  asio::error_code ec(error,
+      asio::error::get_system_category());
+  asio::detail::throw_error(ec, "tss");
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
+#endif // ASIO_DETAIL_IMPL_POSIX_TSS_PTR_IPP

+ 136 - 0
ext/asio/asio/detail/impl/reactive_descriptor_service.ipp

@@ -0,0 +1,136 @@
+//
+// detail/impl/reactive_descriptor_service.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP
+#define ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include "asio/error.hpp"
+#include "asio/detail/reactive_descriptor_service.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+reactive_descriptor_service::reactive_descriptor_service(
+    asio::io_service& io_service)
+  : reactor_(asio::use_service<reactor>(io_service))
+{
+  reactor_.init_task();
+}
+
+void reactive_descriptor_service::shutdown_service()
+{
+}
+
+void reactive_descriptor_service::construct(
+    reactive_descriptor_service::implementation_type& impl)
+{
+  impl.descriptor_ = -1;
+  impl.state_ = 0;
+}
+
+void reactive_descriptor_service::destroy(
+    reactive_descriptor_service::implementation_type& impl)
+{
+  if (is_open(impl))
+    reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_);
+
+  asio::error_code ignored_ec;
+  descriptor_ops::close(impl.descriptor_, impl.state_, ignored_ec);
+}
+
+asio::error_code reactive_descriptor_service::assign(
+    reactive_descriptor_service::implementation_type& impl,
+    const native_type& native_descriptor, asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    ec = asio::error::already_open;
+    return ec;
+  }
+
+  if (int err = reactor_.register_descriptor(
+        native_descriptor, impl.reactor_data_))
+  {
+    ec = asio::error_code(err,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  impl.descriptor_ = native_descriptor;
+  impl.state_ = 0;
+  ec = asio::error_code();
+  return ec;
+}
+
+asio::error_code reactive_descriptor_service::close(
+    reactive_descriptor_service::implementation_type& impl,
+    asio::error_code& ec)
+{
+  if (is_open(impl))
+    reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_);
+
+  if (descriptor_ops::close(impl.descriptor_, impl.state_, ec) == 0)
+    construct(impl);
+
+  return ec;
+}
+
+asio::error_code reactive_descriptor_service::cancel(
+    reactive_descriptor_service::implementation_type& impl,
+    asio::error_code& ec)
+{
+  if (!is_open(impl))
+  {
+    ec = asio::error::bad_descriptor;
+    return ec;
+  }
+
+  reactor_.cancel_ops(impl.descriptor_, impl.reactor_data_);
+  ec = asio::error_code();
+  return ec;
+}
+
+void reactive_descriptor_service::start_op(
+    reactive_descriptor_service::implementation_type& impl,
+    int op_type, reactor_op* op, bool non_blocking, bool noop)
+{
+  if (!noop)
+  {
+    if ((impl.state_ & descriptor_ops::non_blocking) ||
+        descriptor_ops::set_internal_non_blocking(
+          impl.descriptor_, impl.state_, op->ec_))
+    {
+      reactor_.start_op(op_type, impl.descriptor_,
+          impl.reactor_data_, op, non_blocking);
+      return;
+    }
+  }
+
+  reactor_.post_immediate_completion(op);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#endif // ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP

+ 151 - 0
ext/asio/asio/detail/impl/reactive_serial_port_service.ipp

@@ -0,0 +1,151 @@
+//
+// detail/impl/reactive_serial_port_service.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP
+#define ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_SERIAL_PORT)
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include <cstring>
+#include "asio/detail/reactive_serial_port_service.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+reactive_serial_port_service::reactive_serial_port_service(
+    asio::io_service& io_service)
+  : descriptor_service_(io_service)
+{
+}
+
+void reactive_serial_port_service::shutdown_service()
+{
+  descriptor_service_.shutdown_service();
+}
+
+asio::error_code reactive_serial_port_service::open(
+    reactive_serial_port_service::implementation_type& impl,
+    const std::string& device, asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    ec = asio::error::already_open;
+    return ec;
+  }
+
+  descriptor_ops::state_type state = 0;
+  int fd = descriptor_ops::open(device.c_str(),
+      O_RDWR | O_NONBLOCK | O_NOCTTY, ec);
+  if (fd < 0)
+    return ec;
+
+  int s = descriptor_ops::fcntl(fd, F_GETFL, ec);
+  if (s >= 0)
+    s = descriptor_ops::fcntl(fd, F_SETFL, s | O_NONBLOCK, ec);
+  if (s < 0)
+  {
+    asio::error_code ignored_ec;
+    descriptor_ops::close(fd, state, ignored_ec);
+    return ec;
+  }
+
+  // Set up default serial port options.
+  termios ios;
+  errno = 0;
+  s = descriptor_ops::error_wrapper(::tcgetattr(fd, &ios), ec);
+  if (s >= 0)
+  {
+#if defined(_BSD_SOURCE)
+    ::cfmakeraw(&ios);
+#else
+    ios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK
+        | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
+    ios.c_oflag &= ~OPOST;
+    ios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+    ios.c_cflag &= ~(CSIZE | PARENB);
+    ios.c_cflag |= CS8;
+#endif
+    ios.c_iflag |= IGNPAR;
+    ios.c_cflag |= CREAD | CLOCAL;
+    errno = 0;
+    s = descriptor_ops::error_wrapper(::tcsetattr(fd, TCSANOW, &ios), ec);
+  }
+  if (s < 0)
+  {
+    asio::error_code ignored_ec;
+    descriptor_ops::close(fd, state, ignored_ec);
+    return ec;
+  }
+
+  // We're done. Take ownership of the serial port descriptor.
+  if (descriptor_service_.assign(impl, fd, ec))
+  {
+    asio::error_code ignored_ec;
+    descriptor_ops::close(fd, state, ignored_ec);
+  }
+
+  return ec;
+}
+
+asio::error_code reactive_serial_port_service::do_set_option(
+    reactive_serial_port_service::implementation_type& impl,
+    reactive_serial_port_service::store_function_type store,
+    const void* option, asio::error_code& ec)
+{
+  termios ios;
+  errno = 0;
+  descriptor_ops::error_wrapper(::tcgetattr(
+        descriptor_service_.native(impl), &ios), ec);
+  if (ec)
+    return ec;
+
+  if (store(option, ios, ec))
+    return ec;
+
+  errno = 0;
+  descriptor_ops::error_wrapper(::tcsetattr(
+        descriptor_service_.native(impl), TCSANOW, &ios), ec);
+  return ec;
+}
+
+asio::error_code reactive_serial_port_service::do_get_option(
+    const reactive_serial_port_service::implementation_type& impl,
+    reactive_serial_port_service::load_function_type load,
+    void* option, asio::error_code& ec) const
+{
+  termios ios;
+  errno = 0;
+  descriptor_ops::error_wrapper(::tcgetattr(
+        descriptor_service_.native(impl), &ios), ec);
+  if (ec)
+    return ec;
+
+  return load(option, ios, ec);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#endif // defined(ASIO_HAS_SERIAL_PORT)
+
+#endif // ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP

+ 212 - 0
ext/asio/asio/detail/impl/reactive_socket_service_base.ipp

@@ -0,0 +1,212 @@
+//
+// detail/reactive_socket_service_base.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP
+#define ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if !defined(ASIO_HAS_IOCP)
+
+#include "asio/detail/reactive_socket_service_base.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+reactive_socket_service_base::reactive_socket_service_base(
+    asio::io_service& io_service)
+  : reactor_(use_service<reactor>(io_service))
+{
+  reactor_.init_task();
+}
+
+void reactive_socket_service_base::shutdown_service()
+{
+}
+
+void reactive_socket_service_base::construct(
+    reactive_socket_service_base::base_implementation_type& impl)
+{
+  impl.socket_ = invalid_socket;
+  impl.state_ = 0;
+}
+
+void reactive_socket_service_base::destroy(
+    reactive_socket_service_base::base_implementation_type& impl)
+{
+  if (impl.socket_ != invalid_socket)
+  {
+    reactor_.close_descriptor(impl.socket_, impl.reactor_data_);
+
+    asio::error_code ignored_ec;
+    socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
+  }
+}
+
+asio::error_code reactive_socket_service_base::close(
+    reactive_socket_service_base::base_implementation_type& impl,
+    asio::error_code& ec)
+{
+  if (is_open(impl))
+    reactor_.close_descriptor(impl.socket_, impl.reactor_data_);
+
+  if (socket_ops::close(impl.socket_, impl.state_, true, ec) == 0)
+    construct(impl);
+
+  return ec;
+}
+
+asio::error_code reactive_socket_service_base::cancel(
+    reactive_socket_service_base::base_implementation_type& impl,
+    asio::error_code& ec)
+{
+  if (!is_open(impl))
+  {
+    ec = asio::error::bad_descriptor;
+    return ec;
+  }
+
+  reactor_.cancel_ops(impl.socket_, impl.reactor_data_);
+  ec = asio::error_code();
+  return ec;
+}
+
+asio::error_code reactive_socket_service_base::do_open(
+    reactive_socket_service_base::base_implementation_type& impl,
+    int af, int type, int protocol, asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    ec = asio::error::already_open;
+    return ec;
+  }
+
+  socket_holder sock(socket_ops::socket(af, type, protocol, ec));
+  if (sock.get() == invalid_socket)
+    return ec;
+
+  if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_))
+  {
+    ec = asio::error_code(err,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  impl.socket_ = sock.release();
+  switch (type)
+  {
+  case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+  case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+  default: impl.state_ = 0; break;
+  }
+  ec = asio::error_code();
+  return ec;
+}
+
+asio::error_code reactive_socket_service_base::do_assign(
+    reactive_socket_service_base::base_implementation_type& impl, int type,
+    const reactive_socket_service_base::native_type& native_socket,
+    asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    ec = asio::error::already_open;
+    return ec;
+  }
+
+  if (int err = reactor_.register_descriptor(
+        native_socket, impl.reactor_data_))
+  {
+    ec = asio::error_code(err,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  impl.socket_ = native_socket;
+  switch (type)
+  {
+  case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+  case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+  default: impl.state_ = 0; break;
+  }
+  ec = asio::error_code();
+  return ec;
+}
+
+void reactive_socket_service_base::start_op(
+    reactive_socket_service_base::base_implementation_type& impl,
+    int op_type, reactor_op* op, bool non_blocking, bool noop)
+{
+  if (!noop)
+  {
+    if ((impl.state_ & socket_ops::non_blocking)
+        || socket_ops::set_internal_non_blocking(
+          impl.socket_, impl.state_, op->ec_))
+    {
+      reactor_.start_op(op_type, impl.socket_,
+          impl.reactor_data_, op, non_blocking);
+      return;
+    }
+  }
+
+  reactor_.post_immediate_completion(op);
+}
+
+void reactive_socket_service_base::start_accept_op(
+    reactive_socket_service_base::base_implementation_type& impl,
+    reactor_op* op, bool peer_is_open)
+{
+  if (!peer_is_open)
+    start_op(impl, reactor::read_op, op, true, false);
+  else
+  {
+    op->ec_ = asio::error::already_open;
+    reactor_.post_immediate_completion(op);
+  }
+}
+
+void reactive_socket_service_base::start_connect_op(
+    reactive_socket_service_base::base_implementation_type& impl,
+    reactor_op* op, const socket_addr_type* addr, size_t addrlen)
+{
+  if ((impl.state_ & socket_ops::non_blocking)
+      || socket_ops::set_internal_non_blocking(
+        impl.socket_, impl.state_, op->ec_))
+  {
+    if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0)
+    {
+      if (op->ec_ == asio::error::in_progress
+          || op->ec_ == asio::error::would_block)
+      {
+        op->ec_ = asio::error_code();
+        reactor_.start_op(reactor::connect_op,
+            impl.socket_, impl.reactor_data_, op, false);
+        return;
+      }
+    }
+  }
+
+  reactor_.post_immediate_completion(op);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP

+ 106 - 0
ext/asio/asio/detail/impl/resolver_service_base.ipp

@@ -0,0 +1,106 @@
+//
+// detail/impl/resolver_service_base.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP
+#define ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include "asio/detail/resolver_service_base.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class resolver_service_base::work_io_service_runner
+{
+public:
+  work_io_service_runner(asio::io_service& io_service)
+    : io_service_(io_service) {}
+  void operator()() { io_service_.run(); }
+private:
+  asio::io_service& io_service_;
+};
+
+resolver_service_base::resolver_service_base(
+    asio::io_service& io_service)
+  : io_service_impl_(asio::use_service<io_service_impl>(io_service)),
+    work_io_service_(new asio::io_service),
+    work_io_service_impl_(asio::use_service<
+        io_service_impl>(*work_io_service_)),
+    work_(new asio::io_service::work(*work_io_service_)),
+    work_thread_(0)
+{
+}
+
+resolver_service_base::~resolver_service_base()
+{
+  shutdown_service();
+}
+
+void resolver_service_base::shutdown_service()
+{
+  work_.reset();
+  if (work_io_service_)
+  {
+    work_io_service_->stop();
+    if (work_thread_)
+    {
+      work_thread_->join();
+      work_thread_.reset();
+    }
+    work_io_service_.reset();
+  }
+}
+
+void resolver_service_base::construct(
+    resolver_service_base::implementation_type& impl)
+{
+  impl.reset(static_cast<void*>(0), socket_ops::noop_deleter());
+}
+
+void resolver_service_base::destroy(
+    resolver_service_base::implementation_type&)
+{
+}
+
+void resolver_service_base::cancel(
+    resolver_service_base::implementation_type& impl)
+{
+  impl.reset(static_cast<void*>(0), socket_ops::noop_deleter());
+}
+
+void resolver_service_base::start_resolve_op(operation* op)
+{
+  start_work_thread();
+  io_service_impl_.work_started();
+  work_io_service_impl_.post_immediate_completion(op);
+}
+
+void resolver_service_base::start_work_thread()
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  if (!work_thread_)
+  {
+    work_thread_.reset(new asio::detail::thread(
+          work_io_service_runner(*work_io_service_)));
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP

+ 84 - 0
ext/asio/asio/detail/impl/select_reactor.hpp

@@ -0,0 +1,84 @@
+//
+// detail/impl/select_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_SELECT_REACTOR_HPP
+#define ASIO_DETAIL_IMPL_SELECT_REACTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP) \
+  || (!defined(ASIO_HAS_DEV_POLL) \
+      && !defined(ASIO_HAS_EPOLL) \
+      && !defined(ASIO_HAS_KQUEUE))
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Time_Traits>
+void select_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)
+{
+  do_add_timer_queue(queue);
+}
+
+// Remove a timer queue from the reactor.
+template <typename Time_Traits>
+void select_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue)
+{
+  do_remove_timer_queue(queue);
+}
+
+template <typename Time_Traits>
+void select_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
+    const typename Time_Traits::time_type& time,
+    typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  if (shutdown_)
+  {
+    io_service_.post_immediate_completion(op);
+    return;
+  }
+
+  bool earliest = queue.enqueue_timer(time, timer, op);
+  io_service_.work_started();
+  if (earliest)
+    interrupter_.interrupt();
+}
+
+template <typename Time_Traits>
+std::size_t select_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
+    typename timer_queue<Time_Traits>::per_timer_data& timer)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  op_queue<operation> ops;
+  std::size_t n = queue.cancel_timer(timer, ops);
+  lock.unlock();
+  io_service_.post_deferred_completions(ops);
+  return n;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+       //   || (!defined(ASIO_HAS_DEV_POLL)
+       //       && !defined(ASIO_HAS_EPOLL)
+       //       && !defined(ASIO_HAS_KQUEUE))
+
+#endif // ASIO_DETAIL_IMPL_SELECT_REACTOR_HPP

+ 273 - 0
ext/asio/asio/detail/impl/select_reactor.ipp

@@ -0,0 +1,273 @@
+//
+// detail/impl/select_reactor.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_SELECT_REACTOR_IPP
+#define ASIO_DETAIL_IMPL_SELECT_REACTOR_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP) \
+  || (!defined(ASIO_HAS_DEV_POLL) \
+      && !defined(ASIO_HAS_EPOLL) \
+      && !defined(ASIO_HAS_KQUEUE))
+
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/fd_set_adapter.hpp"
+#include "asio/detail/select_reactor.hpp"
+#include "asio/detail/signal_blocker.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+select_reactor::select_reactor(asio::io_service& io_service)
+  : asio::detail::service_base<select_reactor>(io_service),
+    io_service_(use_service<io_service_impl>(io_service)),
+    mutex_(),
+    interrupter_(),
+#if defined(ASIO_HAS_IOCP)
+    stop_thread_(false),
+    thread_(0),
+#endif // defined(ASIO_HAS_IOCP)
+    shutdown_(false)
+{
+#if defined(ASIO_HAS_IOCP)
+  asio::detail::signal_blocker sb;
+  thread_ = new asio::detail::thread(
+      bind_handler(&select_reactor::call_run_thread, this));
+#endif // defined(ASIO_HAS_IOCP)
+}
+
+select_reactor::~select_reactor()
+{
+  shutdown_service();
+}
+
+void select_reactor::shutdown_service()
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  shutdown_ = true;
+#if defined(ASIO_HAS_IOCP)
+  stop_thread_ = true;
+#endif // defined(ASIO_HAS_IOCP)
+  lock.unlock();
+
+#if defined(ASIO_HAS_IOCP)
+  if (thread_)
+  {
+    interrupter_.interrupt();
+    thread_->join();
+    delete thread_;
+    thread_ = 0;
+  }
+#endif // defined(ASIO_HAS_IOCP)
+
+  op_queue<operation> ops;
+
+  for (int i = 0; i < max_ops; ++i)
+    op_queue_[i].get_all_operations(ops);
+
+  timer_queues_.get_all_timers(ops);
+}
+
+void select_reactor::init_task()
+{
+  io_service_.init_task();
+}
+
+int select_reactor::register_descriptor(socket_type,
+    select_reactor::per_descriptor_data&)
+{
+  return 0;
+}
+
+void select_reactor::start_op(int op_type, socket_type descriptor,
+    select_reactor::per_descriptor_data&, reactor_op* op, bool)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  if (shutdown_)
+  {
+    post_immediate_completion(op);
+    return;
+  }
+
+  bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
+  io_service_.work_started();
+  if (first)
+    interrupter_.interrupt();
+}
+
+void select_reactor::cancel_ops(socket_type descriptor,
+    select_reactor::per_descriptor_data&)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
+}
+
+void select_reactor::close_descriptor(socket_type descriptor,
+    select_reactor::per_descriptor_data&)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
+}
+
+void select_reactor::run(bool block, op_queue<operation>& ops)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+#if defined(ASIO_HAS_IOCP)
+  // Check if the thread is supposed to stop.
+  if (stop_thread_)
+    return;
+#endif // defined(ASIO_HAS_IOCP)
+
+  // Set up the descriptor sets.
+  fd_set_adapter fds[max_select_ops];
+  fds[read_op].set(interrupter_.read_descriptor());
+  socket_type max_fd = 0;
+  bool have_work_to_do = !timer_queues_.all_empty();
+  for (int i = 0; i < max_select_ops; ++i)
+  {
+    have_work_to_do = have_work_to_do || !op_queue_[i].empty();
+    op_queue_[i].get_descriptors(fds[i], ops);
+    if (fds[i].max_descriptor() > max_fd)
+      max_fd = fds[i].max_descriptor();
+  }
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+  // Connection operations on Windows use both except and write fd_sets.
+  have_work_to_do = have_work_to_do || !op_queue_[connect_op].empty();
+  op_queue_[connect_op].get_descriptors(fds[write_op], ops);
+  if (fds[write_op].max_descriptor() > max_fd)
+    max_fd = fds[write_op].max_descriptor();
+  op_queue_[connect_op].get_descriptors(fds[except_op], ops);
+  if (fds[except_op].max_descriptor() > max_fd)
+    max_fd = fds[except_op].max_descriptor();
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+  // We can return immediately if there's no work to do and the reactor is
+  // not supposed to block.
+  if (!block && !have_work_to_do)
+    return;
+
+  // Determine how long to block while waiting for events.
+  timeval tv_buf = { 0, 0 };
+  timeval* tv = block ? get_timeout(tv_buf) : &tv_buf;
+
+  lock.unlock();
+
+  // Block on the select call until descriptors become ready.
+  asio::error_code ec;
+  int retval = socket_ops::select(static_cast<int>(max_fd + 1),
+      fds[read_op], fds[write_op], fds[except_op], tv, ec);
+
+  // Reset the interrupter.
+  if (retval > 0 && fds[read_op].is_set(interrupter_.read_descriptor()))
+    interrupter_.reset();
+
+  lock.lock();
+
+  // Dispatch all ready operations.
+  if (retval > 0)
+  {
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+    // Connection operations on Windows use both except and write fd_sets.
+    op_queue_[connect_op].perform_operations_for_descriptors(
+        fds[except_op], ops);
+    op_queue_[connect_op].perform_operations_for_descriptors(
+        fds[write_op], ops);
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+    // Exception operations must be processed first to ensure that any
+    // out-of-band data is read before normal data.
+    for (int i = max_select_ops - 1; i >= 0; --i)
+      op_queue_[i].perform_operations_for_descriptors(fds[i], ops);
+  }
+  timer_queues_.get_ready_timers(ops);
+}
+
+void select_reactor::interrupt()
+{
+  interrupter_.interrupt();
+}
+
+#if defined(ASIO_HAS_IOCP)
+void select_reactor::run_thread()
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  while (!stop_thread_)
+  {
+    lock.unlock();
+    op_queue<operation> ops;
+    run(true, ops);
+    io_service_.post_deferred_completions(ops);
+    lock.lock();
+  }
+}
+
+void select_reactor::call_run_thread(select_reactor* reactor)
+{
+  reactor->run_thread();
+}
+#endif // defined(ASIO_HAS_IOCP)
+
+void select_reactor::do_add_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(mutex_);
+  timer_queues_.insert(&queue);
+}
+
+void select_reactor::do_remove_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(mutex_);
+  timer_queues_.erase(&queue);
+}
+
+timeval* select_reactor::get_timeout(timeval& tv)
+{
+  // By default we will wait no longer than 5 minutes. This will ensure that
+  // any changes to the system clock are detected after no longer than this.
+  long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
+  tv.tv_sec = usec / 1000000;
+  tv.tv_usec = usec % 1000000;
+  return &tv;
+}
+
+void select_reactor::cancel_ops_unlocked(socket_type descriptor,
+    const asio::error_code& ec)
+{
+  bool need_interrupt = false;
+  op_queue<operation> ops;
+  for (int i = 0; i < max_ops; ++i)
+    need_interrupt = op_queue_[i].cancel_operations(
+        descriptor, ops, ec) || need_interrupt;
+  io_service_.post_deferred_completions(ops);
+  if (need_interrupt)
+    interrupter_.interrupt();
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+       //   || (!defined(ASIO_HAS_DEV_POLL)
+       //       && !defined(ASIO_HAS_EPOLL)
+       //       && !defined(ASIO_HAS_KQUEUE))
+
+#endif // ASIO_DETAIL_IMPL_SELECT_REACTOR_IPP

+ 70 - 0
ext/asio/asio/detail/impl/service_registry.hpp

@@ -0,0 +1,70 @@
+//
+// detail/impl/service_registry.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_SERVICE_REGISTRY_HPP
+#define ASIO_DETAIL_IMPL_SERVICE_REGISTRY_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Service>
+Service& service_registry::use_service()
+{
+  asio::io_service::service::key key;
+  init_key(key, Service::id);
+  factory_type factory = &service_registry::create<Service>;
+  return *static_cast<Service*>(do_use_service(key, factory));
+}
+
+template <typename Service>
+void service_registry::add_service(Service* new_service)
+{
+  asio::io_service::service::key key;
+  init_key(key, Service::id);
+  return do_add_service(key, new_service);
+}
+
+template <typename Service>
+bool service_registry::has_service() const
+{
+  asio::io_service::service::key key;
+  init_key(key, Service::id);
+  return do_has_service(key);
+}
+
+#if !defined(ASIO_NO_TYPEID)
+template <typename Service>
+void service_registry::init_key(asio::io_service::service::key& key,
+    const asio::detail::service_id<Service>& /*id*/)
+{
+  key.type_info_ = &typeid(typeid_wrapper<Service>);
+  key.id_ = 0;
+}
+#endif // !defined(ASIO_NO_TYPEID)
+
+template <typename Service>
+asio::io_service::service* service_registry::create(
+    asio::io_service& owner)
+{
+  return new Service(owner);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_IMPL_SERVICE_REGISTRY_HPP

+ 164 - 0
ext/asio/asio/detail/impl/service_registry.ipp

@@ -0,0 +1,164 @@
+//
+// detail/impl/service_registry.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP
+#define ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/throw_exception.hpp>
+#include "asio/detail/service_registry.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+service_registry::service_registry(asio::io_service& o)
+  : owner_(o),
+    first_service_(0)
+{
+}
+
+service_registry::~service_registry()
+{
+  // Shutdown all services. This must be done in a separate loop before the
+  // services are destroyed since the destructors of user-defined handler
+  // objects may try to access other service objects.
+  asio::io_service::service* service = first_service_;
+  while (service)
+  {
+    service->shutdown_service();
+    service = service->next_;
+  }
+
+  // Destroy all services.
+  while (first_service_)
+  {
+    asio::io_service::service* next_service = first_service_->next_;
+    destroy(first_service_);
+    first_service_ = next_service;
+  }
+}
+
+void service_registry::init_key(asio::io_service::service::key& key,
+    const asio::io_service::id& id)
+{
+  key.type_info_ = 0;
+  key.id_ = &id;
+}
+
+bool service_registry::keys_match(
+    const asio::io_service::service::key& key1,
+    const asio::io_service::service::key& key2)
+{
+  if (key1.id_ && key2.id_)
+    if (key1.id_ == key2.id_)
+      return true;
+  if (key1.type_info_ && key2.type_info_)
+    if (*key1.type_info_ == *key2.type_info_)
+      return true;
+  return false;
+}
+
+void service_registry::destroy(asio::io_service::service* service)
+{
+  delete service;
+}
+
+asio::io_service::service* service_registry::do_use_service(
+    const asio::io_service::service::key& key,
+    factory_type factory)
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  // First see if there is an existing service object with the given key.
+  asio::io_service::service* service = first_service_;
+  while (service)
+  {
+    if (keys_match(service->key_, key))
+      return service;
+    service = service->next_;
+  }
+
+  // Create a new service object. The service registry's mutex is not locked
+  // at this time to allow for nested calls into this function from the new
+  // service's constructor.
+  lock.unlock();
+  auto_service_ptr new_service = { factory(owner_) };
+  new_service.ptr_->key_ = key;
+  lock.lock();
+
+  // Check that nobody else created another service object of the same type
+  // while the lock was released.
+  service = first_service_;
+  while (service)
+  {
+    if (keys_match(service->key_, key))
+      return service;
+    service = service->next_;
+  }
+
+  // Service was successfully initialised, pass ownership to registry.
+  new_service.ptr_->next_ = first_service_;
+  first_service_ = new_service.ptr_;
+  new_service.ptr_ = 0;
+  return first_service_;
+}
+
+void service_registry::do_add_service(
+    const asio::io_service::service::key& key,
+    asio::io_service::service* new_service)
+{
+  if (&owner_ != &new_service->io_service())
+    boost::throw_exception(invalid_service_owner());
+
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  // Check if there is an existing service object with the given key.
+  asio::io_service::service* service = first_service_;
+  while (service)
+  {
+    if (keys_match(service->key_, key))
+      boost::throw_exception(service_already_exists());
+    service = service->next_;
+  }
+
+  // Take ownership of the service object.
+  new_service->key_ = key;
+  new_service->next_ = first_service_;
+  first_service_ = new_service;
+}
+
+bool service_registry::do_has_service(
+    const asio::io_service::service::key& key) const
+{
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  asio::io_service::service* service = first_service_;
+  while (service)
+  {
+    if (keys_match(service->key_, key))
+      return true;
+    service = service->next_;
+  }
+
+  return false;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP

File diff suppressed because it is too large
+ 2917 - 0
ext/asio/asio/detail/impl/socket_ops.ipp


+ 151 - 0
ext/asio/asio/detail/impl/socket_select_interrupter.ipp

@@ -0,0 +1,151 @@
+//
+// detail/impl/socket_select_interrupter.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_SOCKET_SELECT_INTERRUPTER_IPP
+#define ASIO_DETAIL_IMPL_SOCKET_SELECT_INTERRUPTER_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_WINDOWS) \
+  || defined(__CYGWIN__) \
+  || defined(__SYMBIAN32__)
+
+#include <cstdlib>
+#include "asio/detail/socket_holder.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/socket_select_interrupter.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+socket_select_interrupter::socket_select_interrupter()
+{
+  asio::error_code ec;
+  socket_holder acceptor(socket_ops::socket(
+        AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));
+  if (acceptor.get() == invalid_socket)
+    asio::detail::throw_error(ec, "socket_select_interrupter");
+
+  int opt = 1;
+  socket_ops::state_type acceptor_state = 0;
+  socket_ops::setsockopt(acceptor.get(), acceptor_state,
+      SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt), ec);
+
+  using namespace std; // For memset.
+  sockaddr_in4_type addr;
+  std::size_t addr_len = sizeof(addr);
+  memset(&addr, 0, sizeof(addr));
+  addr.sin_family = AF_INET;
+  addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+  addr.sin_port = 0;
+  if (socket_ops::bind(acceptor.get(), (const socket_addr_type*)&addr,
+        addr_len, ec) == socket_error_retval)
+    asio::detail::throw_error(ec, "socket_select_interrupter");
+
+  if (socket_ops::getsockname(acceptor.get(), (socket_addr_type*)&addr,
+        &addr_len, ec) == socket_error_retval)
+    asio::detail::throw_error(ec, "socket_select_interrupter");
+
+  // Some broken firewalls on Windows will intermittently cause getsockname to
+  // return 0.0.0.0 when the socket is actually bound to 127.0.0.1. We
+  // explicitly specify the target address here to work around this problem.
+  addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+  if (socket_ops::listen(acceptor.get(),
+        SOMAXCONN, ec) == socket_error_retval)
+    asio::detail::throw_error(ec, "socket_select_interrupter");
+
+  socket_holder client(socket_ops::socket(
+        AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));
+  if (client.get() == invalid_socket)
+    asio::detail::throw_error(ec, "socket_select_interrupter");
+
+  if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr,
+        addr_len, ec) == socket_error_retval)
+    asio::detail::throw_error(ec, "socket_select_interrupter");
+
+  socket_holder server(socket_ops::accept(acceptor.get(), 0, 0, ec));
+  if (server.get() == invalid_socket)
+    asio::detail::throw_error(ec, "socket_select_interrupter");
+  
+  ioctl_arg_type non_blocking = 1;
+  socket_ops::state_type client_state = 0;
+  if (socket_ops::ioctl(client.get(), client_state,
+        FIONBIO, &non_blocking, ec))
+    asio::detail::throw_error(ec, "socket_select_interrupter");
+
+  opt = 1;
+  socket_ops::setsockopt(client.get(), client_state,
+      IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
+
+  non_blocking = 1;
+  socket_ops::state_type server_state = 0;
+  if (socket_ops::ioctl(server.get(), server_state,
+        FIONBIO, &non_blocking, ec))
+    asio::detail::throw_error(ec, "socket_select_interrupter");
+
+  opt = 1;
+  socket_ops::setsockopt(server.get(), server_state,
+      IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
+
+  read_descriptor_ = server.release();
+  write_descriptor_ = client.release();
+}
+
+socket_select_interrupter::~socket_select_interrupter()
+{
+  asio::error_code ec;
+  socket_ops::state_type state = socket_ops::internal_non_blocking;
+  if (read_descriptor_ != invalid_socket)
+    socket_ops::close(read_descriptor_, state, true, ec);
+  if (write_descriptor_ != invalid_socket)
+    socket_ops::close(write_descriptor_, state, true, ec);
+}
+
+void socket_select_interrupter::interrupt()
+{
+  char byte = 0;
+  socket_ops::buf b;
+  socket_ops::init_buf(b, &byte, 1);
+  asio::error_code ec;
+  socket_ops::send(write_descriptor_, &b, 1, 0, ec);
+}
+
+bool socket_select_interrupter::reset()
+{
+  char data[1024];
+  socket_ops::buf b;
+  socket_ops::init_buf(b, data, sizeof(data));
+  asio::error_code ec;
+  int bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
+  bool was_interrupted = (bytes_read > 0);
+  while (bytes_read == sizeof(data))
+    bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
+  return was_interrupted;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_WINDOWS)
+       // || defined(__CYGWIN__)
+       // || defined(__SYMBIAN32__)
+
+#endif // ASIO_DETAIL_IMPL_SOCKET_SELECT_INTERRUPTER_IPP

+ 140 - 0
ext/asio/asio/detail/impl/strand_service.hpp

@@ -0,0 +1,140 @@
+//
+// detail/impl/strand_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_STRAND_SERVICE_HPP
+#define ASIO_DETAIL_IMPL_STRAND_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/call_stack.hpp"
+#include "asio/detail/completion_handler.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+inline strand_service::strand_impl::strand_impl()
+  : operation(&strand_service::do_complete),
+    count_(0)
+{
+}
+
+struct strand_service::on_dispatch_exit
+{
+  io_service_impl* io_service_;
+  strand_impl* impl_;
+
+  ~on_dispatch_exit()
+  {
+    impl_->mutex_.lock();
+    bool more_handlers = (--impl_->count_ > 0);
+    impl_->mutex_.unlock();
+
+    if (more_handlers)
+      io_service_->post_immediate_completion(impl_);
+  }
+};
+
+inline void strand_service::destroy(strand_service::implementation_type& impl)
+{
+  impl = 0;
+}
+
+template <typename Handler>
+void strand_service::dispatch(strand_service::implementation_type& impl,
+    Handler handler)
+{
+  // If we are already in the strand then the handler can run immediately.
+  if (call_stack<strand_impl>::contains(impl))
+  {
+    asio::detail::fenced_block b;
+    asio_handler_invoke_helpers::invoke(handler, handler);
+    return;
+  }
+
+  // Allocate and construct an operation to wrap the handler.
+  typedef completion_handler<Handler> op;
+  typename op::ptr p = { boost::addressof(handler),
+    asio_handler_alloc_helpers::allocate(
+      sizeof(op), handler), 0 };
+  p.p = new (p.v) op(handler);
+
+  // If we are running inside the io_service, and no other handler is queued
+  // or running, then the handler can run immediately.
+  bool can_dispatch = call_stack<io_service_impl>::contains(&io_service_);
+  impl->mutex_.lock();
+  bool first = (++impl->count_ == 1);
+  if (can_dispatch && first)
+  {
+    // Immediate invocation is allowed.
+    impl->mutex_.unlock();
+
+    // Memory must be releaesed before any upcall is made.
+    p.reset();
+
+    // Indicate that this strand is executing on the current thread.
+    call_stack<strand_impl>::context ctx(impl);
+
+    // Ensure the next handler, if any, is scheduled on block exit.
+    on_dispatch_exit on_exit = { &io_service_, impl };
+    (void)on_exit;
+
+    asio::detail::fenced_block b;
+    asio_handler_invoke_helpers::invoke(handler, handler);
+    return;
+  }
+
+  // Immediate invocation is not allowed, so enqueue for later.
+  impl->queue_.push(p.p);
+  impl->mutex_.unlock();
+  p.v = p.p = 0;
+
+  // The first handler to be enqueued is responsible for scheduling the
+  // strand.
+  if (first)
+    io_service_.post_immediate_completion(impl);
+}
+
+// Request the io_service to invoke the given handler and return immediately.
+template <typename Handler>
+void strand_service::post(strand_service::implementation_type& impl,
+    Handler handler)
+{
+  // Allocate and construct an operation to wrap the handler.
+  typedef completion_handler<Handler> op;
+  typename op::ptr p = { boost::addressof(handler),
+    asio_handler_alloc_helpers::allocate(
+      sizeof(op), handler), 0 };
+  p.p = new (p.v) op(handler);
+
+  // Add the handler to the queue.
+  impl->mutex_.lock();
+  bool first = (++impl->count_ == 1);
+  impl->queue_.push(p.p);
+  impl->mutex_.unlock();
+  p.v = p.p = 0;
+
+  // The first handler to be enqueue is responsible for scheduling the strand.
+  if (first)
+    io_service_.post_immediate_completion(impl);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_IMPL_STRAND_SERVICE_HPP

+ 106 - 0
ext/asio/asio/detail/impl/strand_service.ipp

@@ -0,0 +1,106 @@
+//
+// detail/impl/strand_service.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_STRAND_SERVICE_IPP
+#define ASIO_DETAIL_IMPL_STRAND_SERVICE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include "asio/detail/call_stack.hpp"
+#include "asio/detail/strand_service.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+struct strand_service::on_do_complete_exit
+{
+  io_service_impl* owner_;
+  strand_impl* impl_;
+
+  ~on_do_complete_exit()
+  {
+    impl_->mutex_.lock();
+    bool more_handlers = (--impl_->count_ > 0);
+    impl_->mutex_.unlock();
+
+    if (more_handlers)
+      owner_->post_immediate_completion(impl_);
+  }
+};
+
+strand_service::strand_service(asio::io_service& io_service)
+  : asio::detail::service_base<strand_service>(io_service),
+    io_service_(asio::use_service<io_service_impl>(io_service)),
+    mutex_(),
+    salt_(0)
+{
+}
+
+void strand_service::shutdown_service()
+{
+  op_queue<operation> ops;
+
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  for (std::size_t i = 0; i < num_implementations; ++i)
+    if (strand_impl* impl = implementations_[i].get())
+      ops.push(impl->queue_);
+}
+
+void strand_service::construct(strand_service::implementation_type& impl)
+{
+  std::size_t salt = salt_++;
+  std::size_t index = reinterpret_cast<std::size_t>(&impl);
+  index += (reinterpret_cast<std::size_t>(&impl) >> 3);
+  index ^= salt + 0x9e3779b9 + (index << 6) + (index >> 2);
+  index = index % num_implementations;
+
+  asio::detail::mutex::scoped_lock lock(mutex_);
+
+  if (!implementations_[index])
+    implementations_[index].reset(new strand_impl);
+  impl = implementations_[index].get();
+}
+
+void strand_service::do_complete(io_service_impl* owner, operation* base,
+    asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+{
+  if (owner)
+  {
+    strand_impl* impl = static_cast<strand_impl*>(base);
+
+    // Get the next handler to be executed.
+    impl->mutex_.lock();
+    operation* o = impl->queue_.front();
+    impl->queue_.pop();
+    impl->mutex_.unlock();
+
+    // Indicate that this strand is executing on the current thread.
+    call_stack<strand_impl>::context ctx(impl);
+
+    // Ensure the next handler, if any, is scheduled on block exit.
+    on_do_complete_exit on_exit = { owner, impl };
+    (void)on_exit;
+
+    o->complete(*owner);
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_IMPL_STRAND_SERVICE_IPP

+ 60 - 0
ext/asio/asio/detail/impl/task_io_service.hpp

@@ -0,0 +1,60 @@
+//
+// detail/impl/task_io_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_TASK_IO_SERVICE_HPP
+#define ASIO_DETAIL_IMPL_TASK_IO_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/call_stack.hpp"
+#include "asio/detail/completion_handler.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Handler>
+void task_io_service::dispatch(Handler handler)
+{
+  if (call_stack<task_io_service>::contains(this))
+  {
+    asio::detail::fenced_block b;
+    asio_handler_invoke_helpers::invoke(handler, handler);
+  }
+  else
+    post(handler);
+}
+
+template <typename Handler>
+void task_io_service::post(Handler handler)
+{
+  // Allocate and construct an operation to wrap the handler.
+  typedef completion_handler<Handler> op;
+  typename op::ptr p = { boost::addressof(handler),
+    asio_handler_alloc_helpers::allocate(
+      sizeof(op), handler), 0 };
+  p.p = new (p.v) op(handler);
+
+  post_immediate_completion(p.p);
+  p.v = p.p = 0;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_IMPL_TASK_IO_SERVICE_HPP

+ 354 - 0
ext/asio/asio/detail/impl/task_io_service.ipp

@@ -0,0 +1,354 @@
+//
+// detail/impl/task_io_service.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_TASK_IO_SERVICE_IPP
+#define ASIO_DETAIL_IMPL_TASK_IO_SERVICE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if !defined(ASIO_HAS_IOCP)
+
+#include <boost/limits.hpp>
+#include "asio/detail/call_stack.hpp"
+#include "asio/detail/event.hpp"
+#include "asio/detail/reactor.hpp"
+#include "asio/detail/task_io_service.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+struct task_io_service::task_cleanup
+{
+  ~task_cleanup()
+  {
+    // Enqueue the completed operations and reinsert the task at the end of
+    // the operation queue.
+    lock_->lock();
+    task_io_service_->task_interrupted_ = true;
+    task_io_service_->op_queue_.push(*ops_);
+    task_io_service_->op_queue_.push(&task_io_service_->task_operation_);
+  }
+
+  task_io_service* task_io_service_;
+  mutex::scoped_lock* lock_;
+  op_queue<operation>* ops_;
+};
+
+struct task_io_service::work_finished_on_block_exit
+{
+  ~work_finished_on_block_exit()
+  {
+    task_io_service_->work_finished();
+  }
+
+  task_io_service* task_io_service_;
+};
+
+struct task_io_service::idle_thread_info
+{
+  event wakeup_event;
+  idle_thread_info* next;
+};
+
+task_io_service::task_io_service(asio::io_service& io_service)
+  : asio::detail::service_base<task_io_service>(io_service),
+    mutex_(),
+    task_(0),
+    task_interrupted_(true),
+    outstanding_work_(0),
+    stopped_(false),
+    shutdown_(false),
+    first_idle_thread_(0)
+{
+}
+
+void task_io_service::init(std::size_t /*concurrency_hint*/)
+{
+}
+
+void task_io_service::shutdown_service()
+{
+  mutex::scoped_lock lock(mutex_);
+  shutdown_ = true;
+  lock.unlock();
+
+  // Destroy handler objects.
+  while (!op_queue_.empty())
+  {
+    operation* o = op_queue_.front();
+    op_queue_.pop();
+    if (o != &task_operation_)
+      o->destroy();
+  }
+
+  // Reset to initial state.
+  task_ = 0;
+}
+
+void task_io_service::init_task()
+{
+  mutex::scoped_lock lock(mutex_);
+  if (!shutdown_ && !task_)
+  {
+    task_ = &use_service<reactor>(this->get_io_service());
+    op_queue_.push(&task_operation_);
+    wake_one_thread_and_unlock(lock);
+  }
+}
+
+std::size_t task_io_service::run(asio::error_code& ec)
+{
+  ec = asio::error_code();
+  if (outstanding_work_ == 0)
+  {
+    stop();
+    return 0;
+  }
+
+  call_stack<task_io_service>::context ctx(this);
+
+  idle_thread_info this_idle_thread;
+  this_idle_thread.next = 0;
+
+  mutex::scoped_lock lock(mutex_);
+
+  std::size_t n = 0;
+  for (; do_one(lock, &this_idle_thread); lock.lock())
+    if (n != (std::numeric_limits<std::size_t>::max)())
+      ++n;
+  return n;
+}
+
+std::size_t task_io_service::run_one(asio::error_code& ec)
+{
+  ec = asio::error_code();
+  if (outstanding_work_ == 0)
+  {
+    stop();
+    return 0;
+  }
+
+  call_stack<task_io_service>::context ctx(this);
+
+  idle_thread_info this_idle_thread;
+  this_idle_thread.next = 0;
+
+  mutex::scoped_lock lock(mutex_);
+
+  return do_one(lock, &this_idle_thread);
+}
+
+std::size_t task_io_service::poll(asio::error_code& ec)
+{
+  if (outstanding_work_ == 0)
+  {
+    stop();
+    ec = asio::error_code();
+    return 0;
+  }
+
+  call_stack<task_io_service>::context ctx(this);
+
+  mutex::scoped_lock lock(mutex_);
+
+  std::size_t n = 0;
+  for (; do_one(lock, 0); lock.lock())
+    if (n != (std::numeric_limits<std::size_t>::max)())
+      ++n;
+  return n;
+}
+
+std::size_t task_io_service::poll_one(asio::error_code& ec)
+{
+  ec = asio::error_code();
+  if (outstanding_work_ == 0)
+  {
+    stop();
+    return 0;
+  }
+
+  call_stack<task_io_service>::context ctx(this);
+
+  mutex::scoped_lock lock(mutex_);
+
+  return do_one(lock, 0);
+}
+
+void task_io_service::stop()
+{
+  mutex::scoped_lock lock(mutex_);
+  stop_all_threads(lock);
+}
+
+void task_io_service::reset()
+{
+  mutex::scoped_lock lock(mutex_);
+  stopped_ = false;
+}
+
+void task_io_service::post_immediate_completion(task_io_service::operation* op)
+{
+  work_started();
+  post_deferred_completion(op);
+}
+
+void task_io_service::post_deferred_completion(task_io_service::operation* op)
+{
+  mutex::scoped_lock lock(mutex_);
+  op_queue_.push(op);
+  wake_one_thread_and_unlock(lock);
+}
+
+void task_io_service::post_deferred_completions(
+    op_queue<task_io_service::operation>& ops)
+{
+  if (!ops.empty())
+  {
+    mutex::scoped_lock lock(mutex_);
+    op_queue_.push(ops);
+    wake_one_thread_and_unlock(lock);
+  }
+}
+
+std::size_t task_io_service::do_one(mutex::scoped_lock& lock,
+    task_io_service::idle_thread_info* this_idle_thread)
+{
+  bool polling = !this_idle_thread;
+  bool task_has_run = false;
+  while (!stopped_)
+  {
+    if (!op_queue_.empty())
+    {
+      // Prepare to execute first handler from queue.
+      operation* o = op_queue_.front();
+      op_queue_.pop();
+      bool more_handlers = (!op_queue_.empty());
+
+      if (o == &task_operation_)
+      {
+        task_interrupted_ = more_handlers || polling;
+
+        // If the task has already run and we're polling then we're done.
+        if (task_has_run && polling)
+        {
+          task_interrupted_ = true;
+          op_queue_.push(&task_operation_);
+          return 0;
+        }
+        task_has_run = true;
+
+        if (!more_handlers || !wake_one_idle_thread_and_unlock(lock))
+          lock.unlock();
+
+        op_queue<operation> completed_ops;
+        task_cleanup c = { this, &lock, &completed_ops };
+        (void)c;
+
+        // Run the task. May throw an exception. Only block if the operation
+        // queue is empty and we're not polling, otherwise we want to return
+        // as soon as possible.
+        task_->run(!more_handlers && !polling, completed_ops);
+      }
+      else
+      {
+        if (more_handlers)
+          wake_one_thread_and_unlock(lock);
+        else
+          lock.unlock();
+
+        // Ensure the count of outstanding work is decremented on block exit.
+        work_finished_on_block_exit on_exit = { this };
+        (void)on_exit;
+
+        // Complete the operation. May throw an exception.
+        o->complete(*this); // deletes the operation object
+
+        return 1;
+      }
+    }
+    else if (this_idle_thread)
+    {
+      // Nothing to run right now, so just wait for work to do.
+      this_idle_thread->next = first_idle_thread_;
+      first_idle_thread_ = this_idle_thread;
+      this_idle_thread->wakeup_event.clear(lock);
+      this_idle_thread->wakeup_event.wait(lock);
+    }
+    else
+    {
+      return 0;
+    }
+  }
+
+  return 0;
+}
+
+void task_io_service::stop_all_threads(
+    mutex::scoped_lock& lock)
+{
+  stopped_ = true;
+
+  while (first_idle_thread_)
+  {
+    idle_thread_info* idle_thread = first_idle_thread_;
+    first_idle_thread_ = idle_thread->next;
+    idle_thread->next = 0;
+    idle_thread->wakeup_event.signal(lock);
+  }
+
+  if (!task_interrupted_ && task_)
+  {
+    task_interrupted_ = true;
+    task_->interrupt();
+  }
+}
+
+bool task_io_service::wake_one_idle_thread_and_unlock(
+    mutex::scoped_lock& lock)
+{
+  if (first_idle_thread_)
+  {
+    idle_thread_info* idle_thread = first_idle_thread_;
+    first_idle_thread_ = idle_thread->next;
+    idle_thread->next = 0;
+    idle_thread->wakeup_event.signal_and_unlock(lock);
+    return true;
+  }
+  return false;
+}
+
+void task_io_service::wake_one_thread_and_unlock(
+    mutex::scoped_lock& lock)
+{
+  if (!wake_one_idle_thread_and_unlock(lock))
+  {
+    if (!task_interrupted_ && task_)
+    {
+      task_interrupted_ = true;
+      task_->interrupt();
+    }
+    lock.unlock();
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_IMPL_TASK_IO_SERVICE_IPP

+ 47 - 0
ext/asio/asio/detail/impl/throw_error.ipp

@@ -0,0 +1,47 @@
+//
+// detail/impl/throw_error.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_THROW_ERROR_IPP
+#define ASIO_DETAIL_IMPL_THROW_ERROR_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/throw_exception.hpp>
+#include "asio/detail/throw_error.hpp"
+#include "asio/system_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+ASIO_DECL
+void do_throw_error(const asio::error_code& err)
+{
+  asio::system_error e(err);
+  boost::throw_exception(e);
+}
+
+ASIO_DECL
+void do_throw_error(const asio::error_code& err, const char* location)
+{
+  asio::system_error e(err, location);
+  boost::throw_exception(e);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_IMPL_THROW_ERROR_IPP

+ 85 - 0
ext/asio/asio/detail/impl/timer_queue.ipp

@@ -0,0 +1,85 @@
+//
+// detail/impl/timer_queue.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_TIMER_QUEUE_IPP
+#define ASIO_DETAIL_IMPL_TIMER_QUEUE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if !defined(ASIO_HEADER_ONLY)
+
+#include "asio/detail/timer_queue.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+timer_queue<time_traits<boost::posix_time::ptime> >::timer_queue()
+{
+}
+
+timer_queue<time_traits<boost::posix_time::ptime> >::~timer_queue()
+{
+}
+
+bool timer_queue<time_traits<boost::posix_time::ptime> >::enqueue_timer(
+    const time_type& time, per_timer_data& timer, timer_op* op)
+{
+  return impl_.enqueue_timer(time, timer, op);
+}
+
+bool timer_queue<time_traits<boost::posix_time::ptime> >::empty() const
+{
+  return impl_.empty();
+}
+
+long timer_queue<time_traits<boost::posix_time::ptime> >::wait_duration_msec(
+    long max_duration) const
+{
+  return impl_.wait_duration_msec(max_duration);
+}
+
+long timer_queue<time_traits<boost::posix_time::ptime> >::wait_duration_usec(
+    long max_duration) const
+{
+  return impl_.wait_duration_usec(max_duration);
+}
+
+void timer_queue<time_traits<boost::posix_time::ptime> >::get_ready_timers(
+    op_queue<operation>& ops)
+{
+  impl_.get_ready_timers(ops);
+}
+
+void timer_queue<time_traits<boost::posix_time::ptime> >::get_all_timers(
+    op_queue<operation>& ops)
+{
+  impl_.get_all_timers(ops);
+}
+
+std::size_t timer_queue<time_traits<boost::posix_time::ptime> >::cancel_timer(
+    per_timer_data& timer, op_queue<operation>& ops)
+{
+  return impl_.cancel_timer(timer, ops);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(ASIO_HEADER_ONLY)
+
+#endif // ASIO_DETAIL_IMPL_TIMER_QUEUE_IPP

+ 101 - 0
ext/asio/asio/detail/impl/timer_queue_set.ipp

@@ -0,0 +1,101 @@
+//
+// detail/impl/timer_queue_set.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_TIMER_QUEUE_SET_IPP
+#define ASIO_DETAIL_IMPL_TIMER_QUEUE_SET_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include "asio/detail/timer_queue_set.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+timer_queue_set::timer_queue_set()
+  : first_(0)
+{
+}
+
+void timer_queue_set::insert(timer_queue_base* q)
+{
+  q->next_ = first_;
+  first_ = q;
+}
+
+void timer_queue_set::erase(timer_queue_base* q)
+{
+  if (first_)
+  {
+    if (q == first_)
+    {
+      first_ = q->next_;
+      q->next_ = 0;
+      return;
+    }
+
+    for (timer_queue_base* p = first_; p->next_; p = p->next_)
+    {
+      if (p->next_ == q)
+      {
+        p->next_ = q->next_;
+        q->next_ = 0;
+        return;
+      }
+    }
+  }
+}
+
+bool timer_queue_set::all_empty() const
+{
+  for (timer_queue_base* p = first_; p; p = p->next_)
+    if (!p->empty())
+      return false;
+  return true;
+}
+
+long timer_queue_set::wait_duration_msec(long max_duration) const
+{
+  long min_duration = max_duration;
+  for (timer_queue_base* p = first_; p; p = p->next_)
+    min_duration = p->wait_duration_msec(min_duration);
+  return min_duration;
+}
+
+long timer_queue_set::wait_duration_usec(long max_duration) const
+{
+  long min_duration = max_duration;
+  for (timer_queue_base* p = first_; p; p = p->next_)
+    min_duration = p->wait_duration_usec(min_duration);
+  return min_duration;
+}
+
+void timer_queue_set::get_ready_timers(op_queue<operation>& ops)
+{
+  for (timer_queue_base* p = first_; p; p = p->next_)
+    p->get_ready_timers(ops);
+}
+
+void timer_queue_set::get_all_timers(op_queue<operation>& ops)
+{
+  for (timer_queue_base* p = first_; p; p = p->next_)
+    p->get_all_timers(ops);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_IMPL_TIMER_QUEUE_SET_IPP

+ 50 - 0
ext/asio/asio/detail/impl/win_event.ipp

@@ -0,0 +1,50 @@
+//
+// detail/win_event.ipp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WIN_EVENT_IPP
+#define ASIO_DETAIL_IMPL_WIN_EVENT_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_WINDOWS)
+
+#include "asio/detail/throw_error.hpp"
+#include "asio/detail/win_event.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+win_event::win_event()
+  : event_(::CreateEvent(0, true, false, 0))
+{
+  if (!event_)
+  {
+    DWORD last_error = ::GetLastError();
+    asio::error_code ec(last_error,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "event");
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_WINDOWS)
+
+#endif // ASIO_DETAIL_IMPL_WIN_EVENT_IPP

+ 452 - 0
ext/asio/asio/detail/impl/win_iocp_handle_service.ipp

@@ -0,0 +1,452 @@
+//
+// detail/impl/win_iocp_handle_service.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_HANDLE_SERVICE_IPP
+#define ASIO_DETAIL_IMPL_WIN_IOCP_HANDLE_SERVICE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+
+#include "asio/detail/win_iocp_handle_service.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class win_iocp_handle_service::overlapped_wrapper
+  : public OVERLAPPED
+{
+public:
+  explicit overlapped_wrapper(asio::error_code& ec)
+  {
+    Internal = 0;
+    InternalHigh = 0;
+    Offset = 0;
+    OffsetHigh = 0;
+
+    // Create a non-signalled manual-reset event, for GetOverlappedResult.
+    hEvent = ::CreateEvent(0, TRUE, FALSE, 0);
+    if (hEvent)
+    {
+      // As documented in GetQueuedCompletionStatus, setting the low order
+      // bit of this event prevents our synchronous writes from being treated
+      // as completion port events.
+      *reinterpret_cast<DWORD_PTR*>(&hEvent) |= 1;
+    }
+    else
+    {
+      DWORD last_error = ::GetLastError();
+      ec = asio::error_code(last_error,
+          asio::error::get_system_category());
+    }
+  }
+
+  ~overlapped_wrapper()
+  {
+    if (hEvent)
+    {
+      ::CloseHandle(hEvent);
+    }
+  }
+};
+
+win_iocp_handle_service::win_iocp_handle_service(
+    asio::io_service& io_service)
+  : iocp_service_(asio::use_service<win_iocp_io_service>(io_service)),
+    mutex_(),
+    impl_list_(0)
+{
+}
+
+void win_iocp_handle_service::shutdown_service()
+{
+  // Close all implementations, causing all operations to complete.
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  implementation_type* impl = impl_list_;
+  while (impl)
+  {
+    close_for_destruction(*impl);
+    impl = impl->next_;
+  }
+}
+
+void win_iocp_handle_service::construct(
+    win_iocp_handle_service::implementation_type& impl)
+{
+  impl.handle_ = INVALID_HANDLE_VALUE;
+  impl.safe_cancellation_thread_id_ = 0;
+
+  // Insert implementation into linked list of all implementations.
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  impl.next_ = impl_list_;
+  impl.prev_ = 0;
+  if (impl_list_)
+    impl_list_->prev_ = &impl;
+  impl_list_ = &impl;
+}
+
+void win_iocp_handle_service::destroy(
+    win_iocp_handle_service::implementation_type& impl)
+{
+  close_for_destruction(impl);
+  
+  // Remove implementation from linked list of all implementations.
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  if (impl_list_ == &impl)
+    impl_list_ = impl.next_;
+  if (impl.prev_)
+    impl.prev_->next_ = impl.next_;
+  if (impl.next_)
+    impl.next_->prev_= impl.prev_;
+  impl.next_ = 0;
+  impl.prev_ = 0;
+}
+
+asio::error_code win_iocp_handle_service::assign(
+    win_iocp_handle_service::implementation_type& impl,
+    const native_type& native_handle, asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    ec = asio::error::already_open;
+    return ec;
+  }
+
+  if (iocp_service_.register_handle(native_handle, ec))
+    return ec;
+
+  impl.handle_ = native_handle;
+  ec = asio::error_code();
+  return ec;
+}
+
+asio::error_code win_iocp_handle_service::close(
+    win_iocp_handle_service::implementation_type& impl,
+    asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    if (!::CloseHandle(impl.handle_))
+    {
+      DWORD last_error = ::GetLastError();
+      ec = asio::error_code(last_error,
+          asio::error::get_system_category());
+      return ec;
+    }
+
+    impl.handle_ = INVALID_HANDLE_VALUE;
+    impl.safe_cancellation_thread_id_ = 0;
+  }
+
+  ec = asio::error_code();
+  return ec;
+}
+
+asio::error_code win_iocp_handle_service::cancel(
+    win_iocp_handle_service::implementation_type& impl,
+    asio::error_code& ec)
+{
+  if (!is_open(impl))
+  {
+    ec = asio::error::bad_descriptor;
+  }
+  else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
+        ::GetModuleHandleA("KERNEL32"), "CancelIoEx"))
+  {
+    // The version of Windows supports cancellation from any thread.
+    typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);
+    cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr;
+    if (!cancel_io_ex(impl.handle_, 0))
+    {
+      DWORD last_error = ::GetLastError();
+      if (last_error == ERROR_NOT_FOUND)
+      {
+        // ERROR_NOT_FOUND means that there were no operations to be
+        // cancelled. We swallow this error to match the behaviour on other
+        // platforms.
+        ec = asio::error_code();
+      }
+      else
+      {
+        ec = asio::error_code(last_error,
+            asio::error::get_system_category());
+      }
+    }
+    else
+    {
+      ec = asio::error_code();
+    }
+  }
+  else if (impl.safe_cancellation_thread_id_ == 0)
+  {
+    // No operations have been started, so there's nothing to cancel.
+    ec = asio::error_code();
+  }
+  else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId())
+  {
+    // Asynchronous operations have been started from the current thread only,
+    // so it is safe to try to cancel them using CancelIo.
+    if (!::CancelIo(impl.handle_))
+    {
+      DWORD last_error = ::GetLastError();
+      ec = asio::error_code(last_error,
+          asio::error::get_system_category());
+    }
+    else
+    {
+      ec = asio::error_code();
+    }
+  }
+  else
+  {
+    // Asynchronous operations have been started from more than one thread,
+    // so cancellation is not safe.
+    ec = asio::error::operation_not_supported;
+  }
+
+  return ec;
+}
+
+size_t win_iocp_handle_service::do_write(
+    win_iocp_handle_service::implementation_type& impl, boost::uint64_t offset,
+    const asio::const_buffer& buffer, asio::error_code& ec)
+{
+  if (!is_open(impl))
+  {
+    ec = asio::error::bad_descriptor;
+    return 0;
+  }
+
+  // A request to write 0 bytes on a handle is a no-op.
+  if (asio::buffer_size(buffer) == 0)
+  {
+    ec = asio::error_code();
+    return 0;
+  }
+
+  overlapped_wrapper overlapped(ec);
+  if (ec)
+  {
+    return 0;
+  }
+
+  // Write the data. 
+  overlapped.Offset = offset & 0xFFFFFFFF;
+  overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
+  BOOL ok = ::WriteFile(impl.handle_,
+      asio::buffer_cast<LPCVOID>(buffer),
+      static_cast<DWORD>(asio::buffer_size(buffer)), 0, &overlapped);
+  if (!ok) 
+  {
+    DWORD last_error = ::GetLastError();
+    if (last_error != ERROR_IO_PENDING)
+    {
+      ec = asio::error_code(last_error,
+          asio::error::get_system_category());
+      return 0;
+    }
+  }
+
+  // Wait for the operation to complete.
+  DWORD bytes_transferred = 0;
+  ok = ::GetOverlappedResult(impl.handle_,
+      &overlapped, &bytes_transferred, TRUE);
+  if (!ok)
+  {
+    DWORD last_error = ::GetLastError();
+    ec = asio::error_code(last_error,
+        asio::error::get_system_category());
+    return 0;
+  }
+
+  ec = asio::error_code();
+  return bytes_transferred;
+}
+
+void win_iocp_handle_service::start_write_op(
+    win_iocp_handle_service::implementation_type& impl, boost::uint64_t offset,
+    const asio::const_buffer& buffer, operation* op)
+{
+  update_cancellation_thread_id(impl);
+  iocp_service_.work_started();
+
+  if (!is_open(impl))
+  {
+    iocp_service_.on_completion(op, asio::error::bad_descriptor);
+  }
+  else if (asio::buffer_size(buffer) == 0)
+  {
+    // A request to write 0 bytes on a handle is a no-op.
+    iocp_service_.on_completion(op);
+  }
+  else
+  {
+    DWORD bytes_transferred = 0;
+    op->Offset = offset & 0xFFFFFFFF;
+    op->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
+    BOOL ok = ::WriteFile(impl.handle_,
+        asio::buffer_cast<LPCVOID>(buffer),
+        static_cast<DWORD>(asio::buffer_size(buffer)),
+        &bytes_transferred, op);
+    DWORD last_error = ::GetLastError();
+    if (!ok && last_error != ERROR_IO_PENDING
+        && last_error != ERROR_MORE_DATA)
+    {
+      iocp_service_.on_completion(op, last_error, bytes_transferred);
+    }
+    else
+    {
+      iocp_service_.on_pending(op);
+    }
+  }
+}
+
+size_t win_iocp_handle_service::do_read(
+    win_iocp_handle_service::implementation_type& impl, boost::uint64_t offset,
+    const asio::mutable_buffer& buffer, asio::error_code& ec)
+{
+  if (!is_open(impl))
+  {
+    ec = asio::error::bad_descriptor;
+    return 0;
+  }
+  
+  // A request to read 0 bytes on a stream handle is a no-op.
+  if (asio::buffer_size(buffer) == 0)
+  {
+    ec = asio::error_code();
+    return 0;
+  }
+
+  overlapped_wrapper overlapped(ec);
+  if (ec)
+  {
+    return 0;
+  }
+
+  // Read some data.
+  overlapped.Offset = offset & 0xFFFFFFFF;
+  overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
+  BOOL ok = ::ReadFile(impl.handle_,
+      asio::buffer_cast<LPVOID>(buffer),
+      static_cast<DWORD>(asio::buffer_size(buffer)), 0, &overlapped);
+  if (!ok) 
+  {
+    DWORD last_error = ::GetLastError();
+    if (last_error != ERROR_IO_PENDING && last_error != ERROR_MORE_DATA)
+    {
+      if (last_error == ERROR_HANDLE_EOF)
+      {
+        ec = asio::error::eof;
+      }
+      else
+      {
+        ec = asio::error_code(last_error,
+            asio::error::get_system_category());
+      }
+      return 0;
+    }
+  }
+
+  // Wait for the operation to complete.
+  DWORD bytes_transferred = 0;
+  ok = ::GetOverlappedResult(impl.handle_,
+      &overlapped, &bytes_transferred, TRUE);
+  if (!ok)
+  {
+    DWORD last_error = ::GetLastError();
+    if (last_error == ERROR_HANDLE_EOF)
+    {
+      ec = asio::error::eof;
+    }
+    else
+    {
+      ec = asio::error_code(last_error,
+          asio::error::get_system_category());
+    }
+    return 0;
+  }
+
+  ec = asio::error_code();
+  return bytes_transferred;
+}
+
+void win_iocp_handle_service::start_read_op(
+    win_iocp_handle_service::implementation_type& impl, boost::uint64_t offset,
+    const asio::mutable_buffer& buffer, operation* op)
+{
+  update_cancellation_thread_id(impl);
+  iocp_service_.work_started();
+
+  if (!is_open(impl))
+  {
+    iocp_service_.on_completion(op, asio::error::bad_descriptor);
+  }
+  else if (asio::buffer_size(buffer) == 0)
+  {
+    // A request to read 0 bytes on a handle is a no-op.
+    iocp_service_.on_completion(op);
+  }
+  else
+  {
+    DWORD bytes_transferred = 0;
+    op->Offset = offset & 0xFFFFFFFF;
+    op->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
+    BOOL ok = ::ReadFile(impl.handle_,
+        asio::buffer_cast<LPVOID>(buffer),
+        static_cast<DWORD>(asio::buffer_size(buffer)),
+        &bytes_transferred, op);
+    DWORD last_error = ::GetLastError();
+    if (!ok && last_error != ERROR_IO_PENDING
+        && last_error != ERROR_MORE_DATA)
+    {
+      iocp_service_.on_completion(op, last_error, bytes_transferred);
+    }
+    else
+    {
+      iocp_service_.on_pending(op);
+    }
+  }
+}
+
+void win_iocp_handle_service::update_cancellation_thread_id(
+    win_iocp_handle_service::implementation_type& impl)
+{
+  if (impl.safe_cancellation_thread_id_ == 0)
+    impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
+  else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
+    impl.safe_cancellation_thread_id_ = ~DWORD(0);
+}
+
+void win_iocp_handle_service::close_for_destruction(implementation_type& impl)
+{
+  if (is_open(impl))
+  {
+    ::CloseHandle(impl.handle_);
+    impl.handle_ = INVALID_HANDLE_VALUE;
+    impl.safe_cancellation_thread_id_ = 0;
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_IMPL_WIN_IOCP_HANDLE_SERVICE_IPP

+ 115 - 0
ext/asio/asio/detail/impl/win_iocp_io_service.hpp

@@ -0,0 +1,115 @@
+//
+// detail/impl/win_iocp_io_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_HPP
+#define ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+
+#include "asio/detail/call_stack.hpp"
+#include "asio/detail/completion_handler.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Handler>
+void win_iocp_io_service::dispatch(Handler handler)
+{
+  if (call_stack<win_iocp_io_service>::contains(this))
+  {
+    asio::detail::fenced_block b;
+    asio_handler_invoke_helpers::invoke(handler, handler);
+  }
+  else
+    post(handler);
+}
+
+template <typename Handler>
+void win_iocp_io_service::post(Handler handler)
+{
+  // Allocate and construct an operation to wrap the handler.
+  typedef completion_handler<Handler> op;
+  typename op::ptr p = { boost::addressof(handler),
+    asio_handler_alloc_helpers::allocate(
+      sizeof(op), handler), 0 };
+  p.p = new (p.v) op(handler);
+
+  post_immediate_completion(p.p);
+  p.v = p.p = 0;
+}
+
+template <typename Time_Traits>
+void win_iocp_io_service::add_timer_queue(
+    timer_queue<Time_Traits>& queue)
+{
+  do_add_timer_queue(queue);
+}
+
+template <typename Time_Traits>
+void win_iocp_io_service::remove_timer_queue(
+    timer_queue<Time_Traits>& queue)
+{
+  do_remove_timer_queue(queue);
+}
+
+template <typename Time_Traits>
+void win_iocp_io_service::schedule_timer(timer_queue<Time_Traits>& queue,
+    const typename Time_Traits::time_type& time,
+    typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
+{
+  // If the service has been shut down we silently discard the timer.
+  if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
+  {
+    post_immediate_completion(op);
+    return;
+  }
+
+  mutex::scoped_lock lock(dispatch_mutex_);
+
+  bool earliest = queue.enqueue_timer(time, timer, op);
+  work_started();
+  if (earliest)
+    update_timeout();
+}
+
+template <typename Time_Traits>
+std::size_t win_iocp_io_service::cancel_timer(timer_queue<Time_Traits>& queue,
+    typename timer_queue<Time_Traits>::per_timer_data& timer)
+{
+  // If the service has been shut down we silently ignore the cancellation.
+  if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
+    return 0;
+
+  mutex::scoped_lock lock(dispatch_mutex_);
+  op_queue<win_iocp_operation> ops;
+  std::size_t n = queue.cancel_timer(timer, ops);
+  post_deferred_completions(ops);
+  return n;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_HPP

+ 496 - 0
ext/asio/asio/detail/impl/win_iocp_io_service.ipp

@@ -0,0 +1,496 @@
+//
+// detail/impl/win_iocp_io_service.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_IPP
+#define ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+
+#include <boost/limits.hpp>
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/detail/win_iocp_io_service.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+struct win_iocp_io_service::work_finished_on_block_exit
+{
+  ~work_finished_on_block_exit()
+  {
+    io_service_->work_finished();
+  }
+
+  win_iocp_io_service* io_service_;
+};
+
+struct win_iocp_io_service::timer_thread_function
+{
+  void operator()()
+  {
+    while (::InterlockedExchangeAdd(&io_service_->shutdown_, 0) == 0)
+    {
+      if (::WaitForSingleObject(io_service_->waitable_timer_.handle,
+            INFINITE) == WAIT_OBJECT_0)
+      {
+        ::InterlockedExchange(&io_service_->dispatch_required_, 1);
+        ::PostQueuedCompletionStatus(io_service_->iocp_.handle,
+            0, wake_for_dispatch, 0);
+      }
+    }
+  }
+
+  win_iocp_io_service* io_service_;
+};
+
+win_iocp_io_service::win_iocp_io_service(asio::io_service& io_service)
+  : asio::detail::service_base<win_iocp_io_service>(io_service),
+    iocp_(),
+    outstanding_work_(0),
+    stopped_(0),
+    shutdown_(0),
+    dispatch_required_(0)
+{
+}
+
+void win_iocp_io_service::init(size_t concurrency_hint)
+{
+  iocp_.handle = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0,
+      static_cast<DWORD>((std::min<size_t>)(concurrency_hint, DWORD(~0))));
+  if (!iocp_.handle)
+  {
+    DWORD last_error = ::GetLastError();
+    asio::error_code ec(last_error,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "iocp");
+  }
+}
+
+void win_iocp_io_service::shutdown_service()
+{
+  ::InterlockedExchange(&shutdown_, 1);
+
+  if (timer_thread_)
+  {
+    LARGE_INTEGER timeout;
+    timeout.QuadPart = 1;
+    ::SetWaitableTimer(waitable_timer_.handle, &timeout, 1, 0, 0, FALSE);
+  }
+
+  while (::InterlockedExchangeAdd(&outstanding_work_, 0) > 0)
+  {
+    op_queue<win_iocp_operation> ops;
+    timer_queues_.get_all_timers(ops);
+    ops.push(completed_ops_);
+    if (!ops.empty())
+    {
+      while (win_iocp_operation* op = ops.front())
+      {
+        ops.pop();
+        ::InterlockedDecrement(&outstanding_work_);
+        op->destroy();
+      }
+    }
+    else
+    {
+      DWORD bytes_transferred = 0;
+      dword_ptr_t completion_key = 0;
+      LPOVERLAPPED overlapped = 0;
+      ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
+          &completion_key, &overlapped, gqcs_timeout);
+      if (overlapped)
+      {
+        ::InterlockedDecrement(&outstanding_work_);
+        static_cast<win_iocp_operation*>(overlapped)->destroy();
+      }
+    }
+  }
+
+  if (timer_thread_)
+    timer_thread_->join();
+}
+
+asio::error_code win_iocp_io_service::register_handle(
+    HANDLE handle, asio::error_code& ec)
+{
+  if (::CreateIoCompletionPort(handle, iocp_.handle, 0, 0) == 0)
+  {
+    DWORD last_error = ::GetLastError();
+    ec = asio::error_code(last_error,
+        asio::error::get_system_category());
+  }
+  else
+  {
+    ec = asio::error_code();
+  }
+  return ec;
+}
+
+size_t win_iocp_io_service::run(asio::error_code& ec)
+{
+  if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
+  {
+    stop();
+    ec = asio::error_code();
+    return 0;
+  }
+
+  call_stack<win_iocp_io_service>::context ctx(this);
+
+  size_t n = 0;
+  while (do_one(true, ec))
+    if (n != (std::numeric_limits<size_t>::max)())
+      ++n;
+  return n;
+}
+
+size_t win_iocp_io_service::run_one(asio::error_code& ec)
+{
+  if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
+  {
+    stop();
+    ec = asio::error_code();
+    return 0;
+  }
+
+  call_stack<win_iocp_io_service>::context ctx(this);
+
+  return do_one(true, ec);
+}
+
+size_t win_iocp_io_service::poll(asio::error_code& ec)
+{
+  if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
+  {
+    stop();
+    ec = asio::error_code();
+    return 0;
+  }
+
+  call_stack<win_iocp_io_service>::context ctx(this);
+
+  size_t n = 0;
+  while (do_one(false, ec))
+    if (n != (std::numeric_limits<size_t>::max)())
+      ++n;
+  return n;
+}
+
+size_t win_iocp_io_service::poll_one(asio::error_code& ec)
+{
+  if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
+  {
+    stop();
+    ec = asio::error_code();
+    return 0;
+  }
+
+  call_stack<win_iocp_io_service>::context ctx(this);
+
+  return do_one(false, ec);
+}
+
+void win_iocp_io_service::stop()
+{
+  if (::InterlockedExchange(&stopped_, 1) == 0)
+  {
+    if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
+    {
+      DWORD last_error = ::GetLastError();
+      asio::error_code ec(last_error,
+          asio::error::get_system_category());
+      asio::detail::throw_error(ec, "pqcs");
+    }
+  }
+}
+
+void win_iocp_io_service::post_deferred_completion(win_iocp_operation* op)
+{
+  // Flag the operation as ready.
+  op->ready_ = 1;
+
+  // Enqueue the operation on the I/O completion port.
+  if (!::PostQueuedCompletionStatus(iocp_.handle,
+        0, overlapped_contains_result, op))
+  {
+    // Out of resources. Put on completed queue instead.
+    mutex::scoped_lock lock(dispatch_mutex_);
+    completed_ops_.push(op);
+    ::InterlockedExchange(&dispatch_required_, 1);
+  }
+}
+
+void win_iocp_io_service::post_deferred_completions(
+    op_queue<win_iocp_operation>& ops)
+{
+  while (win_iocp_operation* op = ops.front())
+  {
+    ops.pop();
+
+    // Flag the operation as ready.
+    op->ready_ = 1;
+
+    // Enqueue the operation on the I/O completion port.
+    if (!::PostQueuedCompletionStatus(iocp_.handle,
+          0, overlapped_contains_result, op))
+    {
+      // Out of resources. Put on completed queue instead.
+      mutex::scoped_lock lock(dispatch_mutex_);
+      completed_ops_.push(op);
+      completed_ops_.push(ops);
+      ::InterlockedExchange(&dispatch_required_, 1);
+    }
+  }
+}
+
+void win_iocp_io_service::on_pending(win_iocp_operation* op)
+{
+  if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1)
+  {
+    // Enqueue the operation on the I/O completion port.
+    if (!::PostQueuedCompletionStatus(iocp_.handle,
+          0, overlapped_contains_result, op))
+    {
+      // Out of resources. Put on completed queue instead.
+      mutex::scoped_lock lock(dispatch_mutex_);
+      completed_ops_.push(op);
+      ::InterlockedExchange(&dispatch_required_, 1);
+    }
+  }
+}
+
+void win_iocp_io_service::on_completion(win_iocp_operation* op,
+    DWORD last_error, DWORD bytes_transferred)
+{
+  // Flag that the operation is ready for invocation.
+  op->ready_ = 1;
+
+  // Store results in the OVERLAPPED structure.
+  op->Internal = asio::error::get_system_category();
+  op->Offset = last_error;
+  op->OffsetHigh = bytes_transferred;
+
+  // Enqueue the operation on the I/O completion port.
+  if (!::PostQueuedCompletionStatus(iocp_.handle,
+        0, overlapped_contains_result, op))
+  {
+    // Out of resources. Put on completed queue instead.
+    mutex::scoped_lock lock(dispatch_mutex_);
+    completed_ops_.push(op);
+    ::InterlockedExchange(&dispatch_required_, 1);
+  }
+}
+
+void win_iocp_io_service::on_completion(win_iocp_operation* op,
+    const asio::error_code& ec, DWORD bytes_transferred)
+{
+  // Flag that the operation is ready for invocation.
+  op->ready_ = 1;
+
+  // Store results in the OVERLAPPED structure.
+  op->Internal = ec.category();
+  op->Offset = ec.value();
+  op->OffsetHigh = bytes_transferred;
+
+  // Enqueue the operation on the I/O completion port.
+  if (!::PostQueuedCompletionStatus(iocp_.handle,
+        0, overlapped_contains_result, op))
+  {
+    // Out of resources. Put on completed queue instead.
+    mutex::scoped_lock lock(dispatch_mutex_);
+    completed_ops_.push(op);
+    ::InterlockedExchange(&dispatch_required_, 1);
+  }
+}
+
+size_t win_iocp_io_service::do_one(bool block, asio::error_code& ec)
+{
+  for (;;)
+  {
+    // Try to acquire responsibility for dispatching timers and completed ops.
+    if (::InterlockedCompareExchange(&dispatch_required_, 0, 1) == 1)
+    {
+      mutex::scoped_lock lock(dispatch_mutex_);
+
+      // Dispatch pending timers and operations.
+      op_queue<win_iocp_operation> ops;
+      ops.push(completed_ops_);
+      timer_queues_.get_ready_timers(ops);
+      post_deferred_completions(ops);
+      update_timeout();
+    }
+
+    // Get the next operation from the queue.
+    DWORD bytes_transferred = 0;
+    dword_ptr_t completion_key = 0;
+    LPOVERLAPPED overlapped = 0;
+    ::SetLastError(0);
+    BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
+        &completion_key, &overlapped, block ? gqcs_timeout : 0);
+    DWORD last_error = ::GetLastError();
+
+    if (overlapped)
+    {
+      win_iocp_operation* op = static_cast<win_iocp_operation*>(overlapped);
+      asio::error_code result_ec(last_error,
+          asio::error::get_system_category());
+
+      // We may have been passed the last_error and bytes_transferred in the
+      // OVERLAPPED structure itself.
+      if (completion_key == overlapped_contains_result)
+      {
+        result_ec = asio::error_code(static_cast<int>(op->Offset),
+            static_cast<asio::error_category>(op->Internal));
+        bytes_transferred = op->OffsetHigh;
+      }
+
+      // Otherwise ensure any result has been saved into the OVERLAPPED
+      // structure.
+      else
+      {
+        op->Internal = result_ec.category();
+        op->Offset = result_ec.value();
+        op->OffsetHigh = bytes_transferred;
+      }
+
+      // Dispatch the operation only if ready. The operation may not be ready
+      // if the initiating function (e.g. a call to WSARecv) has not yet
+      // returned. This is because the initiating function still wants access
+      // to the operation's OVERLAPPED structure.
+      if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1)
+      {
+        // Ensure the count of outstanding work is decremented on block exit.
+        work_finished_on_block_exit on_exit = { this };
+        (void)on_exit;
+
+        op->complete(*this, result_ec, bytes_transferred);
+        ec = asio::error_code();
+        return 1;
+      }
+    }
+    else if (!ok)
+    {
+      if (last_error != WAIT_TIMEOUT)
+      {
+        ec = asio::error_code(last_error,
+            asio::error::get_system_category());
+        return 0;
+      }
+
+      // If we're not polling we need to keep going until we get a real handler.
+      if (block)
+        continue;
+
+      ec = asio::error_code();
+      return 0;
+    }
+    else if (completion_key == wake_for_dispatch)
+    {
+      // We have been woken up to try to acquire responsibility for dispatching
+      // timers and completed operations.
+    }
+    else
+    {
+      // The stopped_ flag is always checked to ensure that any leftover
+      // interrupts from a previous run invocation are ignored.
+      if (::InterlockedExchangeAdd(&stopped_, 0) != 0)
+      {
+        // Wake up next thread that is blocked on GetQueuedCompletionStatus.
+        if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
+        {
+          last_error = ::GetLastError();
+          ec = asio::error_code(last_error,
+              asio::error::get_system_category());
+          return 0;
+        }
+
+        ec = asio::error_code();
+        return 0;
+      }
+    }
+  }
+}
+
+void win_iocp_io_service::do_add_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(dispatch_mutex_);
+
+  timer_queues_.insert(&queue);
+
+  if (!waitable_timer_.handle)
+  {
+    waitable_timer_.handle = ::CreateWaitableTimer(0, FALSE, 0);
+    if (waitable_timer_.handle == 0)
+    {
+      DWORD last_error = ::GetLastError();
+      asio::error_code ec(last_error,
+          asio::error::get_system_category());
+      asio::detail::throw_error(ec, "timer");
+    }
+
+    LARGE_INTEGER timeout;
+    timeout.QuadPart = -max_timeout_usec;
+    timeout.QuadPart *= 10;
+    ::SetWaitableTimer(waitable_timer_.handle,
+        &timeout, max_timeout_msec, 0, 0, FALSE);
+  }
+
+  if (!timer_thread_)
+  {
+    timer_thread_function thread_function = { this };
+    timer_thread_.reset(new thread(thread_function, 65536));
+  }
+}
+
+void win_iocp_io_service::do_remove_timer_queue(timer_queue_base& queue)
+{
+  mutex::scoped_lock lock(dispatch_mutex_);
+
+  timer_queues_.erase(&queue);
+}
+
+void win_iocp_io_service::update_timeout()
+{
+  if (timer_thread_)
+  {
+    // There's no point updating the waitable timer if the new timeout period
+    // exceeds the maximum timeout. In that case, we might as well wait for the
+    // existing period of the timer to expire.
+    long timeout_usec = timer_queues_.wait_duration_usec(max_timeout_usec);
+    if (timeout_usec < max_timeout_usec)
+    {
+      LARGE_INTEGER timeout;
+      timeout.QuadPart = -timeout_usec;
+      timeout.QuadPart *= 10;
+      ::SetWaitableTimer(waitable_timer_.handle,
+          &timeout, max_timeout_msec, 0, 0, FALSE);
+    }
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_IPP

+ 180 - 0
ext/asio/asio/detail/impl/win_iocp_serial_port_service.ipp

@@ -0,0 +1,180 @@
+//
+// detail/impl/win_iocp_serial_port_service.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_SERIAL_PORT_SERVICE_IPP
+#define ASIO_DETAIL_IMPL_WIN_IOCP_SERIAL_PORT_SERVICE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP) && defined(ASIO_HAS_SERIAL_PORT)
+
+#include <cstring>
+#include "asio/detail/win_iocp_serial_port_service.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+win_iocp_serial_port_service::win_iocp_serial_port_service(
+    asio::io_service& io_service)
+  : handle_service_(io_service)
+{
+}
+
+void win_iocp_serial_port_service::shutdown_service()
+{
+}
+
+asio::error_code win_iocp_serial_port_service::open(
+    win_iocp_serial_port_service::implementation_type& impl,
+    const std::string& device, asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    ec = asio::error::already_open;
+    return ec;
+  }
+
+  // For convenience, add a leading \\.\ sequence if not already present.
+  std::string name = (device[0] == '\\') ? device : "\\\\.\\" + device;
+
+  // Open a handle to the serial port.
+  ::HANDLE handle = ::CreateFileA(name.c_str(),
+      GENERIC_READ | GENERIC_WRITE, 0, 0,
+      OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
+  if (handle == INVALID_HANDLE_VALUE)
+  {
+    DWORD last_error = ::GetLastError();
+    ec = asio::error_code(last_error,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  // Determine the initial serial port parameters.
+  using namespace std; // For memset.
+  ::DCB dcb;
+  memset(&dcb, 0, sizeof(DCB));
+  dcb.DCBlength = sizeof(DCB);
+  if (!::GetCommState(handle, &dcb))
+  {
+    DWORD last_error = ::GetLastError();
+    ::CloseHandle(handle);
+    ec = asio::error_code(last_error,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  // Set some default serial port parameters. This implementation does not
+  // support changing these, so they might as well be in a known state.
+  dcb.fBinary = TRUE; // Win32 only supports binary mode.
+  dcb.fDsrSensitivity = FALSE;
+  dcb.fNull = FALSE; // Do not ignore NULL characters.
+  dcb.fAbortOnError = FALSE; // Ignore serial framing errors.
+  if (!::SetCommState(handle, &dcb))
+  {
+    DWORD last_error = ::GetLastError();
+    ::CloseHandle(handle);
+    ec = asio::error_code(last_error,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  // Set up timeouts so that the serial port will behave similarly to a
+  // network socket. Reads wait for at least one byte, then return with
+  // whatever they have. Writes return once everything is out the door.
+  ::COMMTIMEOUTS timeouts;
+  timeouts.ReadIntervalTimeout = 1;
+  timeouts.ReadTotalTimeoutMultiplier = 0;
+  timeouts.ReadTotalTimeoutConstant = 0;
+  timeouts.WriteTotalTimeoutMultiplier = 0;
+  timeouts.WriteTotalTimeoutConstant = 0;
+  if (!::SetCommTimeouts(handle, &timeouts))
+  {
+    DWORD last_error = ::GetLastError();
+    ::CloseHandle(handle);
+    ec = asio::error_code(last_error,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  // We're done. Take ownership of the serial port handle.
+  if (handle_service_.assign(impl, handle, ec))
+    ::CloseHandle(handle);
+  return ec;
+}
+
+asio::error_code win_iocp_serial_port_service::do_set_option(
+    win_iocp_serial_port_service::implementation_type& impl,
+    win_iocp_serial_port_service::store_function_type store,
+    const void* option, asio::error_code& ec)
+{
+  using namespace std; // For memcpy.
+
+  ::DCB dcb;
+  memset(&dcb, 0, sizeof(DCB));
+  dcb.DCBlength = sizeof(DCB);
+  if (!::GetCommState(handle_service_.native(impl), &dcb))
+  {
+    DWORD last_error = ::GetLastError();
+    ec = asio::error_code(last_error,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  if (store(option, dcb, ec))
+    return ec;
+
+  if (!::SetCommState(handle_service_.native(impl), &dcb))
+  {
+    DWORD last_error = ::GetLastError();
+    ec = asio::error_code(last_error,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  ec = asio::error_code();
+  return ec;
+}
+
+asio::error_code win_iocp_serial_port_service::do_get_option(
+    const win_iocp_serial_port_service::implementation_type& impl,
+    win_iocp_serial_port_service::load_function_type load,
+    void* option, asio::error_code& ec) const
+{
+  using namespace std; // For memset.
+
+  ::DCB dcb;
+  memset(&dcb, 0, sizeof(DCB));
+  dcb.DCBlength = sizeof(DCB);
+  if (!::GetCommState(handle_service_.native(impl), &dcb))
+  {
+    DWORD last_error = ::GetLastError();
+    ec = asio::error_code(last_error,
+        asio::error::get_system_category());
+    return ec;
+  }
+
+  return load(option, dcb, ec);
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP) && defined(ASIO_HAS_SERIAL_PORT)
+
+#endif // ASIO_DETAIL_IMPL_WIN_IOCP_SERIAL_PORT_SERVICE_IPP

+ 575 - 0
ext/asio/asio/detail/impl/win_iocp_socket_service_base.ipp

@@ -0,0 +1,575 @@
+//
+// detail/impl/win_iocp_socket_service_base.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_SOCKET_SERVICE_BASE_IPP
+#define ASIO_DETAIL_IMPL_WIN_IOCP_SOCKET_SERVICE_BASE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+
+#include "asio/detail/win_iocp_socket_service_base.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+win_iocp_socket_service_base::win_iocp_socket_service_base(
+    asio::io_service& io_service)
+  : io_service_(io_service),
+    iocp_service_(use_service<win_iocp_io_service>(io_service)),
+    reactor_(0),
+    mutex_(),
+    impl_list_(0)
+{
+}
+
+void win_iocp_socket_service_base::shutdown_service()
+{
+  // Close all implementations, causing all operations to complete.
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  base_implementation_type* impl = impl_list_;
+  while (impl)
+  {
+    asio::error_code ignored_ec;
+    close_for_destruction(*impl);
+    impl = impl->next_;
+  }
+}
+
+void win_iocp_socket_service_base::construct(
+    win_iocp_socket_service_base::base_implementation_type& impl)
+{
+  impl.socket_ = invalid_socket;
+  impl.state_ = 0;
+  impl.cancel_token_.reset();
+#if defined(ASIO_ENABLE_CANCELIO)
+  impl.safe_cancellation_thread_id_ = 0;
+#endif // defined(ASIO_ENABLE_CANCELIO)
+
+  // Insert implementation into linked list of all implementations.
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  impl.next_ = impl_list_;
+  impl.prev_ = 0;
+  if (impl_list_)
+    impl_list_->prev_ = &impl;
+  impl_list_ = &impl;
+}
+
+void win_iocp_socket_service_base::destroy(
+    win_iocp_socket_service_base::base_implementation_type& impl)
+{
+  close_for_destruction(impl);
+
+  // Remove implementation from linked list of all implementations.
+  asio::detail::mutex::scoped_lock lock(mutex_);
+  if (impl_list_ == &impl)
+    impl_list_ = impl.next_;
+  if (impl.prev_)
+    impl.prev_->next_ = impl.next_;
+  if (impl.next_)
+    impl.next_->prev_= impl.prev_;
+  impl.next_ = 0;
+  impl.prev_ = 0;
+}
+
+asio::error_code win_iocp_socket_service_base::close(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    // Check if the reactor was created, in which case we need to close the
+    // socket on the reactor as well to cancel any operations that might be
+    // running there.
+    reactor* r = static_cast<reactor*>(
+          interlocked_compare_exchange_pointer(
+            reinterpret_cast<void**>(&reactor_), 0, 0));
+    if (r)
+      r->close_descriptor(impl.socket_, impl.reactor_data_);
+  }
+
+  if (socket_ops::close(impl.socket_, impl.state_, false, ec) == 0)
+  {
+    impl.socket_ = invalid_socket;
+    impl.state_ = 0;
+    impl.cancel_token_.reset();
+#if defined(ASIO_ENABLE_CANCELIO)
+    impl.safe_cancellation_thread_id_ = 0;
+#endif // defined(ASIO_ENABLE_CANCELIO)
+  }
+
+  return ec;
+}
+
+asio::error_code win_iocp_socket_service_base::cancel(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    asio::error_code& ec)
+{
+  if (!is_open(impl))
+  {
+    ec = asio::error::bad_descriptor;
+    return ec;
+  }
+  else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
+        ::GetModuleHandleA("KERNEL32"), "CancelIoEx"))
+  {
+    // The version of Windows supports cancellation from any thread.
+    typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);
+    cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr;
+    socket_type sock = impl.socket_;
+    HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock);
+    if (!cancel_io_ex(sock_as_handle, 0))
+    {
+      DWORD last_error = ::GetLastError();
+      if (last_error == ERROR_NOT_FOUND)
+      {
+        // ERROR_NOT_FOUND means that there were no operations to be
+        // cancelled. We swallow this error to match the behaviour on other
+        // platforms.
+        ec = asio::error_code();
+      }
+      else
+      {
+        ec = asio::error_code(last_error,
+            asio::error::get_system_category());
+      }
+    }
+    else
+    {
+      ec = asio::error_code();
+    }
+  }
+#if defined(ASIO_ENABLE_CANCELIO)
+  else if (impl.safe_cancellation_thread_id_ == 0)
+  {
+    // No operations have been started, so there's nothing to cancel.
+    ec = asio::error_code();
+  }
+  else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId())
+  {
+    // Asynchronous operations have been started from the current thread only,
+    // so it is safe to try to cancel them using CancelIo.
+    socket_type sock = impl.socket_;
+    HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock);
+    if (!::CancelIo(sock_as_handle))
+    {
+      DWORD last_error = ::GetLastError();
+      ec = asio::error_code(last_error,
+          asio::error::get_system_category());
+    }
+    else
+    {
+      ec = asio::error_code();
+    }
+  }
+  else
+  {
+    // Asynchronous operations have been started from more than one thread,
+    // so cancellation is not safe.
+    ec = asio::error::operation_not_supported;
+  }
+#else // defined(ASIO_ENABLE_CANCELIO)
+  else
+  {
+    // Cancellation is not supported as CancelIo may not be used.
+    ec = asio::error::operation_not_supported;
+  }
+#endif // defined(ASIO_ENABLE_CANCELIO)
+
+  // Cancel any operations started via the reactor.
+  if (!ec)
+  {
+    reactor* r = static_cast<reactor*>(
+          interlocked_compare_exchange_pointer(
+            reinterpret_cast<void**>(&reactor_), 0, 0));
+    if (r)
+      r->cancel_ops(impl.socket_, impl.reactor_data_);
+  }
+
+  return ec;
+}
+
+asio::error_code win_iocp_socket_service_base::do_open(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    int family, int type, int protocol, asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    ec = asio::error::already_open;
+    return ec;
+  }
+
+  socket_holder sock(socket_ops::socket(family, type, protocol, ec));
+  if (sock.get() == invalid_socket)
+    return ec;
+
+  HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock.get());
+  if (iocp_service_.register_handle(sock_as_handle, ec))
+    return ec;
+
+  impl.socket_ = sock.release();
+  switch (type)
+  {
+  case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+  case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+  default: impl.state_ = 0; break;
+  }
+  impl.cancel_token_.reset(static_cast<void*>(0), socket_ops::noop_deleter());
+  ec = asio::error_code();
+  return ec;
+}
+
+asio::error_code win_iocp_socket_service_base::do_assign(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    int type, socket_type native_socket, asio::error_code& ec)
+{
+  if (is_open(impl))
+  {
+    ec = asio::error::already_open;
+    return ec;
+  }
+
+  HANDLE sock_as_handle = reinterpret_cast<HANDLE>(native_socket);
+  if (iocp_service_.register_handle(sock_as_handle, ec))
+    return ec;
+
+  impl.socket_ = native_socket;
+  switch (type)
+  {
+  case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
+  case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
+  default: impl.state_ = 0; break;
+  }
+  impl.cancel_token_.reset(static_cast<void*>(0), socket_ops::noop_deleter());
+  ec = asio::error_code();
+  return ec;
+}
+
+void win_iocp_socket_service_base::start_send_op(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    WSABUF* buffers, std::size_t buffer_count,
+    socket_base::message_flags flags, bool noop, operation* op)
+{
+  update_cancellation_thread_id(impl);
+  iocp_service_.work_started();
+
+  if (noop)
+    iocp_service_.on_completion(op);
+  else if (!is_open(impl))
+    iocp_service_.on_completion(op, asio::error::bad_descriptor);
+  else
+  {
+    DWORD bytes_transferred = 0;
+    int result = ::WSASend(impl.socket_, buffers,
+        static_cast<DWORD>(buffer_count), &bytes_transferred, flags, op, 0);
+    DWORD last_error = ::WSAGetLastError();
+    if (last_error == ERROR_PORT_UNREACHABLE)
+      last_error = WSAECONNREFUSED;
+    if (result != 0 && last_error != WSA_IO_PENDING)
+      iocp_service_.on_completion(op, last_error, bytes_transferred);
+    else
+      iocp_service_.on_pending(op);
+  }
+}
+
+void win_iocp_socket_service_base::start_send_to_op(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    WSABUF* buffers, std::size_t buffer_count,
+    const socket_addr_type* addr, int addrlen,
+    socket_base::message_flags flags, operation* op)
+{
+  update_cancellation_thread_id(impl);
+  iocp_service_.work_started();
+
+  if (!is_open(impl))
+    iocp_service_.on_completion(op, asio::error::bad_descriptor);
+  else
+  {
+    DWORD bytes_transferred = 0;
+    int result = ::WSASendTo(impl.socket_, buffers,
+        static_cast<DWORD>(buffer_count),
+        &bytes_transferred, flags, addr, addrlen, op, 0);
+    DWORD last_error = ::WSAGetLastError();
+    if (last_error == ERROR_PORT_UNREACHABLE)
+      last_error = WSAECONNREFUSED;
+    if (result != 0 && last_error != WSA_IO_PENDING)
+      iocp_service_.on_completion(op, last_error, bytes_transferred);
+    else
+      iocp_service_.on_pending(op);
+  }
+}
+
+void win_iocp_socket_service_base::start_receive_op(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    WSABUF* buffers, std::size_t buffer_count,
+    socket_base::message_flags flags, bool noop, operation* op)
+{
+  update_cancellation_thread_id(impl);
+  iocp_service_.work_started();
+
+  if (noop)
+    iocp_service_.on_completion(op);
+  else if (!is_open(impl))
+    iocp_service_.on_completion(op, asio::error::bad_descriptor);
+  else
+  {
+    DWORD bytes_transferred = 0;
+    DWORD recv_flags = flags;
+    int result = ::WSARecv(impl.socket_, buffers,
+        static_cast<DWORD>(buffer_count),
+        &bytes_transferred, &recv_flags, op, 0);
+    DWORD last_error = ::WSAGetLastError();
+    if (last_error == ERROR_NETNAME_DELETED)
+      last_error = WSAECONNRESET;
+    else if (last_error == ERROR_PORT_UNREACHABLE)
+      last_error = WSAECONNREFUSED;
+    if (result != 0 && last_error != WSA_IO_PENDING)
+      iocp_service_.on_completion(op, last_error, bytes_transferred);
+    else
+      iocp_service_.on_pending(op);
+  }
+}
+
+void win_iocp_socket_service_base::start_null_buffers_receive_op(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    socket_base::message_flags flags, reactor_op* op)
+{
+  if ((impl.state_ & socket_ops::stream_oriented) != 0)
+  {
+    // For stream sockets on Windows, we may issue a 0-byte overlapped
+    // WSARecv to wait until there is data available on the socket.
+    ::WSABUF buf = { 0, 0 };
+    start_receive_op(impl, &buf, 1, flags, false, op);
+  }
+  else
+  {
+    start_reactor_op(impl,
+        (flags & socket_base::message_out_of_band)
+          ? reactor::except_op : reactor::read_op,
+        op);
+  }
+}
+
+void win_iocp_socket_service_base::start_receive_from_op(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    WSABUF* buffers, std::size_t buffer_count, socket_addr_type* addr,
+    socket_base::message_flags flags, int* addrlen, operation* op)
+{
+  update_cancellation_thread_id(impl);
+  iocp_service_.work_started();
+
+  if (!is_open(impl))
+    iocp_service_.on_completion(op, asio::error::bad_descriptor);
+  else
+  {
+    DWORD bytes_transferred = 0;
+    DWORD recv_flags = flags;
+    int result = ::WSARecvFrom(impl.socket_, buffers,
+        static_cast<DWORD>(buffer_count),
+        &bytes_transferred, &recv_flags, addr, addrlen, op, 0);
+    DWORD last_error = ::WSAGetLastError();
+    if (last_error == ERROR_PORT_UNREACHABLE)
+      last_error = WSAECONNREFUSED;
+    if (result != 0 && last_error != WSA_IO_PENDING)
+      iocp_service_.on_completion(op, last_error, bytes_transferred);
+    else
+      iocp_service_.on_pending(op);
+  }
+}
+
+void win_iocp_socket_service_base::start_accept_op(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    bool peer_is_open, socket_holder& new_socket, int family, int type,
+    int protocol, void* output_buffer, DWORD address_length, operation* op)
+{
+  update_cancellation_thread_id(impl);
+  iocp_service_.work_started();
+
+  if (!is_open(impl))
+    iocp_service_.on_completion(op, asio::error::bad_descriptor);
+  else if (peer_is_open)
+    iocp_service_.on_completion(op, asio::error::already_open);
+  else
+  {
+    asio::error_code ec;
+    new_socket.reset(socket_ops::socket(family, type, protocol, ec));
+    if (new_socket.get() == invalid_socket)
+      iocp_service_.on_completion(op, ec);
+    else
+    {
+      DWORD bytes_read = 0;
+      BOOL result = ::AcceptEx(impl.socket_, new_socket.get(), output_buffer,
+          0, address_length, address_length, &bytes_read, op);
+      DWORD last_error = ::WSAGetLastError();
+      if (!result && last_error != WSA_IO_PENDING)
+        iocp_service_.on_completion(op, last_error);
+      else
+        iocp_service_.on_pending(op);
+    }
+  }
+}
+
+void win_iocp_socket_service_base::restart_accept_op(
+    socket_type s, socket_holder& new_socket, int family, int type,
+    int protocol, void* output_buffer, DWORD address_length, operation* op)
+{
+  new_socket.reset();
+  iocp_service_.work_started();
+
+  asio::error_code ec;
+  new_socket.reset(socket_ops::socket(family, type, protocol, ec));
+  if (new_socket.get() == invalid_socket)
+    iocp_service_.on_completion(op, ec);
+  else
+  {
+    DWORD bytes_read = 0;
+    BOOL result = ::AcceptEx(s, new_socket.get(), output_buffer,
+        0, address_length, address_length, &bytes_read, op);
+    DWORD last_error = ::WSAGetLastError();
+    if (!result && last_error != WSA_IO_PENDING)
+      iocp_service_.on_completion(op, last_error);
+    else
+      iocp_service_.on_pending(op);
+  }
+}
+
+void win_iocp_socket_service_base::start_reactor_op(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    int op_type, reactor_op* op)
+{
+  reactor& r = get_reactor();
+  update_cancellation_thread_id(impl);
+
+  if (is_open(impl))
+  {
+    r.start_op(op_type, impl.socket_, impl.reactor_data_, op, false);
+    return;
+  }
+  else
+    op->ec_ = asio::error::bad_descriptor;
+
+  iocp_service_.post_immediate_completion(op);
+}
+
+void win_iocp_socket_service_base::start_connect_op(
+    win_iocp_socket_service_base::base_implementation_type& impl,
+    reactor_op* op, const socket_addr_type* addr, std::size_t addrlen)
+{
+  reactor& r = get_reactor();
+  update_cancellation_thread_id(impl);
+
+  if ((impl.state_ & socket_ops::non_blocking) != 0
+      || socket_ops::set_internal_non_blocking(
+        impl.socket_, impl.state_, op->ec_))
+  {
+    if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0)
+    {
+      if (op->ec_ == asio::error::in_progress
+          || op->ec_ == asio::error::would_block)
+      {
+        op->ec_ = asio::error_code();
+        r.start_op(reactor::connect_op, impl.socket_,
+            impl.reactor_data_, op, false);
+        return;
+      }
+    }
+  }
+
+  r.post_immediate_completion(op);
+}
+
+void win_iocp_socket_service_base::close_for_destruction(
+    win_iocp_socket_service_base::base_implementation_type& impl)
+{
+  if (is_open(impl))
+  {
+    // Check if the reactor was created, in which case we need to close the
+    // socket on the reactor as well to cancel any operations that might be
+    // running there.
+    reactor* r = static_cast<reactor*>(
+          interlocked_compare_exchange_pointer(
+            reinterpret_cast<void**>(&reactor_), 0, 0));
+    if (r)
+      r->close_descriptor(impl.socket_, impl.reactor_data_);
+  }
+
+  asio::error_code ignored_ec;
+  socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
+  impl.socket_ = invalid_socket;
+  impl.state_ = 0;
+  impl.cancel_token_.reset();
+#if defined(ASIO_ENABLE_CANCELIO)
+  impl.safe_cancellation_thread_id_ = 0;
+#endif // defined(ASIO_ENABLE_CANCELIO)
+}
+
+void win_iocp_socket_service_base::update_cancellation_thread_id(
+    win_iocp_socket_service_base::base_implementation_type& impl)
+{
+#if defined(ASIO_ENABLE_CANCELIO)
+  if (impl.safe_cancellation_thread_id_ == 0)
+    impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
+  else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
+    impl.safe_cancellation_thread_id_ = ~DWORD(0);
+#else // defined(ASIO_ENABLE_CANCELIO)
+  (void)impl;
+#endif // defined(ASIO_ENABLE_CANCELIO)
+}
+
+reactor& win_iocp_socket_service_base::get_reactor()
+{
+  reactor* r = static_cast<reactor*>(
+        interlocked_compare_exchange_pointer(
+          reinterpret_cast<void**>(&reactor_), 0, 0));
+  if (!r)
+  {
+    r = &(use_service<reactor>(io_service_));
+    interlocked_exchange_pointer(reinterpret_cast<void**>(&reactor_), r);
+  }
+  return *r;
+}
+
+void* win_iocp_socket_service_base::interlocked_compare_exchange_pointer(
+    void** dest, void* exch, void* cmp)
+{
+#if defined(_M_IX86)
+  return reinterpret_cast<void*>(InterlockedCompareExchange(
+        reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(exch),
+        reinterpret_cast<LONG>(cmp)));
+#else
+  return InterlockedCompareExchangePointer(dest, exch, cmp);
+#endif
+}
+
+void* win_iocp_socket_service_base::interlocked_exchange_pointer(
+    void** dest, void* val)
+{
+#if defined(_M_IX86)
+  return reinterpret_cast<void*>(InterlockedExchange(
+        reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(val)));
+#else
+  return InterlockedExchangePointer(dest, val);
+#endif
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_IMPL_WIN_IOCP_SOCKET_SERVICE_BASE_IPP

+ 78 - 0
ext/asio/asio/detail/impl/win_mutex.ipp

@@ -0,0 +1,78 @@
+//
+// detail/impl/win_mutex.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WIN_MUTEX_IPP
+#define ASIO_DETAIL_IMPL_WIN_MUTEX_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_WINDOWS)
+
+#include "asio/detail/throw_error.hpp"
+#include "asio/detail/win_mutex.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+win_mutex::win_mutex()
+{
+  int error = do_init();
+  asio::error_code ec(error,
+      asio::error::get_system_category());
+  asio::detail::throw_error(ec, "mutex");
+}
+
+int win_mutex::do_init()
+{
+#if defined(__MINGW32__)
+  // Not sure if MinGW supports structured exception handling, so for now
+  // we'll just call the Windows API and hope.
+# if defined(UNDER_CE)
+  ::InitializeCriticalSection(&crit_section_);
+# else
+  if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000))
+    return ::GetLastError();
+# endif
+  return 0;
+#else
+  __try
+  {
+# if defined(UNDER_CE)
+    ::InitializeCriticalSection(&crit_section_);
+# else
+    if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000))
+      return ::GetLastError();
+# endif
+  }
+  __except(GetExceptionCode() == STATUS_NO_MEMORY
+      ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+  {
+    return ERROR_OUTOFMEMORY;
+  }
+
+  return 0;
+#endif
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_WINDOWS)
+
+#endif // ASIO_DETAIL_IMPL_WIN_MUTEX_IPP

+ 138 - 0
ext/asio/asio/detail/impl/win_thread.ipp

@@ -0,0 +1,138 @@
+//
+// detail/impl/win_thread.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WIN_THREAD_IPP
+#define ASIO_DETAIL_IMPL_WIN_THREAD_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_WINDOWS) && !defined(UNDER_CE)
+
+#include <process.h>
+#include "asio/detail/throw_error.hpp"
+#include "asio/detail/win_thread.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+win_thread::~win_thread()
+{
+  ::CloseHandle(thread_);
+
+  // The exit_event_ handle is deliberately allowed to leak here since it
+  // is an error for the owner of an internal thread not to join() it.
+}
+
+void win_thread::join()
+{
+  HANDLE handles[2] = { exit_event_, thread_ };
+  ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
+  ::CloseHandle(exit_event_);
+  if (terminate_threads())
+  {
+    ::TerminateThread(thread_, 0);
+  }
+  else
+  {
+    ::QueueUserAPC(apc_function, thread_, 0);
+    ::WaitForSingleObject(thread_, INFINITE);
+  }
+}
+
+void win_thread::start_thread(func_base* arg, unsigned int stack_size)
+{
+  ::HANDLE entry_event = 0;
+  arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0);
+  if (!entry_event)
+  {
+    DWORD last_error = ::GetLastError();
+    delete arg;
+    asio::error_code ec(last_error,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "thread.entry_event");
+  }
+
+  arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0);
+  if (!exit_event_)
+  {
+    DWORD last_error = ::GetLastError();
+    delete arg;
+    asio::error_code ec(last_error,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "thread.exit_event");
+  }
+
+  unsigned int thread_id = 0;
+  thread_ = reinterpret_cast<HANDLE>(::_beginthreadex(0,
+        stack_size, win_thread_function, arg, 0, &thread_id));
+  if (!thread_)
+  {
+    DWORD last_error = ::GetLastError();
+    delete arg;
+    if (entry_event)
+      ::CloseHandle(entry_event);
+    if (exit_event_)
+      ::CloseHandle(exit_event_);
+    asio::error_code ec(last_error,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "thread");
+  }
+
+  if (entry_event)
+  {
+    ::WaitForSingleObject(entry_event, INFINITE);
+    ::CloseHandle(entry_event);
+  }
+}
+
+unsigned int __stdcall win_thread_function(void* arg)
+{
+  std::auto_ptr<win_thread::func_base> func(
+      static_cast<win_thread::func_base*>(arg));
+
+  ::SetEvent(func->entry_event_);
+
+  func->run();
+
+  // Signal that the thread has finished its work, but rather than returning go
+  // to sleep to put the thread into a well known state. If the thread is being
+  // joined during global object destruction then it may be killed using
+  // TerminateThread (to avoid a deadlock in DllMain). Otherwise, the SleepEx
+  // call will be interrupted using QueueUserAPC and the thread will shut down
+  // cleanly.
+  HANDLE exit_event = func->exit_event_;
+  func.reset();
+  ::SetEvent(exit_event);
+  ::SleepEx(INFINITE, TRUE);
+
+  return 0;
+}
+
+#if defined(WINVER) && (WINVER < 0x0500)
+void __stdcall apc_function(ULONG) {}
+#else
+void __stdcall apc_function(ULONG_PTR) {}
+#endif
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
+
+#endif // ASIO_DETAIL_IMPL_WIN_THREAD_IPP

+ 57 - 0
ext/asio/asio/detail/impl/win_tss_ptr.ipp

@@ -0,0 +1,57 @@
+//
+// detail/impl/win_tss_ptr.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WIN_TSS_PTR_IPP
+#define ASIO_DETAIL_IMPL_WIN_TSS_PTR_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_WINDOWS)
+
+#include "asio/detail/throw_error.hpp"
+#include "asio/detail/win_tss_ptr.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+DWORD win_tss_ptr_create()
+{
+#if defined(UNDER_CE)
+  enum { out_of_indexes = 0xFFFFFFFF };
+#else
+  enum { out_of_indexes = TLS_OUT_OF_INDEXES };
+#endif
+
+  DWORD tss_key = ::TlsAlloc();
+  if (tss_key == out_of_indexes)
+  {
+    DWORD last_error = ::GetLastError();
+    asio::error_code ec(last_error,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "tss");
+  }
+  return tss_key;
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_WINDOWS)
+
+#endif // ASIO_DETAIL_IMPL_WIN_TSS_PTR_IPP

+ 69 - 0
ext/asio/asio/detail/impl/winsock_init.ipp

@@ -0,0 +1,69 @@
+//
+// detail/impl/winsock_init.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 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)
+//
+
+#ifndef ASIO_DETAIL_IMPL_WINSOCK_INIT_IPP
+#define ASIO_DETAIL_IMPL_WINSOCK_INIT_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#include "asio/detail/socket_types.hpp"
+#include "asio/detail/winsock_init.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+void winsock_init_base::startup(data& d,
+    unsigned char major, unsigned char minor)
+{
+  if (::InterlockedIncrement(&d.init_count_) == 1)
+  {
+    WSADATA wsa_data;
+    long result = ::WSAStartup(MAKEWORD(major, minor), &wsa_data);
+    ::InterlockedExchange(&d.result_, result);
+  }
+}
+
+void winsock_init_base::cleanup(data& d)
+{
+  if (::InterlockedDecrement(&d.init_count_) == 0)
+  {
+    ::WSACleanup();
+  }
+}
+
+void winsock_init_base::throw_on_error(data& d)
+{
+  long result = ::InterlockedExchangeAdd(&d.result_, 0);
+  if (result != 0)
+  {
+    asio::error_code ec(result,
+        asio::error::get_system_category());
+    asio::detail::throw_error(ec, "winsock");
+  }
+}
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#endif // ASIO_DETAIL_IMPL_WINSOCK_INIT_IPP

+ 0 - 0
ext/asio/asio/detail/io_control.hpp


Some files were not shown because too many files changed in this diff