summaryrefslogtreecommitdiffstats
path: root/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext')
-rw-r--r--ext/asio/README2
-rw-r--r--ext/asio/asio.hpp2
-rw-r--r--ext/asio/asio/basic_datagram_socket.hpp13
-rw-r--r--ext/asio/asio/basic_deadline_timer.hpp13
-rw-r--r--ext/asio/asio/basic_io_object.hpp9
-rw-r--r--ext/asio/asio/basic_raw_socket.hpp15
-rw-r--r--ext/asio/asio/basic_serial_port.hpp20
-rw-r--r--ext/asio/asio/basic_socket.hpp13
-rw-r--r--ext/asio/asio/basic_socket_acceptor.hpp9
-rw-r--r--ext/asio/asio/basic_socket_iostream.hpp17
-rw-r--r--ext/asio/asio/basic_socket_streambuf.hpp19
-rw-r--r--ext/asio/asio/basic_stream_socket.hpp13
-rw-r--r--ext/asio/asio/basic_streambuf.hpp38
-rw-r--r--ext/asio/asio/basic_streambuf_fwd.hpp33
-rw-r--r--ext/asio/asio/buffer.hpp22
-rw-r--r--ext/asio/asio/buffered_read_stream.hpp15
-rw-r--r--ext/asio/asio/buffered_read_stream_fwd.hpp6
-rw-r--r--ext/asio/asio/buffered_stream.hpp13
-rw-r--r--ext/asio/asio/buffered_stream_fwd.hpp6
-rw-r--r--ext/asio/asio/buffered_write_stream.hpp17
-rw-r--r--ext/asio/asio/buffered_write_stream_fwd.hpp6
-rw-r--r--ext/asio/asio/buffers_iterator.hpp20
-rw-r--r--ext/asio/asio/completion_condition.hpp8
-rw-r--r--ext/asio/asio/datagram_socket_service.hpp12
-rw-r--r--ext/asio/asio/deadline_timer.hpp10
-rw-r--r--ext/asio/asio/deadline_timer_service.hpp14
-rw-r--r--ext/asio/asio/detail/array_fwd.hpp25
-rw-r--r--ext/asio/asio/detail/base_from_completion_cond.hpp17
-rw-r--r--ext/asio/asio/detail/bind_handler.hpp31
-rw-r--r--ext/asio/asio/detail/buffer_resize_guard.hpp12
-rw-r--r--ext/asio/asio/detail/buffer_sequence_adapter.hpp20
-rw-r--r--ext/asio/asio/detail/buffered_stream_storage.hpp14
-rw-r--r--ext/asio/asio/detail/call_stack.hpp11
-rw-r--r--ext/asio/asio/detail/completion_handler.hpp34
-rw-r--r--ext/asio/asio/detail/config.hpp205
-rw-r--r--ext/asio/asio/detail/consuming_buffers.hpp20
-rw-r--r--ext/asio/asio/detail/deadline_timer_service.hpp76
-rw-r--r--ext/asio/asio/detail/descriptor_ops.hpp171
-rw-r--r--ext/asio/asio/detail/descriptor_read_op.hpp114
-rw-r--r--ext/asio/asio/detail/descriptor_write_op.hpp114
-rw-r--r--ext/asio/asio/detail/dev_poll_reactor.hpp366
-rw-r--r--ext/asio/asio/detail/dev_poll_reactor_fwd.hpp19
-rw-r--r--ext/asio/asio/detail/epoll_reactor.hpp426
-rw-r--r--ext/asio/asio/detail/epoll_reactor_fwd.hpp26
-rw-r--r--ext/asio/asio/detail/event.hpp14
-rw-r--r--ext/asio/asio/detail/eventfd_select_interrupter.hpp120
-rw-r--r--ext/asio/asio/detail/fd_set_adapter.hpp15
-rw-r--r--ext/asio/asio/detail/fenced_block.hpp34
-rw-r--r--ext/asio/asio/detail/gcc_arm_fenced_block.hpp76
-rw-r--r--ext/asio/asio/detail/gcc_hppa_fenced_block.hpp58
-rw-r--r--ext/asio/asio/detail/gcc_sync_fenced_block.hpp61
-rw-r--r--ext/asio/asio/detail/gcc_x86_fenced_block.hpp18
-rw-r--r--ext/asio/asio/detail/handler_alloc_helpers.hpp238
-rw-r--r--ext/asio/asio/detail/handler_invoke_helpers.hpp14
-rw-r--r--ext/asio/asio/detail/hash_map.hpp35
-rw-r--r--ext/asio/asio/detail/impl/descriptor_ops.ipp370
-rw-r--r--ext/asio/asio/detail/impl/dev_poll_reactor.hpp77
-rw-r--r--ext/asio/asio/detail/impl/dev_poll_reactor.ipp338
-rw-r--r--ext/asio/asio/detail/impl/epoll_reactor.hpp75
-rw-r--r--ext/asio/asio/detail/impl/epoll_reactor.ipp390
-rw-r--r--ext/asio/asio/detail/impl/eventfd_select_interrupter.ipp125
-rw-r--r--ext/asio/asio/detail/impl/kqueue_reactor.hpp79
-rw-r--r--ext/asio/asio/detail/impl/kqueue_reactor.ipp385
-rw-r--r--ext/asio/asio/detail/impl/pipe_select_interrupter.ipp96
-rw-r--r--ext/asio/asio/detail/impl/posix_event.ipp46
-rw-r--r--ext/asio/asio/detail/impl/posix_mutex.ipp46
-rw-r--r--ext/asio/asio/detail/impl/posix_thread.ipp74
-rw-r--r--ext/asio/asio/detail/impl/posix_tss_ptr.ipp46
-rw-r--r--ext/asio/asio/detail/impl/reactive_descriptor_service.ipp136
-rw-r--r--ext/asio/asio/detail/impl/reactive_serial_port_service.ipp151
-rw-r--r--ext/asio/asio/detail/impl/reactive_socket_service_base.ipp212
-rw-r--r--ext/asio/asio/detail/impl/resolver_service_base.ipp106
-rw-r--r--ext/asio/asio/detail/impl/select_reactor.hpp84
-rw-r--r--ext/asio/asio/detail/impl/select_reactor.ipp273
-rw-r--r--ext/asio/asio/detail/impl/service_registry.hpp70
-rw-r--r--ext/asio/asio/detail/impl/service_registry.ipp164
-rw-r--r--ext/asio/asio/detail/impl/socket_ops.ipp2863
-rw-r--r--ext/asio/asio/detail/impl/socket_select_interrupter.ipp151
-rw-r--r--ext/asio/asio/detail/impl/strand_service.hpp140
-rw-r--r--ext/asio/asio/detail/impl/strand_service.ipp106
-rw-r--r--ext/asio/asio/detail/impl/task_io_service.hpp60
-rw-r--r--ext/asio/asio/detail/impl/task_io_service.ipp354
-rw-r--r--ext/asio/asio/detail/impl/throw_error.ipp45
-rw-r--r--ext/asio/asio/detail/impl/timer_queue.ipp85
-rw-r--r--ext/asio/asio/detail/impl/timer_queue_set.ipp101
-rw-r--r--ext/asio/asio/detail/impl/win_event.ipp50
-rw-r--r--ext/asio/asio/detail/impl/win_iocp_handle_service.ipp452
-rw-r--r--ext/asio/asio/detail/impl/win_iocp_io_service.hpp115
-rw-r--r--ext/asio/asio/detail/impl/win_iocp_io_service.ipp496
-rw-r--r--ext/asio/asio/detail/impl/win_iocp_serial_port_service.ipp180
-rw-r--r--ext/asio/asio/detail/impl/win_iocp_socket_service_base.ipp575
-rw-r--r--ext/asio/asio/detail/impl/win_mutex.ipp78
-rw-r--r--ext/asio/asio/detail/impl/win_thread.ipp138
-rw-r--r--ext/asio/asio/detail/impl/win_tss_ptr.ipp57
-rw-r--r--ext/asio/asio/detail/impl/winsock_init.ipp69
-rw-r--r--ext/asio/asio/detail/io_control.hpp14
-rw-r--r--ext/asio/asio/detail/kqueue_reactor.hpp406
-rw-r--r--ext/asio/asio/detail/kqueue_reactor_fwd.hpp23
-rw-r--r--ext/asio/asio/detail/local_free_on_block_exit.hpp18
-rw-r--r--ext/asio/asio/detail/macos_fenced_block.hpp20
-rw-r--r--ext/asio/asio/detail/mutex.hpp14
-rw-r--r--ext/asio/asio/detail/noncopyable.hpp14
-rw-r--r--ext/asio/asio/detail/null_event.hpp18
-rw-r--r--ext/asio/asio/detail/null_fenced_block.hpp6
-rw-r--r--ext/asio/asio/detail/null_mutex.hpp18
-rw-r--r--ext/asio/asio/detail/null_signal_blocker.hpp28
-rw-r--r--ext/asio/asio/detail/null_thread.hpp31
-rw-r--r--ext/asio/asio/detail/null_tss_ptr.hpp18
-rw-r--r--ext/asio/asio/detail/object_pool.hpp146
-rw-r--r--ext/asio/asio/detail/old_win_sdk_compat.hpp18
-rw-r--r--ext/asio/asio/detail/op_queue.hpp10
-rw-r--r--ext/asio/asio/detail/operation.hpp15
-rw-r--r--ext/asio/asio/detail/pipe_select_interrupter.hpp84
-rw-r--r--ext/asio/asio/detail/pop_options.hpp16
-rw-r--r--ext/asio/asio/detail/posix_event.hpp44
-rw-r--r--ext/asio/asio/detail/posix_fd_set_adapter.hpp19
-rw-r--r--ext/asio/asio/detail/posix_mutex.hpp43
-rw-r--r--ext/asio/asio/detail/posix_signal_blocker.hpp23
-rw-r--r--ext/asio/asio/detail/posix_thread.hpp80
-rw-r--r--ext/asio/asio/detail/posix_tss_ptr.hpp44
-rw-r--r--ext/asio/asio/detail/push_options.hpp18
-rw-r--r--ext/asio/asio/detail/reactive_descriptor_service.hpp549
-rw-r--r--ext/asio/asio/detail/reactive_null_buffers_op.hpp83
-rw-r--r--ext/asio/asio/detail/reactive_serial_port_service.hpp186
-rw-r--r--ext/asio/asio/detail/reactive_socket_accept_op.hpp131
-rw-r--r--ext/asio/asio/detail/reactive_socket_connect_op.hpp101
-rw-r--r--ext/asio/asio/detail/reactive_socket_recv_op.hpp118
-rw-r--r--ext/asio/asio/detail/reactive_socket_recvfrom_op.hpp128
-rw-r--r--ext/asio/asio/detail/reactive_socket_send_op.hpp115
-rw-r--r--ext/asio/asio/detail/reactive_socket_sendto_op.hpp118
-rw-r--r--ext/asio/asio/detail/reactive_socket_service.hpp1576
-rw-r--r--ext/asio/asio/detail/reactive_socket_service_base.hpp298
-rw-r--r--ext/asio/asio/detail/reactor.hpp10
-rw-r--r--ext/asio/asio/detail/reactor_fwd.hpp30
-rw-r--r--ext/asio/asio/detail/reactor_op.hpp11
-rw-r--r--ext/asio/asio/detail/reactor_op_queue.hpp13
-rw-r--r--ext/asio/asio/detail/regex_fwd.hpp31
-rw-r--r--ext/asio/asio/detail/resolve_endpoint_op.hpp116
-rw-r--r--ext/asio/asio/detail/resolve_op.hpp126
-rw-r--r--ext/asio/asio/detail/resolver_service.hpp401
-rw-r--r--ext/asio/asio/detail/resolver_service_base.hpp123
-rw-r--r--ext/asio/asio/detail/scoped_lock.hpp10
-rw-r--r--ext/asio/asio/detail/select_interrupter.hpp21
-rw-r--r--ext/asio/asio/detail/select_reactor.hpp308
-rw-r--r--ext/asio/asio/detail/select_reactor_fwd.hpp11
-rw-r--r--ext/asio/asio/detail/service_registry.hpp197
-rw-r--r--ext/asio/asio/detail/service_registry_fwd.hpp10
-rw-r--r--ext/asio/asio/detail/shared_ptr.hpp38
-rw-r--r--ext/asio/asio/detail/signal_blocker.hpp24
-rw-r--r--ext/asio/asio/detail/signal_init.hpp20
-rw-r--r--ext/asio/asio/detail/socket_holder.hpp17
-rw-r--r--ext/asio/asio/detail/socket_ops.hpp2051
-rw-r--r--ext/asio/asio/detail/socket_option.hpp14
-rw-r--r--ext/asio/asio/detail/socket_select_interrupter.hpp156
-rw-r--r--ext/asio/asio/detail/socket_types.hpp76
-rw-r--r--ext/asio/asio/detail/solaris_fenced_block.hpp20
-rw-r--r--ext/asio/asio/detail/strand_service.hpp204
-rw-r--r--ext/asio/asio/detail/task_io_service.hpp381
-rw-r--r--ext/asio/asio/detail/task_io_service_fwd.hpp11
-rw-r--r--ext/asio/asio/detail/task_io_service_operation.hpp18
-rw-r--r--ext/asio/asio/detail/thread.hpp14
-rw-r--r--ext/asio/asio/detail/throw_error.hpp35
-rw-r--r--ext/asio/asio/detail/timer_op.hpp11
-rw-r--r--ext/asio/asio/detail/timer_queue.hpp289
-rw-r--r--ext/asio/asio/detail/timer_queue_base.hpp11
-rw-r--r--ext/asio/asio/detail/timer_queue_fwd.hpp10
-rw-r--r--ext/asio/asio/detail/timer_queue_set.hpp85
-rw-r--r--ext/asio/asio/detail/timer_scheduler.hpp11
-rw-r--r--ext/asio/asio/detail/timer_scheduler_fwd.hpp28
-rw-r--r--ext/asio/asio/detail/tss_ptr.hpp14
-rw-r--r--ext/asio/asio/detail/wait_handler.hpp76
-rw-r--r--ext/asio/asio/detail/weak_ptr.hpp39
-rw-r--r--ext/asio/asio/detail/win_event.hpp40
-rw-r--r--ext/asio/asio/detail/win_fd_set_adapter.hpp16
-rw-r--r--ext/asio/asio/detail/win_fenced_block.hpp36
-rw-r--r--ext/asio/asio/detail/win_iocp_handle_read_op.hpp101
-rw-r--r--ext/asio/asio/detail/win_iocp_handle_service.hpp573
-rw-r--r--ext/asio/asio/detail/win_iocp_handle_write_op.hpp97
-rw-r--r--ext/asio/asio/detail/win_iocp_io_service.hpp599
-rw-r--r--ext/asio/asio/detail/win_iocp_io_service_fwd.hpp30
-rw-r--r--ext/asio/asio/detail/win_iocp_null_buffers_op.hpp112
-rw-r--r--ext/asio/asio/detail/win_iocp_operation.hpp19
-rw-r--r--ext/asio/asio/detail/win_iocp_overlapped_op.hpp84
-rw-r--r--ext/asio/asio/detail/win_iocp_overlapped_ptr.hpp72
-rw-r--r--ext/asio/asio/detail/win_iocp_serial_port_service.hpp214
-rw-r--r--ext/asio/asio/detail/win_iocp_socket_accept_op.hpp158
-rw-r--r--ext/asio/asio/detail/win_iocp_socket_recv_op.hpp108
-rw-r--r--ext/asio/asio/detail/win_iocp_socket_recvfrom_op.hpp116
-rw-r--r--ext/asio/asio/detail/win_iocp_socket_send_op.hpp102
-rw-r--r--ext/asio/asio/detail/win_iocp_socket_service.hpp1806
-rw-r--r--ext/asio/asio/detail/win_iocp_socket_service_base.hpp385
-rw-r--r--ext/asio/asio/detail/win_mutex.hpp69
-rw-r--r--ext/asio/asio/detail/win_thread.hpp153
-rw-r--r--ext/asio/asio/detail/win_tss_ptr.hpp44
-rw-r--r--ext/asio/asio/detail/wince_thread.hpp32
-rw-r--r--ext/asio/asio/detail/winsock_init.hpp120
-rw-r--r--ext/asio/asio/detail/wrapped_handler.hpp18
-rw-r--r--ext/asio/asio/error.hpp44
-rw-r--r--ext/asio/asio/error_code.hpp28
-rw-r--r--ext/asio/asio/handler_alloc_hook.hpp8
-rw-r--r--ext/asio/asio/handler_invoke_hook.hpp4
-rw-r--r--ext/asio/asio/impl/error.ipp33
-rw-r--r--ext/asio/asio/impl/error_code.ipp97
-rw-r--r--ext/asio/asio/impl/io_service.hpp132
-rw-r--r--ext/asio/asio/impl/io_service.ipp143
-rw-r--r--ext/asio/asio/impl/read.hpp386
-rw-r--r--ext/asio/asio/impl/read_at.hpp410
-rw-r--r--ext/asio/asio/impl/read_until.hpp902
-rw-r--r--ext/asio/asio/impl/serial_port_base.hpp59
-rw-r--r--ext/asio/asio/impl/serial_port_base.ipp106
-rw-r--r--ext/asio/asio/impl/src.cpp25
-rw-r--r--ext/asio/asio/impl/src.hpp65
-rw-r--r--ext/asio/asio/impl/write.hpp396
-rw-r--r--ext/asio/asio/impl/write_at.hpp417
-rw-r--r--ext/asio/asio/io_service.hpp105
-rw-r--r--ext/asio/asio/ip/address.hpp207
-rw-r--r--ext/asio/asio/ip/address_v4.hpp175
-rw-r--r--ext/asio/asio/ip/address_v6.hpp305
-rw-r--r--ext/asio/asio/ip/basic_endpoint.hpp235
-rw-r--r--ext/asio/asio/ip/basic_resolver.hpp13
-rw-r--r--ext/asio/asio/ip/basic_resolver_entry.hpp11
-rw-r--r--ext/asio/asio/ip/basic_resolver_iterator.hpp18
-rw-r--r--ext/asio/asio/ip/basic_resolver_query.hpp15
-rw-r--r--ext/asio/asio/ip/detail/endpoint.hpp140
-rw-r--r--ext/asio/asio/ip/detail/impl/endpoint.ipp191
-rw-r--r--ext/asio/asio/ip/detail/socket_option.hpp17
-rw-r--r--ext/asio/asio/ip/host_name.hpp44
-rw-r--r--ext/asio/asio/ip/icmp.hpp13
-rw-r--r--ext/asio/asio/ip/impl/address.hpp53
-rw-r--r--ext/asio/asio/ip/impl/address.ipp186
-rw-r--r--ext/asio/asio/ip/impl/address_v4.hpp53
-rw-r--r--ext/asio/asio/ip/impl/address_v4.ipp162
-rw-r--r--ext/asio/asio/ip/impl/address_v6.hpp53
-rw-r--r--ext/asio/asio/ip/impl/address_v6.ipp284
-rw-r--r--ext/asio/asio/ip/impl/basic_endpoint.hpp55
-rw-r--r--ext/asio/asio/ip/impl/host_name.ipp54
-rw-r--r--ext/asio/asio/ip/multicast.hpp15
-rw-r--r--ext/asio/asio/ip/resolver_query_base.hpp15
-rw-r--r--ext/asio/asio/ip/resolver_service.hpp23
-rw-r--r--ext/asio/asio/ip/tcp.hpp15
-rw-r--r--ext/asio/asio/ip/udp.hpp13
-rw-r--r--ext/asio/asio/ip/unicast.hpp15
-rw-r--r--ext/asio/asio/ip/v6_only.hpp11
-rw-r--r--ext/asio/asio/is_read_buffered.hpp11
-rw-r--r--ext/asio/asio/is_write_buffered.hpp11
-rw-r--r--ext/asio/asio/local/basic_endpoint.hpp137
-rw-r--r--ext/asio/asio/local/connect_pair.hpp30
-rw-r--r--ext/asio/asio/local/datagram_protocol.hpp20
-rw-r--r--ext/asio/asio/local/detail/endpoint.hpp133
-rw-r--r--ext/asio/asio/local/detail/impl/endpoint.ipp128
-rw-r--r--ext/asio/asio/local/stream_protocol.hpp20
-rw-r--r--ext/asio/asio/placeholders.hpp9
-rw-r--r--ext/asio/asio/posix/basic_descriptor.hpp20
-rw-r--r--ext/asio/asio/posix/basic_stream_descriptor.hpp24
-rw-r--r--ext/asio/asio/posix/descriptor_base.hpp19
-rw-r--r--ext/asio/asio/posix/stream_descriptor.hpp14
-rw-r--r--ext/asio/asio/posix/stream_descriptor_service.hpp32
-rw-r--r--ext/asio/asio/raw_socket_service.hpp12
-rw-r--r--ext/asio/asio/read.hpp17
-rw-r--r--ext/asio/asio/read_at.hpp17
-rw-r--r--ext/asio/asio/read_until.hpp21
-rw-r--r--ext/asio/asio/serial_port.hpp10
-rw-r--r--ext/asio/asio/serial_port_base.hpp71
-rw-r--r--ext/asio/asio/serial_port_service.hpp23
-rw-r--r--ext/asio/asio/socket_acceptor_service.hpp8
-rw-r--r--ext/asio/asio/socket_base.hpp11
-rw-r--r--ext/asio/asio/ssl.hpp2
-rwxr-xr-xext/asio/asio/ssl/basic_context.hpp16
-rw-r--r--ext/asio/asio/ssl/context.hpp11
-rwxr-xr-xext/asio/asio/ssl/context_base.hpp15
-rwxr-xr-xext/asio/asio/ssl/context_service.hpp15
-rwxr-xr-xext/asio/asio/ssl/detail/openssl_context_service.hpp15
-rwxr-xr-xext/asio/asio/ssl/detail/openssl_init.hpp15
-rwxr-xr-xext/asio/asio/ssl/detail/openssl_operation.hpp22
-rw-r--r--ext/asio/asio/ssl/detail/openssl_stream_service.hpp26
-rwxr-xr-xext/asio/asio/ssl/detail/openssl_types.hpp16
-rw-r--r--ext/asio/asio/ssl/stream.hpp17
-rwxr-xr-xext/asio/asio/ssl/stream_base.hpp11
-rw-r--r--ext/asio/asio/ssl/stream_service.hpp18
-rw-r--r--ext/asio/asio/strand.hpp9
-rw-r--r--ext/asio/asio/stream_socket_service.hpp12
-rw-r--r--ext/asio/asio/streambuf.hpp10
-rw-r--r--ext/asio/asio/system_error.hpp11
-rw-r--r--ext/asio/asio/thread.hpp7
-rw-r--r--ext/asio/asio/time_traits.hpp6
-rw-r--r--ext/asio/asio/version.hpp4
-rw-r--r--ext/asio/asio/windows/basic_handle.hpp22
-rw-r--r--ext/asio/asio/windows/basic_random_access_handle.hpp24
-rw-r--r--ext/asio/asio/windows/basic_stream_handle.hpp22
-rw-r--r--ext/asio/asio/windows/overlapped_ptr.hpp26
-rw-r--r--ext/asio/asio/windows/random_access_handle.hpp14
-rw-r--r--ext/asio/asio/windows/random_access_handle_service.hpp30
-rw-r--r--ext/asio/asio/windows/stream_handle.hpp14
-rw-r--r--ext/asio/asio/windows/stream_handle_service.hpp31
-rw-r--r--ext/asio/asio/write.hpp17
-rw-r--r--ext/asio/asio/write_at.hpp17
296 files changed, 20964 insertions, 13033 deletions
diff --git a/ext/asio/README b/ext/asio/README
index c581e8e90c..9b919aa9c0 100644
--- a/ext/asio/README
+++ b/ext/asio/README
@@ -1,5 +1,5 @@
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.
diff --git a/ext/asio/asio.hpp b/ext/asio/asio.hpp
index d8acd5859e..b0ebc96b00 100644
--- a/ext/asio/asio.hpp
+++ b/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)
diff --git a/ext/asio/asio/basic_datagram_socket.hpp b/ext/asio/asio/basic_datagram_socket.hpp
index cb149f9835..2cbb3544a0 100644
--- a/ext/asio/asio/basic_datagram_socket.hpp
+++ b/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 {
diff --git a/ext/asio/asio/basic_deadline_timer.hpp b/ext/asio/asio/basic_deadline_timer.hpp
index 0d183f76ca..27781e7bd4 100644
--- a/ext/asio/asio/basic_deadline_timer.hpp
+++ b/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 {
diff --git a/ext/asio/asio/basic_io_object.hpp b/ext/asio/asio/basic_io_object.hpp
index 092170df94..da35462024 100644
--- a/ext/asio/asio/basic_io_object.hpp
+++ b/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 {
diff --git a/ext/asio/asio/basic_raw_socket.hpp b/ext/asio/asio/basic_raw_socket.hpp
index 9d93b97f14..7a55c4a49c 100644
--- a/ext/asio/asio/basic_raw_socket.hpp
+++ b/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 {
diff --git a/ext/asio/asio/basic_serial_port.hpp b/ext/asio/asio/basic_serial_port.hpp
index edb7bb07a0..38fe5e99fa 100644
--- a/ext/asio/asio/basic_serial_port.hpp
+++ b/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
diff --git a/ext/asio/asio/basic_socket.hpp b/ext/asio/asio/basic_socket.hpp
index 8b3f1d7f6b..5c66b4ad22 100644
--- a/ext/asio/asio/basic_socket.hpp
+++ b/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 {
diff --git a/ext/asio/asio/basic_socket_acceptor.hpp b/ext/asio/asio/basic_socket_acceptor.hpp
index 97fa56b776..15f9220dca 100644
--- a/ext/asio/asio/basic_socket_acceptor.hpp
+++ b/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 {
diff --git a/ext/asio/asio/basic_socket_iostream.hpp b/ext/asio/asio/basic_socket_iostream.hpp
index 361ecb82cd..efcd51e94b 100644
--- a/ext/asio/asio/basic_socket_iostream.hpp
+++ b/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
diff --git a/ext/asio/asio/basic_socket_streambuf.hpp b/ext/asio/asio/basic_socket_streambuf.hpp
index ae0264e3ea..05fc86591d 100644
--- a/ext/asio/asio/basic_socket_streambuf.hpp
+++ b/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
diff --git a/ext/asio/asio/basic_stream_socket.hpp b/ext/asio/asio/basic_stream_socket.hpp
index b7b4f065fa..41543fc189 100644
--- a/ext/asio/asio/basic_stream_socket.hpp
+++ b/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 {
diff --git a/ext/asio/asio/basic_streambuf.hpp b/ext/asio/asio/basic_streambuf.hpp
index b34b3fecf7..17157da89f 100644
--- a/ext/asio/asio/basic_streambuf.hpp
+++ b/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"
diff --git a/ext/asio/asio/basic_streambuf_fwd.hpp b/ext/asio/asio/basic_streambuf_fwd.hpp
new file mode 100644
index 0000000000..e1d81ac5e3
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/buffer.hpp b/ext/asio/asio/buffer.hpp
index 43b475c5be..6810fca644 100644
--- a/ext/asio/asio/buffer.hpp
+++ b/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;
diff --git a/ext/asio/asio/buffered_read_stream.hpp b/ext/asio/asio/buffered_read_stream.hpp
index afd22cec86..d9dc31160f 100644
--- a/ext/asio/asio/buffered_read_stream.hpp
+++ b/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 {
diff --git a/ext/asio/asio/buffered_read_stream_fwd.hpp b/ext/asio/asio/buffered_read_stream_fwd.hpp
index 5078775d11..0e8495a04a 100644
--- a/ext/asio/asio/buffered_read_stream_fwd.hpp
+++ b/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
diff --git a/ext/asio/asio/buffered_stream.hpp b/ext/asio/asio/buffered_stream.hpp
index 23dc9c33f9..11b99f6484 100644
--- a/ext/asio/asio/buffered_stream.hpp
+++ b/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 {
diff --git a/ext/asio/asio/buffered_stream_fwd.hpp b/ext/asio/asio/buffered_stream_fwd.hpp
index f26cd43c2d..a8e958e0c2 100644
--- a/ext/asio/asio/buffered_stream_fwd.hpp
+++ b/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
diff --git a/ext/asio/asio/buffered_write_stream.hpp b/ext/asio/asio/buffered_write_stream.hpp
index 30a92ce658..ee0ec7764a 100644
--- a/ext/asio/asio/buffered_write_stream.hpp
+++ b/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 {
diff --git a/ext/asio/asio/buffered_write_stream_fwd.hpp b/ext/asio/asio/buffered_write_stream_fwd.hpp
index dc0e014732..cb09fe8be4 100644
--- a/ext/asio/asio/buffered_write_stream_fwd.hpp
+++ b/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
diff --git a/ext/asio/asio/buffers_iterator.hpp b/ext/asio/asio/buffers_iterator.hpp
index 7da55f2f34..dcca2d37d0 100644
--- a/ext/asio/asio/buffers_iterator.hpp
+++ b/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)
diff --git a/ext/asio/asio/completion_condition.hpp b/ext/asio/asio/completion_condition.hpp
index d4e631d035..dd1fb274fd 100644
--- a/ext/asio/asio/completion_condition.hpp
+++ b/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 {
diff --git a/ext/asio/asio/datagram_socket_service.hpp b/ext/asio/asio/datagram_socket_service.hpp
index 7d135eed7c..87821c377c 100644
--- a/ext/asio/asio/datagram_socket_service.hpp
+++ b/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.
diff --git a/ext/asio/asio/deadline_timer.hpp b/ext/asio/asio/deadline_timer.hpp
index e0905f289d..fd0d5dc7c2 100644
--- a/ext/asio/asio/deadline_timer.hpp
+++ b/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
diff --git a/ext/asio/asio/deadline_timer_service.hpp b/ext/asio/asio/deadline_timer_service.hpp
index 284a690ffb..60d898b2b6 100644
--- a/ext/asio/asio/deadline_timer_service.hpp
+++ b/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 {
diff --git a/ext/asio/asio/detail/array_fwd.hpp b/ext/asio/asio/detail/array_fwd.hpp
new file mode 100644
index 0000000000..12c295cde8
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/base_from_completion_cond.hpp b/ext/asio/asio/detail/base_from_completion_cond.hpp
index 90a11f9900..93cc8c45ff 100644
--- a/ext/asio/asio/detail/base_from_completion_cond.hpp
+++ b/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);
diff --git a/ext/asio/asio/detail/bind_handler.hpp b/ext/asio/asio/detail/bind_handler.hpp
index 5d9eb004ae..f663a5bab2 100644
--- a/ext/asio/asio/detail/bind_handler.hpp
+++ b/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
diff --git a/ext/asio/asio/detail/buffer_resize_guard.hpp b/ext/asio/asio/detail/buffer_resize_guard.hpp
index 368de323fe..4bf6a8ed89 100644
--- a/ext/asio/asio/detail/buffer_resize_guard.hpp
+++ b/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 {
diff --git a/ext/asio/asio/detail/buffer_sequence_adapter.hpp b/ext/asio/asio/detail/buffer_sequence_adapter.hpp
index 6269d6ae28..17044b7920 100644
--- a/ext/asio/asio/detail/buffer_sequence_adapter.hpp
+++ b/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);
}
diff --git a/ext/asio/asio/detail/buffered_stream_storage.hpp b/ext/asio/asio/detail/buffered_stream_storage.hpp
index 51f6556fcb..7e1b7467a9 100644
--- a/ext/asio/asio/detail/buffered_stream_storage.hpp
+++ b/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 {
diff --git a/ext/asio/asio/detail/call_stack.hpp b/ext/asio/asio/detail/call_stack.hpp
index 0e9ddafaa3..7ad5dc5588 100644
--- a/ext/asio/asio/detail/call_stack.hpp
+++ b/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 {
diff --git a/ext/asio/asio/detail/completion_handler.hpp b/ext/asio/asio/detail/completion_handler.hpp
index 16167dfbe2..0224d7e83d 100644
--- a/ext/asio/asio/detail/completion_handler.hpp
+++ b/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);
}
diff --git a/ext/asio/asio/detail/config.hpp b/ext/asio/asio/detail/config.hpp
new file mode 100644
index 0000000000..8328d7661c
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/consuming_buffers.hpp b/ext/asio/asio/detail/consuming_buffers.hpp
index 80b6a8e803..8969ae4d98 100644
--- a/ext/asio/asio/detail/consuming_buffers.hpp
+++ b/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.
diff --git a/ext/asio/asio/detail/deadline_timer_service.hpp b/ext/asio/asio/detail/deadline_timer_service.hpp
index 6daf7acb35..782f5c3b4c 100644
--- a/ext/asio/asio/detail/deadline_timer_service.hpp
+++ b/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:
diff --git a/ext/asio/asio/detail/descriptor_ops.hpp b/ext/asio/asio/detail/descriptor_ops.hpp
index ea3731e7ac..5cac91dc4b 100644
--- a/ext/asio/asio/detail/descriptor_ops.hpp
+++ b/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
diff --git a/ext/asio/asio/detail/descriptor_read_op.hpp b/ext/asio/asio/detail/descriptor_read_op.hpp
new file mode 100644
index 0000000000..0d4516721c
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/descriptor_write_op.hpp b/ext/asio/asio/detail/descriptor_write_op.hpp
new file mode 100644
index 0000000000..9caa283e70
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/dev_poll_reactor.hpp b/ext/asio/asio/detail/dev_poll_reactor.hpp
index 1367b7190f..6bbf1b203d 100644
--- a/ext/asio/asio/detail/dev_poll_reactor.hpp
+++ b/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
diff --git a/ext/asio/asio/detail/dev_poll_reactor_fwd.hpp b/ext/asio/asio/detail/dev_poll_reactor_fwd.hpp
index f7f1aebab4..c54f5e17db 100644
--- a/ext/asio/asio/detail/dev_poll_reactor_fwd.hpp
+++ b/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
diff --git a/ext/asio/asio/detail/epoll_reactor.hpp b/ext/asio/asio/detail/epoll_reactor.hpp
index 0a1eac0265..a085766b5f 100644
--- a/ext/asio/asio/detail/epoll_reactor.hpp
+++ b/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
diff --git a/ext/asio/asio/detail/epoll_reactor_fwd.hpp b/ext/asio/asio/detail/epoll_reactor_fwd.hpp
index 266bccdab0..49df6ed9b7 100644
--- a/ext/asio/asio/detail/epoll_reactor_fwd.hpp
+++ b/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
diff --git a/ext/asio/asio/detail/event.hpp b/ext/asio/asio/detail/event.hpp
index 65aa4cba7f..46ee8a6bd9 100644
--- a/ext/asio/asio/detail/event.hpp
+++ b/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
diff --git a/ext/asio/asio/detail/eventfd_select_interrupter.hpp b/ext/asio/asio/detail/eventfd_select_interrupter.hpp
index 63b7ac4ff5..0d3b95802d 100644
--- a/ext/asio/asio/detail/eventfd_select_interrupter.hpp
+++ b/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
diff --git a/ext/asio/asio/detail/fd_set_adapter.hpp b/ext/asio/asio/detail/fd_set_adapter.hpp
index a575491bfb..953cad1729 100644
--- a/ext/asio/asio/detail/fd_set_adapter.hpp
+++ b/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
diff --git a/ext/asio/asio/detail/fenced_block.hpp b/ext/asio/asio/detail/fenced_block.hpp
index 60198bc65b..70c47e13cf 100644
--- a/ext/asio/asio/detail/fenced_block.hpp
+++ b/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
diff --git a/ext/asio/asio/detail/gcc_arm_fenced_block.hpp b/ext/asio/asio/detail/gcc_arm_fenced_block.hpp
new file mode 100644
index 0000000000..76c4d99900
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/gcc_hppa_fenced_block.hpp b/ext/asio/asio/detail/gcc_hppa_fenced_block.hpp
new file mode 100644
index 0000000000..215086a6cc
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/gcc_sync_fenced_block.hpp b/ext/asio/asio/detail/gcc_sync_fenced_block.hpp
new file mode 100644
index 0000000000..569b559124
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/gcc_x86_fenced_block.hpp b/ext/asio/asio/detail/gcc_x86_fenced_block.hpp
index 48119f4c39..3e2e5bcb7e 100644
--- a/ext/asio/asio/detail/gcc_x86_fenced_block.hpp
+++ b/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
diff --git a/ext/asio/asio/detail/handler_alloc_helpers.hpp b/ext/asio/asio/detail/handler_alloc_helpers.hpp
index 0ac42a7b12..9ae80de916 100644
--- a/ext/asio/asio/detail/handler_alloc_helpers.hpp
+++ b/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"
diff --git a/ext/asio/asio/detail/handler_invoke_helpers.hpp b/ext/asio/asio/detail/handler_invoke_helpers.hpp
index 8332567c9f..5b122d9f69 100644
--- a/ext/asio/asio/detail/handler_invoke_helpers.hpp
+++ b/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.
diff --git a/ext/asio/asio/detail/hash_map.hpp b/ext/asio/asio/detail/hash_map.hpp
index b2a1517865..a3957dfa33 100644
--- a/ext/asio/asio/detail/hash_map.hpp
+++ b/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>
diff --git a/ext/asio/asio/detail/impl/descriptor_ops.ipp b/ext/asio/asio/detail/impl/descriptor_ops.ipp
new file mode 100644
index 0000000000..db08c26351
--- /dev/null
+++ b/ext/asio/asio/detail/impl/descriptor_ops.ipp
@@ -0,0 +1,370 @@
+//
+// 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 {
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+ }
+}
+
+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;
+ }
+}
+
+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;
+ }
+}
+
+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;
+ }
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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
diff --git a/ext/asio/asio/detail/impl/dev_poll_reactor.hpp b/ext/asio/asio/detail/impl/dev_poll_reactor.hpp
new file mode 100644
index 0000000000..7fbef82c3d
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/dev_poll_reactor.ipp b/ext/asio/asio/detail/impl/dev_poll_reactor.ipp
new file mode 100644
index 0000000000..0d1456fcbb
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/epoll_reactor.hpp b/ext/asio/asio/detail/impl/epoll_reactor.hpp
new file mode 100644
index 0000000000..9f50a235bc
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/epoll_reactor.ipp b/ext/asio/asio/detail/impl/epoll_reactor.ipp
new file mode 100644
index 0000000000..a95b8f290d
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/eventfd_select_interrupter.ipp b/ext/asio/asio/detail/impl/eventfd_select_interrupter.ipp
new file mode 100644
index 0000000000..959d356af7
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/kqueue_reactor.hpp b/ext/asio/asio/detail/impl/kqueue_reactor.hpp
new file mode 100644
index 0000000000..7950c3b976
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/kqueue_reactor.ipp b/ext/asio/asio/detail/impl/kqueue_reactor.ipp
new file mode 100644
index 0000000000..8db77cb3e5
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/pipe_select_interrupter.ipp b/ext/asio/asio/detail/impl/pipe_select_interrupter.ipp
new file mode 100644
index 0000000000..aac20d43d2
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/posix_event.ipp b/ext/asio/asio/detail/impl/posix_event.ipp
new file mode 100644
index 0000000000..3206418c54
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/posix_mutex.ipp b/ext/asio/asio/detail/impl/posix_mutex.ipp
new file mode 100644
index 0000000000..12b6659745
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/posix_thread.ipp b/ext/asio/asio/detail/impl/posix_thread.ipp
new file mode 100644
index 0000000000..ce91c57bbc
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/posix_tss_ptr.ipp b/ext/asio/asio/detail/impl/posix_tss_ptr.ipp
new file mode 100644
index 0000000000..89b40f7022
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/reactive_descriptor_service.ipp b/ext/asio/asio/detail/impl/reactive_descriptor_service.ipp
new file mode 100644
index 0000000000..706d60f423
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/reactive_serial_port_service.ipp b/ext/asio/asio/detail/impl/reactive_serial_port_service.ipp
new file mode 100644
index 0000000000..c4df79303c
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/reactive_socket_service_base.ipp b/ext/asio/asio/detail/impl/reactive_socket_service_base.ipp
new file mode 100644
index 0000000000..54e7944875
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/resolver_service_base.ipp b/ext/asio/asio/detail/impl/resolver_service_base.ipp
new file mode 100644
index 0000000000..a844a2374e
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/select_reactor.hpp b/ext/asio/asio/detail/impl/select_reactor.hpp
new file mode 100644
index 0000000000..50d3ad42d0
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/select_reactor.ipp b/ext/asio/asio/detail/impl/select_reactor.ipp
new file mode 100644
index 0000000000..1a59be37e7
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/service_registry.hpp b/ext/asio/asio/detail/impl/service_registry.hpp
new file mode 100644
index 0000000000..c2aa9ec4e4
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/service_registry.ipp b/ext/asio/asio/detail/impl/service_registry.ipp
new file mode 100644
index 0000000000..57c57b88b0
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/socket_ops.ipp b/ext/asio/asio/detail/impl/socket_ops.ipp
new file mode 100644
index 0000000000..d348d1b737
--- /dev/null
+++ b/ext/asio/asio/detail/impl/socket_ops.ipp
@@ -0,0 +1,2863 @@
+//
+// detail/impl/socket_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_SOCKET_OPS_IPP
+#define ASIO_DETAIL_SOCKET_OPS_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/assert.hpp>
+#include <boost/detail/workaround.hpp>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+#include <new>
+#include "asio/detail/socket_ops.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+namespace socket_ops {
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+struct msghdr { int msg_namelen; };
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#if defined(__hpux)
+// HP-UX doesn't declare these functions extern "C", so they are declared again
+// here to avoid linker errors about undefined symbols.
+extern "C" char* if_indextoname(unsigned int, char*);
+extern "C" unsigned int if_nametoindex(const char*);
+#endif // defined(__hpux)
+
+inline void clear_last_error()
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ WSASetLastError(0);
+#else
+ errno = 0;
+#endif
+}
+
+template <typename ReturnType>
+inline ReturnType error_wrapper(ReturnType return_value,
+ asio::error_code& ec)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ ec = asio::error_code(WSAGetLastError(),
+ asio::error::get_system_category());
+#else
+ ec = asio::error_code(errno,
+ asio::error::get_system_category());
+#endif
+ return return_value;
+}
+
+template <typename SockLenType>
+inline socket_type call_accept(SockLenType msghdr::*,
+ socket_type s, socket_addr_type* addr, std::size_t* addrlen)
+{
+ SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0;
+ socket_type result = ::accept(s, addr, addrlen ? &tmp_addrlen : 0);
+ if (addrlen)
+ *addrlen = (std::size_t)tmp_addrlen;
+ return result;
+}
+
+socket_type accept(socket_type s, socket_addr_type* addr,
+ std::size_t* addrlen, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return invalid_socket;
+ }
+
+ clear_last_error();
+
+ socket_type new_s = error_wrapper(call_accept(
+ &msghdr::msg_namelen, s, addr, addrlen), ec);
+ if (new_s == invalid_socket)
+ return new_s;
+
+#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
+ int optval = 1;
+ int result = error_wrapper(::setsockopt(new_s,
+ SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec);
+ if (result != 0)
+ {
+ ::close(new_s);
+ return invalid_socket;
+ }
+#endif
+
+ ec = asio::error_code();
+ return new_s;
+}
+
+socket_type sync_accept(socket_type s, state_type state,
+ socket_addr_type* addr, std::size_t* addrlen, asio::error_code& ec)
+{
+ // Accept a socket.
+ for (;;)
+ {
+ // Try to complete the operation without blocking.
+ socket_type new_socket = socket_ops::accept(s, addr, addrlen, ec);
+
+ // Check if operation succeeded.
+ if (new_socket != invalid_socket)
+ return new_socket;
+
+ // Operation failed.
+ if (ec == asio::error::would_block
+ || ec == asio::error::try_again)
+ {
+ if (state & user_set_non_blocking)
+ return invalid_socket;
+ // Fall through to retry operation.
+ }
+ else if (ec == asio::error::connection_aborted)
+ {
+ if (state & enable_connection_aborted)
+ return invalid_socket;
+ // Fall through to retry operation.
+ }
+#if defined(EPROTO)
+ else if (ec.value() == EPROTO)
+ {
+ if (state & enable_connection_aborted)
+ return invalid_socket;
+ // Fall through to retry operation.
+ }
+#endif // defined(EPROTO)
+ else
+ return invalid_socket;
+
+ // Wait for socket to become ready.
+ if (socket_ops::poll_read(s, ec) < 0)
+ return invalid_socket;
+ }
+}
+
+#if defined(ASIO_HAS_IOCP)
+
+void complete_iocp_accept(socket_type s,
+ void* output_buffer, DWORD address_length,
+ socket_addr_type* addr, std::size_t* addrlen,
+ socket_type new_socket, asio::error_code& ec)
+{
+ // Map non-portable errors to their portable counterparts.
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ ec = asio::error::connection_aborted;
+
+ if (!ec)
+ {
+ // Get the address of the peer.
+ if (addr && addrlen)
+ {
+ LPSOCKADDR local_addr = 0;
+ int local_addr_length = 0;
+ LPSOCKADDR remote_addr = 0;
+ int remote_addr_length = 0;
+ GetAcceptExSockaddrs(output_buffer, 0, address_length,
+ address_length, &local_addr, &local_addr_length,
+ &remote_addr, &remote_addr_length);
+ if (static_cast<std::size_t>(remote_addr_length) > *addrlen)
+ {
+ ec = asio::error::invalid_argument;
+ }
+ else
+ {
+ using namespace std; // For memcpy.
+ memcpy(addr, remote_addr, remote_addr_length);
+ *addrlen = static_cast<std::size_t>(remote_addr_length);
+ }
+ }
+
+ // Need to set the SO_UPDATE_ACCEPT_CONTEXT option so that getsockname
+ // and getpeername will work on the accepted socket.
+ SOCKET update_ctx_param = s;
+ socket_ops::state_type state = 0;
+ socket_ops::setsockopt(new_socket, state,
+ SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
+ &update_ctx_param, sizeof(SOCKET), ec);
+ }
+}
+
+#else // defined(ASIO_HAS_IOCP)
+
+bool non_blocking_accept(socket_type s,
+ state_type state, socket_addr_type* addr, std::size_t* addrlen,
+ asio::error_code& ec, socket_type& new_socket)
+{
+ for (;;)
+ {
+ // Accept the waiting connection.
+ new_socket = socket_ops::accept(s, addr, addrlen, ec);
+
+ // Check if operation succeeded.
+ if (new_socket != invalid_socket)
+ return true;
+
+ // Retry operation if interrupted by signal.
+ if (ec == asio::error::interrupted)
+ continue;
+
+ // Operation failed.
+ if (ec == asio::error::would_block
+ || ec == asio::error::try_again)
+ {
+ if (state & user_set_non_blocking)
+ return true;
+ // Fall through to retry operation.
+ }
+ else if (ec == asio::error::connection_aborted)
+ {
+ if (state & enable_connection_aborted)
+ return true;
+ // Fall through to retry operation.
+ }
+#if defined(EPROTO)
+ else if (ec.value() == EPROTO)
+ {
+ if (state & enable_connection_aborted)
+ return true;
+ // Fall through to retry operation.
+ }
+#endif // defined(EPROTO)
+ else
+ return true;
+
+ return false;
+ }
+}
+
+#endif // defined(ASIO_HAS_IOCP)
+
+template <typename SockLenType>
+inline int call_bind(SockLenType msghdr::*,
+ socket_type s, const socket_addr_type* addr, std::size_t addrlen)
+{
+ return ::bind(s, addr, (SockLenType)addrlen);
+}
+
+int bind(socket_type s, const socket_addr_type* addr,
+ std::size_t addrlen, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return socket_error_retval;
+ }
+
+ clear_last_error();
+ int result = error_wrapper(call_bind(
+ &msghdr::msg_namelen, s, addr, addrlen), ec);
+ if (result == 0)
+ ec = asio::error_code();
+ return result;
+}
+
+int close(socket_type s, state_type& state,
+ bool destruction, asio::error_code& ec)
+{
+ int result = 0;
+ if (s != invalid_socket)
+ {
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ if ((state & non_blocking) && (state & user_set_linger))
+ {
+ ioctl_arg_type arg = 0;
+ ::ioctlsocket(s, FIONBIO, &arg);
+ state &= ~non_blocking;
+ }
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ if (state & non_blocking)
+ {
+#if defined(__SYMBIAN32__)
+ int flags = ::fcntl(s, F_GETFL, 0);
+ if (flags >= 0)
+ ::fcntl(s, F_SETFL, flags & ~O_NONBLOCK);
+#else // defined(__SYMBIAN32__)
+ ioctl_arg_type arg = 0;
+ ::ioctl(s, FIONBIO, &arg);
+#endif // defined(__SYMBIAN32__)
+ state &= ~non_blocking;
+ }
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+ if (destruction && (state & user_set_linger))
+ {
+ ::linger opt;
+ opt.l_onoff = 0;
+ opt.l_linger = 0;
+ asio::error_code ignored_ec;
+ socket_ops::setsockopt(s, state, SOL_SOCKET,
+ SO_LINGER, &opt, sizeof(opt), ignored_ec);
+ }
+
+ clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ result = error_wrapper(::closesocket(s), ec);
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ result = error_wrapper(::close(s), ec);
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ }
+
+ if (result == 0)
+ ec = asio::error_code();
+ return result;
+}
+
+bool set_internal_non_blocking(socket_type s,
+ state_type& state, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return false;
+ }
+
+ clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ ioctl_arg_type arg = 1;
+ int result = error_wrapper(::ioctlsocket(s, FIONBIO, &arg), ec);
+#elif defined(__SYMBIAN32__)
+ int result = error_wrapper(::fcntl(s, F_GETFL, 0), ec);
+ if (result >= 0)
+ {
+ clear_last_error();
+ result = error_wrapper(::fcntl(s, F_SETFL, result | O_NONBLOCK), ec);
+ }
+#else
+ ioctl_arg_type arg = 1;
+ int result = error_wrapper(::ioctl(s, FIONBIO, &arg), ec);
+#endif
+
+ if (result >= 0)
+ {
+ ec = asio::error_code();
+ state |= internal_non_blocking;
+ return true;
+ }
+
+ return false;
+}
+
+int shutdown(socket_type s, int what, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return socket_error_retval;
+ }
+
+ clear_last_error();
+ int result = error_wrapper(::shutdown(s, what), ec);
+ if (result == 0)
+ ec = asio::error_code();
+ return result;
+}
+
+template <typename SockLenType>
+inline int call_connect(SockLenType msghdr::*,
+ socket_type s, const socket_addr_type* addr, std::size_t addrlen)
+{
+ return ::connect(s, addr, (SockLenType)addrlen);
+}
+
+int connect(socket_type s, const socket_addr_type* addr,
+ std::size_t addrlen, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return socket_error_retval;
+ }
+
+ clear_last_error();
+ int result = error_wrapper(call_connect(
+ &msghdr::msg_namelen, s, addr, addrlen), ec);
+ if (result == 0)
+ ec = asio::error_code();
+ return result;
+}
+
+void sync_connect(socket_type s, const socket_addr_type* addr,
+ std::size_t addrlen, asio::error_code& ec)
+{
+ // Perform the connect operation.
+ socket_ops::connect(s, addr, addrlen, ec);
+ if (ec != asio::error::in_progress
+ && ec != asio::error::would_block)
+ {
+ // The connect operation finished immediately.
+ return;
+ }
+
+ // Wait for socket to become ready.
+ if (socket_ops::poll_connect(s, ec) < 0)
+ return;
+
+ // Get the error code from the connect operation.
+ int connect_error = 0;
+ size_t connect_error_len = sizeof(connect_error);
+ if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_ERROR,
+ &connect_error, &connect_error_len, ec) == socket_error_retval)
+ return;
+
+ // Return the result of the connect operation.
+ ec = asio::error_code(connect_error,
+ asio::error::get_system_category());
+}
+
+bool non_blocking_connect(socket_type s, asio::error_code& ec)
+{
+ // Get the error code from the connect operation.
+ int connect_error = 0;
+ size_t connect_error_len = sizeof(connect_error);
+ if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_ERROR,
+ &connect_error, &connect_error_len, ec) == 0)
+ {
+ if (connect_error)
+ {
+ ec = asio::error_code(connect_error,
+ asio::error::get_system_category());
+ }
+ else
+ ec = asio::error_code();
+ }
+
+ return true;
+}
+
+int socketpair(int af, int type, int protocol,
+ socket_type sv[2], asio::error_code& ec)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ (void)(af);
+ (void)(type);
+ (void)(protocol);
+ (void)(sv);
+ ec = asio::error::operation_not_supported;
+ return socket_error_retval;
+#else
+ clear_last_error();
+ int result = error_wrapper(::socketpair(af, type, protocol, sv), ec);
+ if (result == 0)
+ ec = asio::error_code();
+ return result;
+#endif
+}
+
+bool sockatmark(socket_type s, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return false;
+ }
+
+#if defined(SIOCATMARK)
+ ioctl_arg_type value = 0;
+# if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ int result = error_wrapper(::ioctlsocket(s, SIOCATMARK, &value), ec);
+# else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ int result = error_wrapper(::ioctl(s, SIOCATMARK, &value), ec);
+# endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ if (result == 0)
+ ec = asio::error_code();
+# if defined(ENOTTY)
+ if (ec.value() == ENOTTY)
+ ec = asio::error::not_socket;
+# endif // defined(ENOTTY)
+#else // defined(SIOCATMARK)
+ int value = error_wrapper(::sockatmark(s), ec);
+ if (value != -1)
+ ec = asio::error_code();
+#endif // defined(SIOCATMARK)
+
+ return ec ? false : value != 0;
+}
+
+size_t available(socket_type s, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return 0;
+ }
+
+ ioctl_arg_type value = 0;
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ int result = error_wrapper(::ioctlsocket(s, FIONREAD, &value), ec);
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ int result = error_wrapper(::ioctl(s, FIONREAD, &value), ec);
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ if (result == 0)
+ ec = asio::error_code();
+#if defined(ENOTTY)
+ if (ec.value() == ENOTTY)
+ ec = asio::error::not_socket;
+#endif // defined(ENOTTY)
+
+ return ec ? static_cast<size_t>(0) : static_cast<size_t>(value);
+}
+
+int listen(socket_type s, int backlog, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return socket_error_retval;
+ }
+
+ clear_last_error();
+ int result = error_wrapper(::listen(s, backlog), ec);
+ if (result == 0)
+ ec = asio::error_code();
+ return result;
+}
+
+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);
+}
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+typedef WSABUF buf;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+typedef iovec buf;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+void init_buf(buf& b, void* data, size_t size)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ b.buf = static_cast<char*>(data);
+ b.len = static_cast<u_long>(size);
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ init_buf_iov_base(b.iov_base, data);
+ b.iov_len = size;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+void init_buf(buf& b, const void* data, size_t size)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ b.buf = static_cast<char*>(const_cast<void*>(data));
+ b.len = static_cast<u_long>(size);
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ init_buf_iov_base(b.iov_base, const_cast<void*>(data));
+ b.iov_len = size;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+inline void init_msghdr_msg_name(void*& name, socket_addr_type* addr)
+{
+ name = addr;
+}
+
+inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr)
+{
+ name = const_cast<socket_addr_type*>(addr);
+}
+
+template <typename T>
+inline void init_msghdr_msg_name(T& name, socket_addr_type* addr)
+{
+ name = reinterpret_cast<T>(addr);
+}
+
+template <typename T>
+inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr)
+{
+ name = reinterpret_cast<T>(const_cast<socket_addr_type*>(addr));
+}
+
+int recv(socket_type s, buf* bufs, size_t count, int flags,
+ asio::error_code& ec)
+{
+ clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ // Receive some data.
+ DWORD recv_buf_count = static_cast<DWORD>(count);
+ DWORD bytes_transferred = 0;
+ DWORD recv_flags = flags;
+ int result = error_wrapper(::WSARecv(s, bufs,
+ recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec);
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ ec = asio::error::connection_reset;
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ ec = asio::error::connection_refused;
+ if (result != 0)
+ return socket_error_retval;
+ ec = asio::error_code();
+ return bytes_transferred;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ msghdr msg = msghdr();
+ msg.msg_iov = bufs;
+ msg.msg_iovlen = count;
+ int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
+ if (result >= 0)
+ ec = asio::error_code();
+ return result;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+size_t sync_recv(socket_type s, state_type state, buf* bufs,
+ size_t count, int flags, bool all_empty, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // A request to read 0 bytes on a stream is a no-op.
+ if (all_empty && (state & stream_oriented))
+ {
+ ec = asio::error_code();
+ return 0;
+ }
+
+ // Read some data.
+ for (;;)
+ {
+ // Try to complete the operation without blocking.
+ int bytes = socket_ops::recv(s, bufs, count, flags, ec);
+
+ // Check if operation succeeded.
+ if (bytes > 0)
+ return bytes;
+
+ // Check for EOF.
+ if ((state & stream_oriented) && 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 socket to become ready.
+ if (socket_ops::poll_read(s, ec) < 0)
+ return 0;
+ }
+}
+
+#if defined(ASIO_HAS_IOCP)
+
+void complete_iocp_recv(state_type state,
+ const weak_cancel_token_type& cancel_token, bool all_empty,
+ asio::error_code& ec, size_t bytes_transferred)
+{
+ // Map non-portable errors to their portable counterparts.
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ {
+ if (cancel_token.expired())
+ ec = asio::error::operation_aborted;
+ else
+ ec = asio::error::connection_reset;
+ }
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = asio::error::connection_refused;
+ }
+
+ // Check for connection closed.
+ else if (!ec && bytes_transferred == 0
+ && (state & stream_oriented) != 0
+ && !all_empty)
+ {
+ ec = asio::error::eof;
+ }
+}
+
+#else // defined(ASIO_HAS_IOCP)
+
+bool non_blocking_recv(socket_type s,
+ buf* bufs, size_t count, int flags, bool is_stream,
+ asio::error_code& ec, size_t& bytes_transferred)
+{
+ for (;;)
+ {
+ // Read some data.
+ int bytes = socket_ops::recv(s, bufs, count, flags, ec);
+
+ // Check for end of stream.
+ if (is_stream && 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;
+ }
+}
+
+#endif // defined(ASIO_HAS_IOCP)
+
+int recvfrom(socket_type s, buf* bufs, size_t count, int flags,
+ socket_addr_type* addr, std::size_t* addrlen,
+ asio::error_code& ec)
+{
+ clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ // Receive some data.
+ DWORD recv_buf_count = static_cast<DWORD>(count);
+ DWORD bytes_transferred = 0;
+ DWORD recv_flags = flags;
+ int tmp_addrlen = (int)*addrlen;
+ int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count,
+ &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0), ec);
+ *addrlen = (std::size_t)tmp_addrlen;
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ ec = asio::error::connection_reset;
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ ec = asio::error::connection_refused;
+ if (result != 0)
+ return socket_error_retval;
+ ec = asio::error_code();
+ return bytes_transferred;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ msghdr msg = msghdr();
+ init_msghdr_msg_name(msg.msg_name, addr);
+ msg.msg_namelen = *addrlen;
+ msg.msg_iov = bufs;
+ msg.msg_iovlen = count;
+ int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
+ *addrlen = msg.msg_namelen;
+ if (result >= 0)
+ ec = asio::error_code();
+ return result;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+size_t sync_recvfrom(socket_type s, state_type state, buf* bufs,
+ size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Read some data.
+ for (;;)
+ {
+ // Try to complete the operation without blocking.
+ int bytes = socket_ops::recvfrom(s, bufs, count, flags, addr, addrlen, 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 socket to become ready.
+ if (socket_ops::poll_read(s, ec) < 0)
+ return 0;
+ }
+}
+
+#if defined(ASIO_HAS_IOCP)
+
+void complete_iocp_recvfrom(
+ const weak_cancel_token_type& cancel_token,
+ asio::error_code& ec)
+{
+ // Map non-portable errors to their portable counterparts.
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ {
+ if (cancel_token.expired())
+ ec = asio::error::operation_aborted;
+ else
+ ec = asio::error::connection_reset;
+ }
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = asio::error::connection_refused;
+ }
+}
+
+#else // defined(ASIO_HAS_IOCP)
+
+bool non_blocking_recvfrom(socket_type s,
+ buf* bufs, size_t count, int flags,
+ socket_addr_type* addr, std::size_t* addrlen,
+ asio::error_code& ec, size_t& bytes_transferred)
+{
+ for (;;)
+ {
+ // Read some data.
+ int bytes = socket_ops::recvfrom(s, bufs, count, flags, addr, addrlen, 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;
+ }
+}
+
+#endif // defined(ASIO_HAS_IOCP)
+
+int send(socket_type s, const buf* bufs, size_t count, int flags,
+ asio::error_code& ec)
+{
+ clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ // Send the data.
+ DWORD send_buf_count = static_cast<DWORD>(count);
+ DWORD bytes_transferred = 0;
+ DWORD send_flags = flags;
+ int result = error_wrapper(::WSASend(s, const_cast<buf*>(bufs),
+ send_buf_count, &bytes_transferred, send_flags, 0, 0), ec);
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ ec = asio::error::connection_reset;
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ ec = asio::error::connection_refused;
+ if (result != 0)
+ return socket_error_retval;
+ ec = asio::error_code();
+ return bytes_transferred;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ msghdr msg = msghdr();
+ msg.msg_iov = const_cast<buf*>(bufs);
+ msg.msg_iovlen = count;
+#if defined(__linux__)
+ flags |= MSG_NOSIGNAL;
+#endif // defined(__linux__)
+ int result = error_wrapper(::sendmsg(s, &msg, flags), ec);
+ if (result >= 0)
+ ec = asio::error_code();
+ return result;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+size_t sync_send(socket_type s, state_type state, const buf* bufs,
+ size_t count, int flags, bool all_empty, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // A request to write 0 bytes to a stream is a no-op.
+ if (all_empty && (state & stream_oriented))
+ {
+ ec = asio::error_code();
+ return 0;
+ }
+
+ // Read some data.
+ for (;;)
+ {
+ // Try to complete the operation without blocking.
+ int bytes = socket_ops::send(s, bufs, count, flags, 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 socket to become ready.
+ if (socket_ops::poll_write(s, ec) < 0)
+ return 0;
+ }
+}
+
+#if defined(ASIO_HAS_IOCP)
+
+void complete_iocp_send(
+ const weak_cancel_token_type& cancel_token,
+ asio::error_code& ec)
+{
+ // Map non-portable errors to their portable counterparts.
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ {
+ if (cancel_token.expired())
+ ec = asio::error::operation_aborted;
+ else
+ ec = asio::error::connection_reset;
+ }
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = asio::error::connection_refused;
+ }
+}
+
+#else // defined(ASIO_HAS_IOCP)
+
+bool non_blocking_send(socket_type s,
+ const buf* bufs, size_t count, int flags,
+ asio::error_code& ec, size_t& bytes_transferred)
+{
+ for (;;)
+ {
+ // Write some data.
+ int bytes = socket_ops::send(s, bufs, count, flags, 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;
+ }
+}
+
+#endif // defined(ASIO_HAS_IOCP)
+
+int sendto(socket_type s, const buf* bufs, size_t count, int flags,
+ const socket_addr_type* addr, std::size_t addrlen,
+ asio::error_code& ec)
+{
+ clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ // Send the data.
+ DWORD send_buf_count = static_cast<DWORD>(count);
+ DWORD bytes_transferred = 0;
+ int result = error_wrapper(::WSASendTo(s, const_cast<buf*>(bufs),
+ send_buf_count, &bytes_transferred, flags, addr,
+ static_cast<int>(addrlen), 0, 0), ec);
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ ec = asio::error::connection_reset;
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ ec = asio::error::connection_refused;
+ if (result != 0)
+ return socket_error_retval;
+ ec = asio::error_code();
+ return bytes_transferred;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ msghdr msg = msghdr();
+ init_msghdr_msg_name(msg.msg_name, addr);
+ msg.msg_namelen = addrlen;
+ msg.msg_iov = const_cast<buf*>(bufs);
+ msg.msg_iovlen = count;
+#if defined(__linux__)
+ flags |= MSG_NOSIGNAL;
+#endif // defined(__linux__)
+ int result = error_wrapper(::sendmsg(s, &msg, flags), ec);
+ if (result >= 0)
+ ec = asio::error_code();
+ return result;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+size_t sync_sendto(socket_type s, state_type state, const buf* bufs,
+ size_t count, int flags, const socket_addr_type* addr,
+ std::size_t addrlen, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Write some data.
+ for (;;)
+ {
+ // Try to complete the operation without blocking.
+ int bytes = socket_ops::sendto(s, bufs, count, flags, addr, addrlen, 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 socket to become ready.
+ if (socket_ops::poll_write(s, ec) < 0)
+ return 0;
+ }
+}
+
+#if !defined(ASIO_HAS_IOCP)
+
+bool non_blocking_sendto(socket_type s,
+ const buf* bufs, size_t count, int flags,
+ const socket_addr_type* addr, std::size_t addrlen,
+ asio::error_code& ec, size_t& bytes_transferred)
+{
+ for (;;)
+ {
+ // Write some data.
+ int bytes = socket_ops::sendto(s, bufs, count, flags, addr, addrlen, 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;
+ }
+}
+
+#endif // !defined(ASIO_HAS_IOCP)
+
+socket_type socket(int af, int type, int protocol,
+ asio::error_code& ec)
+{
+ clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ socket_type s = error_wrapper(::WSASocket(af, type, protocol, 0, 0,
+ WSA_FLAG_OVERLAPPED), ec);
+ if (s == invalid_socket)
+ return s;
+
+ if (af == AF_INET6)
+ {
+ // Try to enable the POSIX default behaviour of having IPV6_V6ONLY set to
+ // false. This will only succeed on Windows Vista and later versions of
+ // Windows, where a dual-stack IPv4/v6 implementation is available.
+ DWORD optval = 0;
+ ::setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
+ reinterpret_cast<const char*>(&optval), sizeof(optval));
+ }
+
+ ec = asio::error_code();
+
+ return s;
+#elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
+ socket_type s = error_wrapper(::socket(af, type, protocol), ec);
+ if (s == invalid_socket)
+ return s;
+
+ int optval = 1;
+ int result = error_wrapper(::setsockopt(s,
+ SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec);
+ if (result != 0)
+ {
+ ::close(s);
+ return invalid_socket;
+ }
+
+ return s;
+#else
+ int s = error_wrapper(::socket(af, type, protocol), ec);
+ if (s >= 0)
+ ec = asio::error_code();
+ return s;
+#endif
+}
+
+template <typename SockLenType>
+inline int call_setsockopt(SockLenType msghdr::*,
+ socket_type s, int level, int optname,
+ const void* optval, std::size_t optlen)
+{
+ return ::setsockopt(s, level, optname,
+ (const char*)optval, (SockLenType)optlen);
+}
+
+int setsockopt(socket_type s, state_type& state, int level, int optname,
+ const void* optval, std::size_t optlen, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return socket_error_retval;
+ }
+
+ if (level == custom_socket_option_level && optname == always_fail_option)
+ {
+ ec = asio::error::invalid_argument;
+ return socket_error_retval;
+ }
+
+ if (level == custom_socket_option_level
+ && optname == enable_connection_aborted_option)
+ {
+ if (optlen != sizeof(int))
+ {
+ ec = asio::error::invalid_argument;
+ return socket_error_retval;
+ }
+
+ if (*static_cast<const int*>(optval))
+ state |= enable_connection_aborted;
+ else
+ state &= ~enable_connection_aborted;
+ ec = asio::error_code();
+ return 0;
+ }
+
+ if (level == SOL_SOCKET && optname == SO_LINGER)
+ state |= user_set_linger;
+
+#if defined(__BORLANDC__)
+ // Mysteriously, using the getsockopt and setsockopt functions directly with
+ // Borland C++ results in incorrect values being set and read. The bug can be
+ // worked around by using function addresses resolved with GetProcAddress.
+ if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
+ {
+ typedef int (WSAAPI *sso_t)(SOCKET, int, int, const char*, int);
+ if (sso_t sso = (sso_t)::GetProcAddress(winsock_module, "setsockopt"))
+ {
+ clear_last_error();
+ return error_wrapper(sso(s, level, optname,
+ reinterpret_cast<const char*>(optval),
+ static_cast<int>(optlen)), ec);
+ }
+ }
+ ec = asio::error::fault;
+ return socket_error_retval;
+#else // defined(__BORLANDC__)
+ clear_last_error();
+ int result = error_wrapper(call_setsockopt(&msghdr::msg_namelen,
+ s, level, optname, optval, optlen), ec);
+ if (result == 0)
+ {
+ ec = asio::error_code();
+
+#if defined(__MACH__) && defined(__APPLE__) \
+ || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+ // To implement portable behaviour for SO_REUSEADDR with UDP sockets we
+ // need to also set SO_REUSEPORT on BSD-based platforms.
+ if ((state & datagram_oriented)
+ && level == SOL_SOCKET && optname == SO_REUSEADDR)
+ {
+ call_setsockopt(&msghdr::msg_namelen, s,
+ SOL_SOCKET, SO_REUSEPORT, optval, optlen);
+ }
+#endif
+ }
+
+ return result;
+#endif // defined(__BORLANDC__)
+}
+
+template <typename SockLenType>
+inline int call_getsockopt(SockLenType msghdr::*,
+ socket_type s, int level, int optname,
+ void* optval, std::size_t* optlen)
+{
+ SockLenType tmp_optlen = (SockLenType)*optlen;
+ int result = ::getsockopt(s, level, optname, (char*)optval, &tmp_optlen);
+ *optlen = (std::size_t)tmp_optlen;
+ return result;
+}
+
+int getsockopt(socket_type s, state_type state, int level, int optname,
+ void* optval, size_t* optlen, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return socket_error_retval;
+ }
+
+ if (level == custom_socket_option_level && optname == always_fail_option)
+ {
+ ec = asio::error::invalid_argument;
+ return socket_error_retval;
+ }
+
+ if (level == custom_socket_option_level
+ && optname == enable_connection_aborted_option)
+ {
+ if (*optlen != sizeof(int))
+ {
+ ec = asio::error::invalid_argument;
+ return socket_error_retval;
+ }
+
+ *static_cast<int*>(optval) = (state & enable_connection_aborted) ? 1 : 0;
+ ec = asio::error_code();
+ return 0;
+ }
+
+#if defined(__BORLANDC__)
+ // Mysteriously, using the getsockopt and setsockopt functions directly with
+ // Borland C++ results in incorrect values being set and read. The bug can be
+ // worked around by using function addresses resolved with GetProcAddress.
+ if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
+ {
+ typedef int (WSAAPI *gso_t)(SOCKET, int, int, char*, int*);
+ if (gso_t gso = (gso_t)::GetProcAddress(winsock_module, "getsockopt"))
+ {
+ clear_last_error();
+ int tmp_optlen = static_cast<int>(*optlen);
+ int result = error_wrapper(gso(s, level, optname,
+ reinterpret_cast<char*>(optval), &tmp_optlen), ec);
+ *optlen = static_cast<size_t>(tmp_optlen);
+ if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
+ && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
+ {
+ // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are
+ // only supported on Windows Vista and later. To simplify program logic
+ // we will fake success of getting this option and specify that the
+ // value is non-zero (i.e. true). This corresponds to the behavior of
+ // IPv6 sockets on Windows platforms pre-Vista.
+ *static_cast<DWORD*>(optval) = 1;
+ ec = asio::error_code();
+ }
+ return result;
+ }
+ }
+ ec = asio::error::fault;
+ return socket_error_retval;
+#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ clear_last_error();
+ int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
+ s, level, optname, optval, optlen), ec);
+ if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
+ && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
+ {
+ // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are only
+ // supported on Windows Vista and later. To simplify program logic we will
+ // fake success of getting this option and specify that the value is
+ // non-zero (i.e. true). This corresponds to the behavior of IPv6 sockets
+ // on Windows platforms pre-Vista.
+ *static_cast<DWORD*>(optval) = 1;
+ ec = asio::error_code();
+ }
+ if (result == 0)
+ ec = asio::error_code();
+ return result;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ clear_last_error();
+ int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
+ s, level, optname, optval, optlen), ec);
+#if defined(__linux__)
+ if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int)
+ && (optname == SO_SNDBUF || optname == SO_RCVBUF))
+ {
+ // On Linux, setting SO_SNDBUF or SO_RCVBUF to N actually causes the kernel
+ // to set the buffer size to N*2. Linux puts additional stuff into the
+ // buffers so that only about half is actually available to the application.
+ // The retrieved value is divided by 2 here to make it appear as though the
+ // correct value has been set.
+ *static_cast<int*>(optval) /= 2;
+ }
+#endif // defined(__linux__)
+ if (result == 0)
+ ec = asio::error_code();
+ return result;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+template <typename SockLenType>
+inline int call_getpeername(SockLenType msghdr::*,
+ socket_type s, socket_addr_type* addr, std::size_t* addrlen)
+{
+ SockLenType tmp_addrlen = (SockLenType)*addrlen;
+ int result = ::getpeername(s, addr, &tmp_addrlen);
+ *addrlen = (std::size_t)tmp_addrlen;
+ return result;
+}
+
+int getpeername(socket_type s, socket_addr_type* addr,
+ std::size_t* addrlen, bool cached, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return socket_error_retval;
+ }
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ if (cached)
+ {
+ // Check if socket is still connected.
+ DWORD connect_time = 0;
+ size_t connect_time_len = sizeof(connect_time);
+ if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_CONNECT_TIME,
+ &connect_time, &connect_time_len, ec) == socket_error_retval)
+ {
+ return socket_error_retval;
+ }
+ if (connect_time == 0xFFFFFFFF)
+ {
+ ec = asio::error::not_connected;
+ return socket_error_retval;
+ }
+
+ // The cached value is still valid.
+ ec = asio::error_code();
+ return 0;
+ }
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ (void)cached;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+ clear_last_error();
+ int result = error_wrapper(call_getpeername(
+ &msghdr::msg_namelen, s, addr, addrlen), ec);
+ if (result == 0)
+ ec = asio::error_code();
+ return result;
+}
+
+template <typename SockLenType>
+inline int call_getsockname(SockLenType msghdr::*,
+ socket_type s, socket_addr_type* addr, std::size_t* addrlen)
+{
+ SockLenType tmp_addrlen = (SockLenType)*addrlen;
+ int result = ::getsockname(s, addr, &tmp_addrlen);
+ *addrlen = (std::size_t)tmp_addrlen;
+ return result;
+}
+
+int getsockname(socket_type s, socket_addr_type* addr,
+ std::size_t* addrlen, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return socket_error_retval;
+ }
+
+ clear_last_error();
+ int result = error_wrapper(call_getsockname(
+ &msghdr::msg_namelen, s, addr, addrlen), ec);
+ if (result == 0)
+ ec = asio::error_code();
+ return result;
+}
+
+int ioctl(socket_type s, state_type& state, int cmd,
+ ioctl_arg_type* arg, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return socket_error_retval;
+ }
+
+ clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ int result = error_wrapper(::ioctlsocket(s, cmd, arg), ec);
+#elif defined(__MACH__) && defined(__APPLE__) \
+ || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+ int result = error_wrapper(::ioctl(s,
+ static_cast<unsigned int>(cmd), arg), ec);
+#else
+ int result = error_wrapper(::ioctl(s, cmd, arg), ec);
+#endif
+ 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 socket is already in
+ // the correct state. This ensures that the underlying socket 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<int>(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;
+}
+
+int select(int nfds, fd_set* readfds, fd_set* writefds,
+ fd_set* exceptfds, timeval* timeout, asio::error_code& ec)
+{
+ clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ if (!readfds && !writefds && !exceptfds && timeout)
+ {
+ DWORD milliseconds = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
+ if (milliseconds == 0)
+ milliseconds = 1; // Force context switch.
+ ::Sleep(milliseconds);
+ ec = asio::error_code();
+ return 0;
+ }
+
+ // The select() call allows timeout values measured in microseconds, but the
+ // system clock (as wrapped by boost::posix_time::microsec_clock) typically
+ // has a resolution of 10 milliseconds. This can lead to a spinning select
+ // reactor, meaning increased CPU usage, when waiting for the earliest
+ // scheduled timeout if it's less than 10 milliseconds away. To avoid a tight
+ // spin we'll use a minimum timeout of 1 millisecond.
+ if (timeout && timeout->tv_sec == 0
+ && timeout->tv_usec > 0 && timeout->tv_usec < 1000)
+ timeout->tv_usec = 1000;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#if defined(__hpux) && defined(__SELECT)
+ timespec ts;
+ ts.tv_sec = timeout ? timeout->tv_sec : 0;
+ ts.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0;
+ return error_wrapper(::pselect(nfds, readfds,
+ writefds, exceptfds, timeout ? &ts : 0, 0), ec);
+#else
+ int result = error_wrapper(::select(nfds, readfds,
+ writefds, exceptfds, timeout), ec);
+ if (result >= 0)
+ ec = asio::error_code();
+ return result;
+#endif
+}
+
+int poll_read(socket_type s, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return socket_error_retval;
+ }
+
+#if defined(BOOST_WINDOWS) \
+ || defined(__CYGWIN__) \
+ || defined(__SYMBIAN32__)
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(s, &fds);
+ clear_last_error();
+ int result = error_wrapper(::select(s, &fds, 0, 0, 0), ec);
+ if (result >= 0)
+ ec = asio::error_code();
+ return result;
+#else // defined(BOOST_WINDOWS)
+ // || defined(__CYGWIN__)
+ // || defined(__SYMBIAN32__)
+ pollfd fds;
+ fds.fd = s;
+ fds.events = POLLIN;
+ fds.revents = 0;
+ clear_last_error();
+ int result = error_wrapper(::poll(&fds, 1, -1), ec);
+ if (result >= 0)
+ ec = asio::error_code();
+ return result;
+#endif // defined(BOOST_WINDOWS)
+ // || defined(__CYGWIN__)
+ // || defined(__SYMBIAN32__)
+}
+
+int poll_write(socket_type s, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return socket_error_retval;
+ }
+
+#if defined(BOOST_WINDOWS) \
+ || defined(__CYGWIN__) \
+ || defined(__SYMBIAN32__)
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(s, &fds);
+ clear_last_error();
+ int result = error_wrapper(::select(s, 0, &fds, 0, 0), ec);
+ if (result >= 0)
+ ec = asio::error_code();
+ return result;
+#else // defined(BOOST_WINDOWS)
+ // || defined(__CYGWIN__)
+ // || defined(__SYMBIAN32__)
+ pollfd fds;
+ fds.fd = s;
+ fds.events = POLLOUT;
+ fds.revents = 0;
+ clear_last_error();
+ int result = error_wrapper(::poll(&fds, 1, -1), ec);
+ if (result >= 0)
+ ec = asio::error_code();
+ return result;
+#endif // defined(BOOST_WINDOWS)
+ // || defined(__CYGWIN__)
+ // || defined(__SYMBIAN32__)
+}
+
+int poll_connect(socket_type s, asio::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = asio::error::bad_descriptor;
+ return socket_error_retval;
+ }
+
+#if defined(BOOST_WINDOWS) \
+ || defined(__CYGWIN__) \
+ || defined(__SYMBIAN32__)
+ fd_set write_fds;
+ FD_ZERO(&write_fds);
+ FD_SET(s, &write_fds);
+ fd_set except_fds;
+ FD_ZERO(&except_fds);
+ FD_SET(s, &except_fds);
+ clear_last_error();
+ int result = error_wrapper(::select(s, 0, &write_fds, &except_fds, 0), ec);
+ if (result >= 0)
+ ec = asio::error_code();
+ return result;
+#else // defined(BOOST_WINDOWS)
+ // || defined(__CYGWIN__)
+ // || defined(__SYMBIAN32__)
+ pollfd fds;
+ fds.fd = s;
+ fds.events = POLLOUT;
+ fds.revents = 0;
+ clear_last_error();
+ int result = error_wrapper(::poll(&fds, 1, -1), ec);
+ if (result >= 0)
+ ec = asio::error_code();
+ return result;
+#endif // defined(BOOST_WINDOWS)
+ // || defined(__CYGWIN__)
+ // || defined(__SYMBIAN32__)
+}
+
+const char* inet_ntop(int af, const void* src, char* dest, size_t length,
+ unsigned long scope_id, asio::error_code& ec)
+{
+ clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ using namespace std; // For memcpy.
+
+ if (af != AF_INET && af != AF_INET6)
+ {
+ ec = asio::error::address_family_not_supported;
+ return 0;
+ }
+
+ union
+ {
+ socket_addr_type base;
+ sockaddr_storage_type storage;
+ sockaddr_in4_type v4;
+ sockaddr_in6_type v6;
+ } address;
+ DWORD address_length;
+ if (af == AF_INET)
+ {
+ address_length = sizeof(sockaddr_in4_type);
+ address.v4.sin_family = AF_INET;
+ address.v4.sin_port = 0;
+ memcpy(&address.v4.sin_addr, src, sizeof(in4_addr_type));
+ }
+ else // AF_INET6
+ {
+ address_length = sizeof(sockaddr_in6_type);
+ address.v6.sin6_family = AF_INET6;
+ address.v6.sin6_port = 0;
+ address.v6.sin6_flowinfo = 0;
+ address.v6.sin6_scope_id = scope_id;
+ memcpy(&address.v6.sin6_addr, src, sizeof(in6_addr_type));
+ }
+
+ DWORD string_length = static_cast<DWORD>(length);
+#if defined(BOOST_NO_ANSI_APIS)
+ LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR));
+ int result = error_wrapper(::WSAAddressToStringW(&address.base,
+ address_length, 0, string_buffer, &string_length), ec);
+ ::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1, dest, length, 0, 0);
+#else
+ int result = error_wrapper(::WSAAddressToStringA(
+ &address.base, address_length, 0, dest, &string_length), ec);
+#endif
+
+ // Windows may set error code on success.
+ if (result != socket_error_retval)
+ ec = asio::error_code();
+
+ // Windows may not set an error code on failure.
+ else if (result == socket_error_retval && !ec)
+ ec = asio::error::invalid_argument;
+
+ return result == socket_error_retval ? 0 : dest;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ const char* result = error_wrapper(::inet_ntop(af, src, dest, length), ec);
+ if (result == 0 && !ec)
+ ec = asio::error::invalid_argument;
+ if (result != 0 && af == AF_INET6 && scope_id != 0)
+ {
+ using namespace std; // For strcat and sprintf.
+ char if_name[IF_NAMESIZE + 1] = "%";
+ const in6_addr_type* ipv6_address = static_cast<const in6_addr_type*>(src);
+ bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address);
+ if (!is_link_local || if_indextoname(scope_id, if_name + 1) == 0)
+ sprintf(if_name + 1, "%lu", scope_id);
+ strcat(dest, if_name);
+ }
+ return result;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+int inet_pton(int af, const char* src, void* dest,
+ unsigned long* scope_id, asio::error_code& ec)
+{
+ clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ using namespace std; // For memcpy and strcmp.
+
+ if (af != AF_INET && af != AF_INET6)
+ {
+ ec = asio::error::address_family_not_supported;
+ return -1;
+ }
+
+ union
+ {
+ socket_addr_type base;
+ sockaddr_storage_type storage;
+ sockaddr_in4_type v4;
+ sockaddr_in6_type v6;
+ } address;
+ int address_length = sizeof(sockaddr_storage_type);
+#if defined(BOOST_NO_ANSI_APIS)
+ int num_wide_chars = strlen(src) + 1;
+ LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR));
+ ::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars);
+ int result = error_wrapper(::WSAStringToAddressW(
+ wide_buffer, af, 0, &address.base, &address_length), ec);
+#else
+ int result = error_wrapper(::WSAStringToAddressA(
+ const_cast<char*>(src), af, 0, &address.base, &address_length), ec);
+#endif
+
+ if (af == AF_INET)
+ {
+ if (result != socket_error_retval)
+ {
+ memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type));
+ ec = asio::error_code();
+ }
+ else if (strcmp(src, "255.255.255.255") == 0)
+ {
+ static_cast<in4_addr_type*>(dest)->s_addr = INADDR_NONE;
+ ec = asio::error_code();
+ }
+ }
+ else // AF_INET6
+ {
+ if (result != socket_error_retval)
+ {
+ memcpy(dest, &address.v6.sin6_addr, sizeof(in6_addr_type));
+ if (scope_id)
+ *scope_id = address.v6.sin6_scope_id;
+ ec = asio::error_code();
+ }
+ }
+
+ // Windows may not set an error code on failure.
+ if (result == socket_error_retval && !ec)
+ ec = asio::error::invalid_argument;
+
+ if (result != socket_error_retval)
+ ec = asio::error_code();
+
+ return result == socket_error_retval ? -1 : 1;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ int result = error_wrapper(::inet_pton(af, src, dest), ec);
+ if (result <= 0 && !ec)
+ ec = asio::error::invalid_argument;
+ if (result > 0 && af == AF_INET6 && scope_id)
+ {
+ using namespace std; // For strchr and atoi.
+ *scope_id = 0;
+ if (const char* if_name = strchr(src, '%'))
+ {
+ in6_addr_type* ipv6_address = static_cast<in6_addr_type*>(dest);
+ bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address);
+ if (is_link_local)
+ *scope_id = if_nametoindex(if_name + 1);
+ if (*scope_id == 0)
+ *scope_id = atoi(if_name + 1);
+ }
+ }
+ return result;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+int gethostname(char* name, int namelen, asio::error_code& ec)
+{
+ clear_last_error();
+ int result = error_wrapper(::gethostname(name, namelen), ec);
+#if defined(BOOST_WINDOWS)
+ if (result == 0)
+ ec = asio::error_code();
+#endif
+ return result;
+}
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) \
+ || defined(__MACH__) && defined(__APPLE__)
+
+// The following functions are only needed for emulation of getaddrinfo and
+// getnameinfo.
+
+inline asio::error_code translate_netdb_error(int error)
+{
+ switch (error)
+ {
+ case 0:
+ return asio::error_code();
+ case HOST_NOT_FOUND:
+ return asio::error::host_not_found;
+ case TRY_AGAIN:
+ return asio::error::host_not_found_try_again;
+ case NO_RECOVERY:
+ return asio::error::no_recovery;
+ case NO_DATA:
+ return asio::error::no_data;
+ default:
+ BOOST_ASSERT(false);
+ return asio::error::invalid_argument;
+ }
+}
+
+inline hostent* gethostbyaddr(const char* addr, int length, int af,
+ hostent* result, char* buffer, int buflength, asio::error_code& ec)
+{
+ clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ (void)(buffer);
+ (void)(buflength);
+ hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec);
+ if (!retval)
+ return 0;
+ ec = asio::error_code();
+ *result = *retval;
+ return retval;
+#elif defined(__sun) || defined(__QNX__)
+ int error = 0;
+ hostent* retval = error_wrapper(::gethostbyaddr_r(addr, length, af, result,
+ buffer, buflength, &error), ec);
+ if (error)
+ ec = translate_netdb_error(error);
+ return retval;
+#elif defined(__MACH__) && defined(__APPLE__)
+ (void)(buffer);
+ (void)(buflength);
+ int error = 0;
+ hostent* retval = error_wrapper(::getipnodebyaddr(
+ addr, length, af, &error), ec);
+ if (error)
+ ec = translate_netdb_error(error);
+ if (!retval)
+ return 0;
+ *result = *retval;
+ return retval;
+#else
+ hostent* retval = 0;
+ int error = 0;
+ error_wrapper(::gethostbyaddr_r(addr, length, af, result, buffer,
+ buflength, &retval, &error), ec);
+ if (error)
+ ec = translate_netdb_error(error);
+ return retval;
+#endif
+}
+
+inline hostent* gethostbyname(const char* name, int af, struct hostent* result,
+ char* buffer, int buflength, int ai_flags, asio::error_code& ec)
+{
+ clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ (void)(buffer);
+ (void)(buflength);
+ (void)(ai_flags);
+ if (af != AF_INET)
+ {
+ ec = asio::error::address_family_not_supported;
+ return 0;
+ }
+ hostent* retval = error_wrapper(::gethostbyname(name), ec);
+ if (!retval)
+ return 0;
+ ec = asio::error_code();
+ *result = *retval;
+ return result;
+#elif defined(__sun) || defined(__QNX__)
+ (void)(ai_flags);
+ if (af != AF_INET)
+ {
+ ec = asio::error::address_family_not_supported;
+ return 0;
+ }
+ int error = 0;
+ hostent* retval = error_wrapper(::gethostbyname_r(name, result, buffer,
+ buflength, &error), ec);
+ if (error)
+ ec = translate_netdb_error(error);
+ return retval;
+#elif defined(__MACH__) && defined(__APPLE__)
+ (void)(buffer);
+ (void)(buflength);
+ int error = 0;
+ hostent* retval = error_wrapper(::getipnodebyname(
+ name, af, ai_flags, &error), ec);
+ if (error)
+ ec = translate_netdb_error(error);
+ if (!retval)
+ return 0;
+ *result = *retval;
+ return retval;
+#else
+ (void)(ai_flags);
+ if (af != AF_INET)
+ {
+ ec = asio::error::address_family_not_supported;
+ return 0;
+ }
+ hostent* retval = 0;
+ int error = 0;
+ error_wrapper(::gethostbyname_r(name, result,
+ buffer, buflength, &retval, &error), ec);
+ if (error)
+ ec = translate_netdb_error(error);
+ return retval;
+#endif
+}
+
+inline void freehostent(hostent* h)
+{
+#if defined(__MACH__) && defined(__APPLE__)
+ if (h)
+ ::freehostent(h);
+#else
+ (void)(h);
+#endif
+}
+
+// Emulation of getaddrinfo based on implementation in:
+// Stevens, W. R., UNIX Network Programming Vol. 1, 2nd Ed., Prentice-Hall 1998.
+
+struct gai_search
+{
+ const char* host;
+ int family;
+};
+
+inline int gai_nsearch(const char* host,
+ const addrinfo_type* hints, gai_search (&search)[2])
+{
+ int search_count = 0;
+ if (host == 0 || host[0] == '\0')
+ {
+ if (hints->ai_flags & AI_PASSIVE)
+ {
+ // No host and AI_PASSIVE implies wildcard bind.
+ switch (hints->ai_family)
+ {
+ case AF_INET:
+ search[search_count].host = "0.0.0.0";
+ search[search_count].family = AF_INET;
+ ++search_count;
+ break;
+ case AF_INET6:
+ search[search_count].host = "0::0";
+ search[search_count].family = AF_INET6;
+ ++search_count;
+ break;
+ case AF_UNSPEC:
+ search[search_count].host = "0::0";
+ search[search_count].family = AF_INET6;
+ ++search_count;
+ search[search_count].host = "0.0.0.0";
+ search[search_count].family = AF_INET;
+ ++search_count;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // No host and not AI_PASSIVE means connect to local host.
+ switch (hints->ai_family)
+ {
+ case AF_INET:
+ search[search_count].host = "localhost";
+ search[search_count].family = AF_INET;
+ ++search_count;
+ break;
+ case AF_INET6:
+ search[search_count].host = "localhost";
+ search[search_count].family = AF_INET6;
+ ++search_count;
+ break;
+ case AF_UNSPEC:
+ search[search_count].host = "localhost";
+ search[search_count].family = AF_INET6;
+ ++search_count;
+ search[search_count].host = "localhost";
+ search[search_count].family = AF_INET;
+ ++search_count;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else
+ {
+ // Host is specified.
+ switch (hints->ai_family)
+ {
+ case AF_INET:
+ search[search_count].host = host;
+ search[search_count].family = AF_INET;
+ ++search_count;
+ break;
+ case AF_INET6:
+ search[search_count].host = host;
+ search[search_count].family = AF_INET6;
+ ++search_count;
+ break;
+ case AF_UNSPEC:
+ search[search_count].host = host;
+ search[search_count].family = AF_INET6;
+ ++search_count;
+ search[search_count].host = host;
+ search[search_count].family = AF_INET;
+ ++search_count;
+ break;
+ default:
+ break;
+ }
+ }
+ return search_count;
+}
+
+template <typename T>
+inline T* gai_alloc(std::size_t size = sizeof(T))
+{
+ using namespace std;
+ T* p = static_cast<T*>(::operator new(size, std::nothrow));
+ if (p)
+ memset(p, 0, size);
+ return p;
+}
+
+inline void gai_free(void* p)
+{
+ ::operator delete(p);
+}
+
+inline void gai_strcpy(char* target, const char* source, std::size_t max_size)
+{
+ using namespace std;
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
+ strcpy_s(target, max_size, source);
+#else
+ *target = 0;
+ strncat(target, source, max_size);
+#endif
+}
+
+enum { gai_clone_flag = 1 << 30 };
+
+inline int gai_aistruct(addrinfo_type*** next, const addrinfo_type* hints,
+ const void* addr, int family)
+{
+ using namespace std;
+
+ addrinfo_type* ai = gai_alloc<addrinfo_type>();
+ if (ai == 0)
+ return EAI_MEMORY;
+
+ ai->ai_next = 0;
+ **next = ai;
+ *next = &ai->ai_next;
+
+ ai->ai_canonname = 0;
+ ai->ai_socktype = hints->ai_socktype;
+ if (ai->ai_socktype == 0)
+ ai->ai_flags |= gai_clone_flag;
+ ai->ai_protocol = hints->ai_protocol;
+ ai->ai_family = family;
+
+ switch (ai->ai_family)
+ {
+ case AF_INET:
+ {
+ sockaddr_in4_type* sinptr = gai_alloc<sockaddr_in4_type>();
+ if (sinptr == 0)
+ return EAI_MEMORY;
+ sinptr->sin_family = AF_INET;
+ memcpy(&sinptr->sin_addr, addr, sizeof(in4_addr_type));
+ ai->ai_addr = reinterpret_cast<sockaddr*>(sinptr);
+ ai->ai_addrlen = sizeof(sockaddr_in4_type);
+ break;
+ }
+ case AF_INET6:
+ {
+ sockaddr_in6_type* sin6ptr = gai_alloc<sockaddr_in6_type>();
+ if (sin6ptr == 0)
+ return EAI_MEMORY;
+ sin6ptr->sin6_family = AF_INET6;
+ memcpy(&sin6ptr->sin6_addr, addr, sizeof(in6_addr_type));
+ ai->ai_addr = reinterpret_cast<sockaddr*>(sin6ptr);
+ ai->ai_addrlen = sizeof(sockaddr_in6_type);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+inline addrinfo_type* gai_clone(addrinfo_type* ai)
+{
+ using namespace std;
+
+ addrinfo_type* new_ai = gai_alloc<addrinfo_type>();
+ if (new_ai == 0)
+ return new_ai;
+
+ new_ai->ai_next = ai->ai_next;
+ ai->ai_next = new_ai;
+
+ new_ai->ai_flags = 0;
+ new_ai->ai_family = ai->ai_family;
+ new_ai->ai_socktype = ai->ai_socktype;
+ new_ai->ai_protocol = ai->ai_protocol;
+ new_ai->ai_canonname = 0;
+ new_ai->ai_addrlen = ai->ai_addrlen;
+ new_ai->ai_addr = gai_alloc<sockaddr>(ai->ai_addrlen);
+ memcpy(new_ai->ai_addr, ai->ai_addr, ai->ai_addrlen);
+
+ return new_ai;
+}
+
+inline int gai_port(addrinfo_type* aihead, int port, int socktype)
+{
+ int num_found = 0;
+
+ for (addrinfo_type* ai = aihead; ai; ai = ai->ai_next)
+ {
+ if (ai->ai_flags & gai_clone_flag)
+ {
+ if (ai->ai_socktype != 0)
+ {
+ ai = gai_clone(ai);
+ if (ai == 0)
+ return -1;
+ // ai now points to newly cloned entry.
+ }
+ }
+ else if (ai->ai_socktype != socktype)
+ {
+ // Ignore if mismatch on socket type.
+ continue;
+ }
+
+ ai->ai_socktype = socktype;
+
+ switch (ai->ai_family)
+ {
+ case AF_INET:
+ {
+ sockaddr_in4_type* sinptr =
+ reinterpret_cast<sockaddr_in4_type*>(ai->ai_addr);
+ sinptr->sin_port = port;
+ ++num_found;
+ break;
+ }
+ case AF_INET6:
+ {
+ sockaddr_in6_type* sin6ptr =
+ reinterpret_cast<sockaddr_in6_type*>(ai->ai_addr);
+ sin6ptr->sin6_port = port;
+ ++num_found;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ return num_found;
+}
+
+inline int gai_serv(addrinfo_type* aihead,
+ const addrinfo_type* hints, const char* serv)
+{
+ using namespace std;
+
+ int num_found = 0;
+
+ if (
+#if defined(AI_NUMERICSERV)
+ (hints->ai_flags & AI_NUMERICSERV) ||
+#endif
+ isdigit(static_cast<unsigned char>(serv[0])))
+ {
+ int port = htons(atoi(serv));
+ if (hints->ai_socktype)
+ {
+ // Caller specifies socket type.
+ int rc = gai_port(aihead, port, hints->ai_socktype);
+ if (rc < 0)
+ return EAI_MEMORY;
+ num_found += rc;
+ }
+ else
+ {
+ // Caller does not specify socket type.
+ int rc = gai_port(aihead, port, SOCK_STREAM);
+ if (rc < 0)
+ return EAI_MEMORY;
+ num_found += rc;
+ rc = gai_port(aihead, port, SOCK_DGRAM);
+ if (rc < 0)
+ return EAI_MEMORY;
+ num_found += rc;
+ }
+ }
+ else
+ {
+ // Try service name with TCP first, then UDP.
+ if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_STREAM)
+ {
+ servent* sptr = getservbyname(serv, "tcp");
+ if (sptr != 0)
+ {
+ int rc = gai_port(aihead, sptr->s_port, SOCK_STREAM);
+ if (rc < 0)
+ return EAI_MEMORY;
+ num_found += rc;
+ }
+ }
+ if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_DGRAM)
+ {
+ servent* sptr = getservbyname(serv, "udp");
+ if (sptr != 0)
+ {
+ int rc = gai_port(aihead, sptr->s_port, SOCK_DGRAM);
+ if (rc < 0)
+ return EAI_MEMORY;
+ num_found += rc;
+ }
+ }
+ }
+
+ if (num_found == 0)
+ {
+ if (hints->ai_socktype == 0)
+ {
+ // All calls to getservbyname() failed.
+ return EAI_NONAME;
+ }
+ else
+ {
+ // Service not supported for socket type.
+ return EAI_SERVICE;
+ }
+ }
+
+ return 0;
+}
+
+inline int gai_echeck(const char* host, const char* service,
+ int flags, int family, int socktype, int protocol)
+{
+ (void)(flags);
+ (void)(protocol);
+
+ // Host or service must be specified.
+ if (host == 0 || host[0] == '\0')
+ if (service == 0 || service[0] == '\0')
+ return EAI_NONAME;
+
+ // Check combination of family and socket type.
+ switch (family)
+ {
+ case AF_UNSPEC:
+ break;
+ case AF_INET:
+ case AF_INET6:
+ if (service != 0 && service[0] != '\0')
+ if (socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM)
+ return EAI_SOCKTYPE;
+ break;
+ default:
+ return EAI_FAMILY;
+ }
+
+ return 0;
+}
+
+inline void freeaddrinfo_emulation(addrinfo_type* aihead)
+{
+ addrinfo_type* ai = aihead;
+ while (ai)
+ {
+ gai_free(ai->ai_addr);
+ gai_free(ai->ai_canonname);
+ addrinfo_type* ainext = ai->ai_next;
+ gai_free(ai);
+ ai = ainext;
+ }
+}
+
+inline int getaddrinfo_emulation(const char* host, const char* service,
+ const addrinfo_type* hintsp, addrinfo_type** result)
+{
+ // Set up linked list of addrinfo structures.
+ addrinfo_type* aihead = 0;
+ addrinfo_type** ainext = &aihead;
+ char* canon = 0;
+
+ // Supply default hints if not specified by caller.
+ addrinfo_type hints = addrinfo_type();
+ hints.ai_family = AF_UNSPEC;
+ if (hintsp)
+ hints = *hintsp;
+
+ // If the resolution is not specifically for AF_INET6, remove the AI_V4MAPPED
+ // and AI_ALL flags.
+#if defined(AI_V4MAPPED)
+ if (hints.ai_family != AF_INET6)
+ hints.ai_flags &= ~AI_V4MAPPED;
+#endif
+#if defined(AI_ALL)
+ if (hints.ai_family != AF_INET6)
+ hints.ai_flags &= ~AI_ALL;
+#endif
+
+ // Basic error checking.
+ int rc = gai_echeck(host, service, hints.ai_flags, hints.ai_family,
+ hints.ai_socktype, hints.ai_protocol);
+ if (rc != 0)
+ {
+ freeaddrinfo_emulation(aihead);
+ return rc;
+ }
+
+ gai_search search[2];
+ int search_count = gai_nsearch(host, &hints, search);
+ for (gai_search* sptr = search; sptr < search + search_count; ++sptr)
+ {
+ // Check for IPv4 dotted decimal string.
+ in4_addr_type inaddr;
+ asio::error_code ec;
+ if (socket_ops::inet_pton(AF_INET, sptr->host, &inaddr, 0, ec) == 1)
+ {
+ if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET)
+ {
+ freeaddrinfo_emulation(aihead);
+ gai_free(canon);
+ return EAI_FAMILY;
+ }
+ if (sptr->family == AF_INET)
+ {
+ rc = gai_aistruct(&ainext, &hints, &inaddr, AF_INET);
+ if (rc != 0)
+ {
+ freeaddrinfo_emulation(aihead);
+ gai_free(canon);
+ return rc;
+ }
+ }
+ continue;
+ }
+
+ // Check for IPv6 hex string.
+ in6_addr_type in6addr;
+ if (socket_ops::inet_pton(AF_INET6, sptr->host, &in6addr, 0, ec) == 1)
+ {
+ if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET6)
+ {
+ freeaddrinfo_emulation(aihead);
+ gai_free(canon);
+ return EAI_FAMILY;
+ }
+ if (sptr->family == AF_INET6)
+ {
+ rc = gai_aistruct(&ainext, &hints, &in6addr, AF_INET6);
+ if (rc != 0)
+ {
+ freeaddrinfo_emulation(aihead);
+ gai_free(canon);
+ return rc;
+ }
+ }
+ continue;
+ }
+
+ // Look up hostname.
+ hostent hent;
+ char hbuf[8192] = "";
+ hostent* hptr = socket_ops::gethostbyname(sptr->host,
+ sptr->family, &hent, hbuf, sizeof(hbuf), hints.ai_flags, ec);
+ if (hptr == 0)
+ {
+ if (search_count == 2)
+ {
+ // Failure is OK if there are multiple searches.
+ continue;
+ }
+ freeaddrinfo_emulation(aihead);
+ gai_free(canon);
+ if (ec == asio::error::host_not_found)
+ return EAI_NONAME;
+ if (ec == asio::error::host_not_found_try_again)
+ return EAI_AGAIN;
+ if (ec == asio::error::no_recovery)
+ return EAI_FAIL;
+ if (ec == asio::error::no_data)
+ return EAI_NONAME;
+ return EAI_NONAME;
+ }
+
+ // Check for address family mismatch if one was specified.
+ if (hints.ai_family != AF_UNSPEC && hints.ai_family != hptr->h_addrtype)
+ {
+ freeaddrinfo_emulation(aihead);
+ gai_free(canon);
+ socket_ops::freehostent(hptr);
+ return EAI_FAMILY;
+ }
+
+ // Save canonical name first time.
+ if (host != 0 && host[0] != '\0' && hptr->h_name && hptr->h_name[0]
+ && (hints.ai_flags & AI_CANONNAME) && canon == 0)
+ {
+ std::size_t canon_len = strlen(hptr->h_name) + 1;
+ canon = gai_alloc<char>(canon_len);
+ if (canon == 0)
+ {
+ freeaddrinfo_emulation(aihead);
+ socket_ops::freehostent(hptr);
+ return EAI_MEMORY;
+ }
+ gai_strcpy(canon, hptr->h_name, canon_len);
+ }
+
+ // Create an addrinfo structure for each returned address.
+ for (char** ap = hptr->h_addr_list; *ap; ++ap)
+ {
+ rc = gai_aistruct(&ainext, &hints, *ap, hptr->h_addrtype);
+ if (rc != 0)
+ {
+ freeaddrinfo_emulation(aihead);
+ gai_free(canon);
+ socket_ops::freehostent(hptr);
+ return EAI_FAMILY;
+ }
+ }
+
+ socket_ops::freehostent(hptr);
+ }
+
+ // Check if we found anything.
+ if (aihead == 0)
+ {
+ gai_free(canon);
+ return EAI_NONAME;
+ }
+
+ // Return canonical name in first entry.
+ if (host != 0 && host[0] != '\0' && (hints.ai_flags & AI_CANONNAME))
+ {
+ if (canon)
+ {
+ aihead->ai_canonname = canon;
+ canon = 0;
+ }
+ else
+ {
+ std::size_t canonname_len = strlen(search[0].host) + 1;
+ aihead->ai_canonname = gai_alloc<char>(canonname_len);
+ if (aihead->ai_canonname == 0)
+ {
+ freeaddrinfo_emulation(aihead);
+ return EAI_MEMORY;
+ }
+ gai_strcpy(aihead->ai_canonname, search[0].host, canonname_len);
+ }
+ }
+ gai_free(canon);
+
+ // Process the service name.
+ if (service != 0 && service[0] != '\0')
+ {
+ rc = gai_serv(aihead, &hints, service);
+ if (rc != 0)
+ {
+ freeaddrinfo_emulation(aihead);
+ return rc;
+ }
+ }
+
+ // Return result to caller.
+ *result = aihead;
+ return 0;
+}
+
+inline asio::error_code getnameinfo_emulation(
+ const socket_addr_type* sa, std::size_t salen, char* host,
+ std::size_t hostlen, char* serv, std::size_t servlen, int flags,
+ asio::error_code& ec)
+{
+ using namespace std;
+
+ const char* addr;
+ size_t addr_len;
+ unsigned short port;
+ switch (sa->sa_family)
+ {
+ case AF_INET:
+ if (salen != sizeof(sockaddr_in4_type))
+ {
+ return ec = asio::error::invalid_argument;
+ }
+ addr = reinterpret_cast<const char*>(
+ &reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_addr);
+ addr_len = sizeof(in4_addr_type);
+ port = reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_port;
+ break;
+ case AF_INET6:
+ if (salen != sizeof(sockaddr_in6_type))
+ {
+ return ec = asio::error::invalid_argument;
+ }
+ addr = reinterpret_cast<const char*>(
+ &reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_addr);
+ addr_len = sizeof(in6_addr_type);
+ port = reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_port;
+ break;
+ default:
+ return ec = asio::error::address_family_not_supported;
+ }
+
+ if (host && hostlen > 0)
+ {
+ if (flags & NI_NUMERICHOST)
+ {
+ if (socket_ops::inet_ntop(sa->sa_family, addr, host, hostlen, 0, ec) == 0)
+ {
+ return ec;
+ }
+ }
+ else
+ {
+ hostent hent;
+ char hbuf[8192] = "";
+ hostent* hptr = socket_ops::gethostbyaddr(addr,
+ static_cast<int>(addr_len), sa->sa_family,
+ &hent, hbuf, sizeof(hbuf), ec);
+ if (hptr && hptr->h_name && hptr->h_name[0] != '\0')
+ {
+ if (flags & NI_NOFQDN)
+ {
+ char* dot = strchr(hptr->h_name, '.');
+ if (dot)
+ {
+ *dot = 0;
+ }
+ }
+ gai_strcpy(host, hptr->h_name, hostlen);
+ socket_ops::freehostent(hptr);
+ }
+ else
+ {
+ socket_ops::freehostent(hptr);
+ if (flags & NI_NAMEREQD)
+ {
+ return ec = asio::error::host_not_found;
+ }
+ if (socket_ops::inet_ntop(sa->sa_family,
+ addr, host, hostlen, 0, ec) == 0)
+ {
+ return ec;
+ }
+ }
+ }
+ }
+
+ if (serv && servlen > 0)
+ {
+ if (flags & NI_NUMERICSERV)
+ {
+ if (servlen < 6)
+ {
+ return ec = asio::error::no_buffer_space;
+ }
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
+ sprintf_s(serv, servlen, "%u", ntohs(port));
+#else
+ sprintf(serv, "%u", ntohs(port));
+#endif
+ }
+ else
+ {
+#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) \
+ && !defined(ASIO_DISABLE_THREADS)
+ static ::pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+ ::pthread_mutex_lock(&mutex);
+#endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
+ // && !defined(ASIO_DISABLE_THREADS)
+ servent* sptr = ::getservbyport(port, (flags & NI_DGRAM) ? "udp" : 0);
+ if (sptr && sptr->s_name && sptr->s_name[0] != '\0')
+ {
+ gai_strcpy(serv, sptr->s_name, servlen);
+ }
+ else
+ {
+ if (servlen < 6)
+ {
+ return ec = asio::error::no_buffer_space;
+ }
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
+ sprintf_s(serv, servlen, "%u", ntohs(port));
+#else
+ sprintf(serv, "%u", ntohs(port));
+#endif
+ }
+#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS) \
+ && !defined(ASIO_DISABLE_THREADS)
+ ::pthread_mutex_unlock(&mutex);
+#endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
+ // && !defined(ASIO_DISABLE_THREADS)
+ }
+ }
+
+ ec = asio::error_code();
+ return ec;
+}
+
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ // || defined(__MACH__) && defined(__APPLE__)
+
+inline asio::error_code translate_addrinfo_error(int error)
+{
+ switch (error)
+ {
+ case 0:
+ return asio::error_code();
+ case EAI_AGAIN:
+ return asio::error::host_not_found_try_again;
+ case EAI_BADFLAGS:
+ return asio::error::invalid_argument;
+ case EAI_FAIL:
+ return asio::error::no_recovery;
+ case EAI_FAMILY:
+ return asio::error::address_family_not_supported;
+ case EAI_MEMORY:
+ return asio::error::no_memory;
+ case EAI_NONAME:
+#if defined(EAI_ADDRFAMILY)
+ case EAI_ADDRFAMILY:
+#endif
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+ case EAI_NODATA:
+#endif
+ return asio::error::host_not_found;
+ case EAI_SERVICE:
+ return asio::error::service_not_found;
+ case EAI_SOCKTYPE:
+ return asio::error::socket_type_not_supported;
+ default: // Possibly the non-portable EAI_SYSTEM.
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ return asio::error_code(
+ WSAGetLastError(), asio::error::get_system_category());
+#else
+ return asio::error_code(
+ errno, asio::error::get_system_category());
+#endif
+ }
+}
+
+asio::error_code getaddrinfo(const char* host,
+ const char* service, const addrinfo_type& hints,
+ addrinfo_type** result, asio::error_code& ec)
+{
+ host = (host && *host) ? host : 0;
+ service = (service && *service) ? service : 0;
+ clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
+ // Building for Windows XP, Windows Server 2003, or later.
+ int error = ::getaddrinfo(host, service, &hints, result);
+ return ec = translate_addrinfo_error(error);
+# else
+ // Building for Windows 2000 or earlier.
+ typedef int (WSAAPI *gai_t)(const char*,
+ const char*, const addrinfo_type*, addrinfo_type**);
+ if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
+ {
+ if (gai_t gai = (gai_t)::GetProcAddress(winsock_module, "getaddrinfo"))
+ {
+ int error = gai(host, service, &hints, result);
+ return ec = translate_addrinfo_error(error);
+ }
+ }
+ int error = getaddrinfo_emulation(host, service, &hints, result);
+ return ec = translate_addrinfo_error(error);
+# endif
+#elif defined(__MACH__) && defined(__APPLE__)
+ int error = getaddrinfo_emulation(host, service, &hints, result);
+ return ec = translate_addrinfo_error(error);
+#else
+ int error = ::getaddrinfo(host, service, &hints, result);
+ return ec = translate_addrinfo_error(error);
+#endif
+}
+
+asio::error_code background_getaddrinfo(
+ const weak_cancel_token_type& cancel_token, const char* host,
+ const char* service, const addrinfo_type& hints,
+ addrinfo_type** result, asio::error_code& ec)
+{
+ if (cancel_token.expired())
+ ec = asio::error::operation_aborted;
+ else
+ socket_ops::getaddrinfo(host, service, hints, result, ec);
+ return ec;
+}
+
+void freeaddrinfo(addrinfo_type* ai)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
+ // Building for Windows XP, Windows Server 2003, or later.
+ ::freeaddrinfo(ai);
+# else
+ // Building for Windows 2000 or earlier.
+ typedef int (WSAAPI *fai_t)(addrinfo_type*);
+ if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
+ {
+ if (fai_t fai = (fai_t)::GetProcAddress(winsock_module, "freeaddrinfo"))
+ {
+ fai(ai);
+ return;
+ }
+ }
+ freeaddrinfo_emulation(ai);
+# endif
+#elif defined(__MACH__) && defined(__APPLE__)
+ freeaddrinfo_emulation(ai);
+#else
+ ::freeaddrinfo(ai);
+#endif
+}
+
+asio::error_code getnameinfo(const socket_addr_type* addr,
+ std::size_t addrlen, char* host, std::size_t hostlen,
+ char* serv, std::size_t servlen, int flags, asio::error_code& ec)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
+ // Building for Windows XP, Windows Server 2003, or later.
+ clear_last_error();
+ int error = ::getnameinfo(addr, static_cast<socklen_t>(addrlen),
+ host, static_cast<DWORD>(hostlen),
+ serv, static_cast<DWORD>(servlen), flags);
+ return ec = translate_addrinfo_error(error);
+# else
+ // Building for Windows 2000 or earlier.
+ typedef int (WSAAPI *gni_t)(const socket_addr_type*,
+ int, char*, DWORD, char*, DWORD, int);
+ if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
+ {
+ if (gni_t gni = (gni_t)::GetProcAddress(winsock_module, "getnameinfo"))
+ {
+ clear_last_error();
+ int error = gni(addr, static_cast<int>(addrlen),
+ host, static_cast<DWORD>(hostlen),
+ serv, static_cast<DWORD>(servlen), flags);
+ return ec = translate_addrinfo_error(error);
+ }
+ }
+ clear_last_error();
+ return getnameinfo_emulation(addr, addrlen,
+ host, hostlen, serv, servlen, flags, ec);
+# endif
+#elif defined(__MACH__) && defined(__APPLE__)
+ using namespace std; // For memcpy.
+ sockaddr_storage_type tmp_addr;
+ memcpy(&tmp_addr, addr, addrlen);
+ tmp_addr.ss_len = addrlen;
+ addr = reinterpret_cast<socket_addr_type*>(&tmp_addr);
+ clear_last_error();
+ return getnameinfo_emulation(addr, addrlen,
+ host, hostlen, serv, servlen, flags, ec);
+#else
+ clear_last_error();
+ int error = ::getnameinfo(addr, addrlen, host, hostlen, serv, servlen, flags);
+ return ec = translate_addrinfo_error(error);
+#endif
+}
+
+asio::error_code sync_getnameinfo(
+ const socket_addr_type* addr, std::size_t addrlen,
+ char* host, std::size_t hostlen, char* serv,
+ std::size_t servlen, int sock_type, asio::error_code& ec)
+{
+ // First try resolving with the service name. If that fails try resolving
+ // but allow the service to be returned as a number.
+ int flags = (sock_type == SOCK_DGRAM) ? NI_DGRAM : 0;
+ socket_ops::getnameinfo(addr, addrlen, host,
+ hostlen, serv, servlen, flags, ec);
+ if (ec)
+ {
+ socket_ops::getnameinfo(addr, addrlen, host, hostlen,
+ serv, servlen, flags | NI_NUMERICSERV, ec);
+ }
+
+ return ec;
+}
+
+asio::error_code background_getnameinfo(
+ const weak_cancel_token_type& cancel_token,
+ const socket_addr_type* addr, std::size_t addrlen,
+ char* host, std::size_t hostlen, char* serv,
+ std::size_t servlen, int sock_type, asio::error_code& ec)
+{
+ if (cancel_token.expired())
+ {
+ ec = asio::error::operation_aborted;
+ }
+ else
+ {
+ // First try resolving with the service name. If that fails try resolving
+ // but allow the service to be returned as a number.
+ int flags = (sock_type == SOCK_DGRAM) ? NI_DGRAM : 0;
+ socket_ops::getnameinfo(addr, addrlen, host,
+ hostlen, serv, servlen, flags, ec);
+ if (ec)
+ {
+ socket_ops::getnameinfo(addr, addrlen, host, hostlen,
+ serv, servlen, flags | NI_NUMERICSERV, ec);
+ }
+ }
+
+ return ec;
+}
+
+u_long_type network_to_host_long(u_long_type value)
+{
+ return ntohl(value);
+}
+
+u_long_type host_to_network_long(u_long_type value)
+{
+ return htonl(value);
+}
+
+u_short_type network_to_host_short(u_short_type value)
+{
+ return ntohs(value);
+}
+
+u_short_type host_to_network_short(u_short_type value)
+{
+ return htons(value);
+}
+
+} // namespace socket_ops
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_SOCKET_OPS_IPP
diff --git a/ext/asio/asio/detail/impl/socket_select_interrupter.ipp b/ext/asio/asio/detail/impl/socket_select_interrupter.ipp
new file mode 100644
index 0000000000..181c543754
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/strand_service.hpp b/ext/asio/asio/detail/impl/strand_service.hpp
new file mode 100644
index 0000000000..81f438a988
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/strand_service.ipp b/ext/asio/asio/detail/impl/strand_service.ipp
new file mode 100644
index 0000000000..84b806a553
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/task_io_service.hpp b/ext/asio/asio/detail/impl/task_io_service.hpp
new file mode 100644
index 0000000000..20ffd61c06
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/task_io_service.ipp b/ext/asio/asio/detail/impl/task_io_service.ipp
new file mode 100644
index 0000000000..12a22be8cc
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/throw_error.ipp b/ext/asio/asio/detail/impl/throw_error.ipp
new file mode 100644
index 0000000000..913df7c619
--- /dev/null
+++ b/ext/asio/asio/detail/impl/throw_error.ipp
@@ -0,0 +1,45 @@
+//
+// 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 {
+
+void do_throw_error(const asio::error_code& err)
+{
+ asio::system_error e(err);
+ boost::throw_exception(e);
+}
+
+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
diff --git a/ext/asio/asio/detail/impl/timer_queue.ipp b/ext/asio/asio/detail/impl/timer_queue.ipp
new file mode 100644
index 0000000000..63fbd7e90a
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/timer_queue_set.ipp b/ext/asio/asio/detail/impl/timer_queue_set.ipp
new file mode 100644
index 0000000000..81ab5a9a3c
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/win_event.ipp b/ext/asio/asio/detail/impl/win_event.ipp
new file mode 100644
index 0000000000..2b72f6ecda
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/win_iocp_handle_service.ipp b/ext/asio/asio/detail/impl/win_iocp_handle_service.ipp
new file mode 100644
index 0000000000..3b30b1d5df
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/win_iocp_io_service.hpp b/ext/asio/asio/detail/impl/win_iocp_io_service.hpp
new file mode 100644
index 0000000000..ab235471e8
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/win_iocp_io_service.ipp b/ext/asio/asio/detail/impl/win_iocp_io_service.ipp
new file mode 100644
index 0000000000..890e32f534
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/win_iocp_serial_port_service.ipp b/ext/asio/asio/detail/impl/win_iocp_serial_port_service.ipp
new file mode 100644
index 0000000000..763151434c
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/win_iocp_socket_service_base.ipp b/ext/asio/asio/detail/impl/win_iocp_socket_service_base.ipp
new file mode 100644
index 0000000000..37c6f63379
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/win_mutex.ipp b/ext/asio/asio/detail/impl/win_mutex.ipp
new file mode 100644
index 0000000000..910cc23372
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/win_thread.ipp b/ext/asio/asio/detail/impl/win_thread.ipp
new file mode 100644
index 0000000000..65844c8866
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/win_tss_ptr.ipp b/ext/asio/asio/detail/impl/win_tss_ptr.ipp
new file mode 100644
index 0000000000..de3ea3c7e0
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/impl/winsock_init.ipp b/ext/asio/asio/detail/impl/winsock_init.ipp
new file mode 100644
index 0000000000..3b20c98e27
--- /dev/null
+++ b/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
diff --git a/ext/asio/asio/detail/io_control.hpp b/ext/asio/asio/detail/io_control.hpp
index df7171cbe2..b3ef844958 100644
--- a/ext/asio/asio/detail/io_control.hpp
+++ b/ext/asio/asio/detail/io_control.hpp
@@ -1,8 +1,8 @@
//
-// io_control.hpp
-// ~~~~~~~~~~~~~~
+// detail/io_control.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 <cstddef>
#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
#include "asio/detail/socket_types.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
namespace io_control {
diff --git a/ext/asio/asio/detail/kqueue_reactor.hpp b/ext/asio/asio/detail/kqueue_reactor.hpp
index bfa004d0da..07087ddd6e 100644
--- a/ext/asio/asio/detail/kqueue_reactor.hpp
+++ b/ext/asio/asio/detail/kqueue_reactor.hpp
@@ -1,8 +1,8 @@
//
-// kqueue_reactor.hpp
-// ~~~~~~~~~~~~~~~~~~
+// detail/kqueue_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)
// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -16,41 +16,35 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/kqueue_reactor_fwd.hpp"
+#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_KQUEUE)
-#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.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/kqueue_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"
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
// Older versions of Mac OS X may not define EV_OOBAND.
#if !defined(EV_OOBAND)
# define EV_OOBAND EV_FLAG1
#endif // !defined(EV_OOBAND)
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
@@ -64,384 +58,98 @@ public:
// Per-descriptor queues.
struct descriptor_state
{
- descriptor_state() {}
- descriptor_state(const descriptor_state&) {}
- void operator=(const descriptor_state&) {}
-
+ friend class kqueue_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.
- 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();
- }
+ ASIO_DECL kqueue_reactor(asio::io_service& io_service);
// Destructor.
- ~kqueue_reactor()
- {
- close(kqueue_fd_);
- }
+ ASIO_DECL ~kqueue_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;
+ ASIO_DECL int register_descriptor(socket_type descriptor,
+ per_descriptor_data& descriptor_data);
- descriptor_data->shutdown_ = false;
-
- 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;
-
- 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:
- EV_SET(&event, descriptor, EVFILT_READ,
- EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
- break;
- case write_op:
- 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.
- 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);
- }
- }
- }
+ 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 kqueue 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>& 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>& 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)
- 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 the kqueue loop.
- void 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 = 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.
- static const int filter[max_ops] =
- { 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())
- EV_SET(&event, descriptor, EVFILT_READ,
- EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
- else if (!descriptor_data->op_queue_[except_op].empty())
- 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())
- 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);
- }
+ ASIO_DECL void run(bool block, op_queue<operation>& ops);
// Interrupt the kqueue loop.
- void interrupt()
- {
- struct kevent event;
- EV_SET(&event, interrupter_.read_descriptor(),
- EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &interrupter_);
- ::kevent(kqueue_fd_, &event, 1, 0, 0, 0);
- }
+ ASIO_DECL void interrupt();
private:
// Create the kqueue file descriptor. Throws an exception if the descriptor
// cannot be created.
- static int do_kqueue_create()
- {
- int fd = kqueue();
- if (fd == -1)
- {
- boost::throw_exception(
- asio::system_error(
- asio::error_code(errno,
- asio::error::get_system_category()),
- "kqueue"));
- }
- return fd;
- }
+ ASIO_DECL static int do_kqueue_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 kevent call.
- timespec* 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;
- }
+ ASIO_DECL timespec* get_timeout(timespec& ts);
// The io_service implementation used to post completions.
io_service_impl& io_service_;
@@ -464,22 +172,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_KQUEUE)
-
#include "asio/detail/pop_options.hpp"
+#include "asio/detail/impl/kqueue_reactor.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/kqueue_reactor.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_KQUEUE)
+
#endif // ASIO_DETAIL_KQUEUE_REACTOR_HPP
diff --git a/ext/asio/asio/detail/kqueue_reactor_fwd.hpp b/ext/asio/asio/detail/kqueue_reactor_fwd.hpp
index abbc0c7d7b..fda59ce8ec 100644
--- a/ext/asio/asio/detail/kqueue_reactor_fwd.hpp
+++ b/ext/asio/asio/detail/kqueue_reactor_fwd.hpp
@@ -1,8 +1,8 @@
//
-// kqueue_reactor_fwd.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~
+// detail/kqueue_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)
// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -16,15 +16,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_KQUEUE)
-
-#if (defined(__MACH__) && defined(__APPLE__)) \
- || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
-
-// Define this to indicate that kqueue is supported on the target platform.
-#define ASIO_HAS_KQUEUE 1
+#if defined(ASIO_HAS_KQUEUE)
namespace asio {
namespace detail {
@@ -34,11 +28,6 @@ class kqueue_reactor;
} // namespace detail
} // namespace asio
-#endif // (defined(__MACH__) && defined(__APPLE__))
- // || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
-
-#endif // !defined(ASIO_DISABLE_KQUEUE)
-
-#include "asio/detail/pop_options.hpp"
+#endif // defined(ASIO_HAS_KQUEUE)
#endif // ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP
diff --git a/ext/asio/asio/detail/local_free_on_block_exit.hpp b/ext/asio/asio/detail/local_free_on_block_exit.hpp
index 554943c817..a55bd4b34d 100644
--- a/ext/asio/asio/detail/local_free_on_block_exit.hpp
+++ b/ext/asio/asio/detail/local_free_on_block_exit.hpp
@@ -1,8 +1,8 @@
//
-// local_free_on_block_exit.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/local_free_on_block_exit.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,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_WINDOWS) || defined(__CYGWIN__)
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_types.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
@@ -52,8 +50,8 @@ private:
} // namespace detail
} // namespace asio
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-
#include "asio/detail/pop_options.hpp"
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
#endif // ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP
diff --git a/ext/asio/asio/detail/macos_fenced_block.hpp b/ext/asio/asio/detail/macos_fenced_block.hpp
index 3c303d62bc..fcb8bfc61f 100644
--- a/ext/asio/asio/detail/macos_fenced_block.hpp
+++ b/ext/asio/asio/detail/macos_fenced_block.hpp
@@ -1,8 +1,8 @@
//
-// macos_fenced_block.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~
+// detail/macos_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,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 <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
#if defined(__MACH__) && defined(__APPLE__)
-#include "asio/detail/push_options.hpp"
#include <libkern/OSAtomic.h>
-#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
@@ -50,8 +46,8 @@ public:
} // namespace detail
} // namespace asio
-#endif // defined(__MACH__) && defined(__APPLE__)
-
#include "asio/detail/pop_options.hpp"
+#endif // defined(__MACH__) && defined(__APPLE__)
+
#endif // ASIO_DETAIL_MACOS_FENCED_BLOCK_HPP
diff --git a/ext/asio/asio/detail/mutex.hpp b/ext/asio/asio/detail/mutex.hpp
index 024ec7f43f..dc478ff8c3 100644
--- a/ext/asio/asio/detail/mutex.hpp
+++ b/ext/asio/asio/detail/mutex.hpp
@@ -1,8 +1,8 @@
//
-// mutex.hpp
-// ~~~~~~~~~
+// detail/mutex.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_mutex.hpp"
@@ -45,6 +41,4 @@ typedef posix_mutex mutex;
} // namespace detail
} // namespace asio
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_DETAIL_MUTEX_HPP
diff --git a/ext/asio/asio/detail/noncopyable.hpp b/ext/asio/asio/detail/noncopyable.hpp
index 8b73ff0407..e7f6437d7c 100644
--- a/ext/asio/asio/detail/noncopyable.hpp
+++ b/ext/asio/asio/detail/noncopyable.hpp
@@ -1,8 +1,8 @@
//
-// noncopyable.hpp
-// ~~~~~~~~~~~~~~~
+// detail/noncopyable.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,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 "asio/detail/config.hpp"
#include <boost/noncopyable.hpp>
#include <boost/detail/workaround.hpp>
-#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
diff --git a/ext/asio/asio/detail/null_event.hpp b/ext/asio/asio/detail/null_event.hpp
index bcea31b804..db7b7471fb 100644
--- a/ext/asio/asio/detail/null_event.hpp
+++ b/ext/asio/asio/detail/null_event.hpp
@@ -1,8 +1,8 @@
//
-// null_event.hpp
-// ~~~~~~~~~~~~~~
+// detail/null_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,16 +15,14 @@
# 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/noncopyable.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
@@ -70,8 +68,8 @@ public:
} // namespace detail
} // namespace asio
-#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
-
#include "asio/detail/pop_options.hpp"
+#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+
#endif // ASIO_DETAIL_NULL_EVENT_HPP
diff --git a/ext/asio/asio/detail/null_fenced_block.hpp b/ext/asio/asio/detail/null_fenced_block.hpp
index dd9a095a72..fbd025f18b 100644
--- a/ext/asio/asio/detail/null_fenced_block.hpp
+++ b/ext/asio/asio/detail/null_fenced_block.hpp
@@ -1,8 +1,8 @@
//
-// null_fenced_block.hpp
-// ~~~~~~~~~~~~~~~~~~~~~
+// detail/null_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)
diff --git a/ext/asio/asio/detail/null_mutex.hpp b/ext/asio/asio/detail/null_mutex.hpp
index 6661ef8324..bbceb7c2a5 100644
--- a/ext/asio/asio/detail/null_mutex.hpp
+++ b/ext/asio/asio/detail/null_mutex.hpp
@@ -1,8 +1,8 @@
//
-// null_mutex.hpp
-// ~~~~~~~~~~~~~~
+// detail/null_mutex.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,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_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/scoped_lock.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
@@ -59,8 +57,8 @@ public:
} // namespace detail
} // namespace asio
-#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
-
#include "asio/detail/pop_options.hpp"
+#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+
#endif // ASIO_DETAIL_NULL_MUTEX_HPP
diff --git a/ext/asio/asio/detail/null_signal_blocker.hpp b/ext/asio/asio/detail/null_signal_blocker.hpp
index a5db315acb..e0d996f736 100644
--- a/ext/asio/asio/detail/null_signal_blocker.hpp
+++ b/ext/asio/asio/detail/null_signal_blocker.hpp
@@ -1,8 +1,8 @@
//
-// null_signal_blocker.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~
+// detail/null_signal_blocker.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,18 @@
# 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)
+#if !defined(BOOST_HAS_THREADS) \
+ || defined(ASIO_DISABLE_THREADS) \
+ || defined(BOOST_WINDOWS) \
+ || defined(__CYGWIN__) \
+ || defined(__SYMBIAN32__)
#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
@@ -56,8 +58,12 @@ public:
} // namespace detail
} // namespace asio
-#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
-
#include "asio/detail/pop_options.hpp"
+#endif // !defined(BOOST_HAS_THREADS)
+ // || defined(ASIO_DISABLE_THREADS)
+ // || defined(BOOST_WINDOWS)
+ // || defined(__CYGWIN__)
+ // || defined(__SYMBIAN32__)
+
#endif // ASIO_DETAIL_NULL_SIGNAL_BLOCKER_HPP
diff --git a/ext/asio/asio/detail/null_thread.hpp b/ext/asio/asio/detail/null_thread.hpp
index ce3d470ad9..bfe918e289 100644
--- a/ext/asio/asio/detail/null_thread.hpp
+++ b/ext/asio/asio/detail/null_thread.hpp
@@ -1,8 +1,8 @@
//
-// null_thread.hpp
-// ~~~~~~~~~~~~~~~
+// detail/null_thread.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,21 +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_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
-#include "asio/detail/push_options.hpp"
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
@@ -40,11 +34,10 @@ class null_thread
public:
// Constructor.
template <typename Function>
- null_thread(Function )
+ null_thread(Function, unsigned int = 0)
{
- asio::system_error e(
+ asio::detail::throw_error(
asio::error::operation_not_supported, "thread");
- boost::throw_exception(e);
}
// Destructor.
@@ -61,8 +54,8 @@ public:
} // namespace detail
} // namespace asio
-#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
-
#include "asio/detail/pop_options.hpp"
+#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+
#endif // ASIO_DETAIL_NULL_THREAD_HPP
diff --git a/ext/asio/asio/detail/null_tss_ptr.hpp b/ext/asio/asio/detail/null_tss_ptr.hpp
index 112b4761c6..d3456e6157 100644
--- a/ext/asio/asio/detail/null_tss_ptr.hpp
+++ b/ext/asio/asio/detail/null_tss_ptr.hpp
@@ -1,8 +1,8 @@
//
-// null_tss_ptr.hpp
-// ~~~~~~~~~~~~~~~~
+// detail/null_tss_ptr.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/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/noncopyable.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
@@ -63,8 +61,8 @@ private:
} // namespace detail
} // namespace asio
-#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
-
#include "asio/detail/pop_options.hpp"
+#endif // !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+
#endif // ASIO_DETAIL_NULL_TSS_PTR_HPP
diff --git a/ext/asio/asio/detail/object_pool.hpp b/ext/asio/asio/detail/object_pool.hpp
new file mode 100644
index 0000000000..dc50febb16
--- /dev/null
+++ b/ext/asio/asio/detail/object_pool.hpp
@@ -0,0 +1,146 @@
+//
+// detail/object_pool.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_OBJECT_POOL_HPP
+#define ASIO_DETAIL_OBJECT_POOL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/noncopyable.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Object>
+class object_pool;
+
+class object_pool_access
+{
+public:
+ template <typename Object>
+ static Object* create()
+ {
+ return new Object;
+ }
+
+ template <typename Object>
+ static void destroy(Object* o)
+ {
+ delete o;
+ }
+
+ template <typename Object>
+ static Object*& next(Object* o)
+ {
+ return o->next_;
+ }
+
+ template <typename Object>
+ static Object*& prev(Object* o)
+ {
+ return o->prev_;
+ }
+};
+
+template <typename Object>
+class object_pool
+ : private noncopyable
+{
+public:
+ // Constructor.
+ object_pool()
+ : live_list_(0),
+ free_list_(0)
+ {
+ }
+
+ // Destructor destroys all objects.
+ ~object_pool()
+ {
+ destroy_list(live_list_);
+ destroy_list(free_list_);
+ }
+
+ // Get the object at the start of the live list.
+ Object* first()
+ {
+ return live_list_;
+ }
+
+ // Allocate a new object.
+ Object* alloc()
+ {
+ Object* o = free_list_;
+ if (o)
+ free_list_ = object_pool_access::next(free_list_);
+ else
+ o = object_pool_access::create<Object>();
+
+ object_pool_access::next(o) = live_list_;
+ object_pool_access::prev(o) = 0;
+ if (live_list_)
+ object_pool_access::prev(live_list_) = o;
+ live_list_ = o;
+
+ return o;
+ }
+
+ // Free an object. Moves it to the free list. No destructors are run.
+ void free(Object* o)
+ {
+ if (live_list_ == o)
+ live_list_ = object_pool_access::next(o);
+
+ if (object_pool_access::prev(o))
+ {
+ object_pool_access::next(object_pool_access::prev(o))
+ = object_pool_access::next(o);
+ }
+
+ if (object_pool_access::next(o))
+ {
+ object_pool_access::prev(object_pool_access::next(o))
+ = object_pool_access::prev(o);
+ }
+
+ object_pool_access::next(o) = free_list_;
+ object_pool_access::prev(o) = 0;
+ free_list_ = o;
+ }
+
+private:
+ // Helper function to destroy all elements in a list.
+ void destroy_list(Object* list)
+ {
+ while (list)
+ {
+ Object* o = list;
+ list = object_pool_access::next(o);
+ object_pool_access::destroy(o);
+ }
+ }
+
+ // The list of live objects.
+ Object* live_list_;
+
+ // The free list.
+ Object* free_list_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_OBJECT_POOL_HPP
diff --git a/ext/asio/asio/detail/old_win_sdk_compat.hpp b/ext/asio/asio/detail/old_win_sdk_compat.hpp
index 70e5916d6a..fb755791d3 100644
--- a/ext/asio/asio/detail/old_win_sdk_compat.hpp
+++ b/ext/asio/asio/detail/old_win_sdk_compat.hpp
@@ -1,8 +1,8 @@
//
-// old_win_sdk_compat.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~
+// detail/old_win_sdk_compat.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_WINDOWS) || defined(__CYGWIN__)
@@ -36,6 +32,8 @@
// a recent (i.e. Vista or later) SDK, as the SDK does not provide IPv6 support
// in that case.
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
@@ -321,6 +319,8 @@ inline int IN6_IS_ADDR_MC_GLOBAL(const in6_addr_emulation* a)
} // namespace detail
} // namespace asio
+#include "asio/detail/pop_options.hpp"
+
#endif // defined(ASIO_HAS_OLD_WIN_SDK)
// Even newer Platform SDKs that support IPv6 may not define IPV6_V6ONLY.
@@ -335,6 +335,4 @@ inline int IN6_IS_ADDR_MC_GLOBAL(const in6_addr_emulation* a)
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_DETAIL_OLD_WIN_SDK_COMPAT_HPP
diff --git a/ext/asio/asio/detail/op_queue.hpp b/ext/asio/asio/detail/op_queue.hpp
index ccf8b9a5c2..38278eafac 100644
--- a/ext/asio/asio/detail/op_queue.hpp
+++ b/ext/asio/asio/detail/op_queue.hpp
@@ -1,8 +1,8 @@
//
-// op_queue.hpp
-// ~~~~~~~~~~~~
+// detail/op_queue.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,10 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
diff --git a/ext/asio/asio/detail/operation.hpp b/ext/asio/asio/detail/operation.hpp
index 6aba361218..3435c057db 100644
--- a/ext/asio/asio/detail/operation.hpp
+++ b/ext/asio/asio/detail/operation.hpp
@@ -1,8 +1,8 @@
//
-// operation.hpp
-// ~~~~~~~~~~~~~
+// detail/operation.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,11 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_IOCP)
# include "asio/detail/win_iocp_operation.hpp"
#else
-# include "asio/detail/reactor_fwd.hpp"
# include "asio/detail/task_io_service_operation.hpp"
#endif
@@ -32,12 +29,10 @@ namespace detail {
#if defined(ASIO_HAS_IOCP)
typedef win_iocp_operation operation;
#else
-typedef task_io_service_operation<reactor> operation;
+typedef task_io_service_operation operation;
#endif
} // namespace detail
} // namespace asio
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_DETAIL_OPERATION_HPP
diff --git a/ext/asio/asio/detail/pipe_select_interrupter.hpp b/ext/asio/asio/detail/pipe_select_interrupter.hpp
index 74695994dc..bf3942684c 100644
--- a/ext/asio/asio/detail/pipe_select_interrupter.hpp
+++ b/ext/asio/asio/detail/pipe_select_interrupter.hpp
@@ -1,8 +1,8 @@
//
-// pipe_select_interrupter.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/pipe_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)
//
// 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,14 @@
# 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 <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#if !defined(BOOST_WINDOWS)
+#if !defined(__CYGWIN__)
+#if !defined(__SYMBIAN32__)
+#if !defined(ASIO_HAS_EVENTFD)
#include "asio/detail/push_options.hpp"
-#include <fcntl.h>
-#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 {
@@ -39,57 +31,16 @@ class pipe_select_interrupter
{
public:
// Constructor.
- 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::system_error e(ec, "pipe_select_interrupter");
- boost::throw_exception(e);
- }
- }
+ ASIO_DECL pipe_select_interrupter();
// Destructor.
- ~pipe_select_interrupter()
- {
- if (read_descriptor_ != -1)
- ::close(read_descriptor_);
- if (write_descriptor_ != -1)
- ::close(write_descriptor_);
- }
+ ASIO_DECL ~pipe_select_interrupter();
// Interrupt the select call.
- void interrupt()
- {
- char byte = 0;
- int result = ::write(write_descriptor_, &byte, 1);
- (void)result;
- }
+ ASIO_DECL void interrupt();
// Reset the select interrupt. Returns true if the call was interrupted.
- bool 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;
- }
- }
+ ASIO_DECL bool reset();
// Get the read descriptor to be passed to select.
int read_descriptor() const
@@ -113,8 +64,15 @@ private:
} // 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/pipe_select_interrupter.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // !defined(ASIO_HAS_EVENTFD)
+#endif // !defined(__SYMBIAN32__)
+#endif // !defined(__CYGWIN__)
+#endif // !defined(BOOST_WINDOWS)
+
#endif // ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP
diff --git a/ext/asio/asio/detail/pop_options.hpp b/ext/asio/asio/detail/pop_options.hpp
index a26b2039c0..4e193363ab 100644
--- a/ext/asio/asio/detail/pop_options.hpp
+++ b/ext/asio/asio/detail/pop_options.hpp
@@ -1,8 +1,8 @@
//
-// pop_options.hpp
-// ~~~~~~~~~~~~~~~
+// detail/pop_options.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)
@@ -31,6 +31,16 @@
# pragma pack (pop)
# endif
+# if defined(__OBJC__)
+# if !defined(__APPLE_CC__) || (__APPLE_CC__ <= 1)
+# if defined(ASIO_OBJC_WORKAROUND)
+# undef Protocol
+# undef id
+# undef ASIO_OBJC_WORKAROUND
+# endif
+# endif
+# endif
+
#elif defined(__KCC)
// Kai C++
diff --git a/ext/asio/asio/detail/posix_event.hpp b/ext/asio/asio/detail/posix_event.hpp
index 49c15aa5a0..d0ec8b0012 100644
--- a/ext/asio/asio/detail/posix_event.hpp
+++ b/ext/asio/asio/detail/posix_event.hpp
@@ -1,8 +1,8 @@
//
-// posix_event.hpp
-// ~~~~~~~~~~~~~~~
+// detail/posix_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,24 +15,16 @@
# 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_PTHREADS)
+#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
-#include "asio/detail/push_options.hpp"
#include <boost/assert.hpp>
-#include <boost/throw_exception.hpp>
#include <pthread.h>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
@@ -41,19 +33,7 @@ class posix_event
{
public:
// Constructor.
- posix_event()
- : signalled_(false)
- {
- int error = ::pthread_cond_init(&cond_, 0);
- if (error != 0)
- {
- asio::system_error e(
- asio::error_code(error,
- asio::error::get_system_category()),
- "event");
- boost::throw_exception(e);
- }
- }
+ ASIO_DECL posix_event();
// Destructor.
~posix_event()
@@ -107,8 +87,12 @@ private:
} // namespace detail
} // namespace asio
-#endif // defined(BOOST_HAS_PTHREADS)
-
#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/posix_event.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
#endif // ASIO_DETAIL_POSIX_EVENT_HPP
diff --git a/ext/asio/asio/detail/posix_fd_set_adapter.hpp b/ext/asio/asio/detail/posix_fd_set_adapter.hpp
index 17ef269cee..92d6bba7f2 100644
--- a/ext/asio/asio/detail/posix_fd_set_adapter.hpp
+++ b/ext/asio/asio/detail/posix_fd_set_adapter.hpp
@@ -1,8 +1,8 @@
//
-// posix_fd_set_adapter.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/posix_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,15 +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/push_options.hpp"
-#include <cstring>
-#include "asio/detail/pop_options.hpp"
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#include <cstring>
#include "asio/detail/socket_types.hpp"
-#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
@@ -74,8 +73,8 @@ private:
} // namespace detail
} // namespace asio
-#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-
#include "asio/detail/pop_options.hpp"
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
#endif // ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP
diff --git a/ext/asio/asio/detail/posix_mutex.hpp b/ext/asio/asio/detail/posix_mutex.hpp
index 230b83a356..bcdf6b27d4 100644
--- a/ext/asio/asio/detail/posix_mutex.hpp
+++ b/ext/asio/asio/detail/posix_mutex.hpp
@@ -1,8 +1,8 @@
//
-// posix_mutex.hpp
-// ~~~~~~~~~~~~~~~
+// detail/posix_mutex.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,16 @@
# 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_PTHREADS)
+#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
-#include "asio/detail/push_options.hpp"
-#include <boost/throw_exception.hpp>
#include <pthread.h>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/scoped_lock.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
@@ -45,18 +37,7 @@ public:
typedef asio::detail::scoped_lock<posix_mutex> scoped_lock;
// Constructor.
- posix_mutex()
- {
- int error = ::pthread_mutex_init(&mutex_, 0);
- if (error != 0)
- {
- asio::system_error e(
- asio::error_code(error,
- asio::error::get_system_category()),
- "mutex");
- boost::throw_exception(e);
- }
- }
+ ASIO_DECL posix_mutex();
// Destructor.
~posix_mutex()
@@ -84,8 +65,12 @@ private:
} // namespace detail
} // namespace asio
-#endif // defined(BOOST_HAS_PTHREADS)
-
#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/posix_mutex.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
#endif // ASIO_DETAIL_POSIX_MUTEX_HPP
diff --git a/ext/asio/asio/detail/posix_signal_blocker.hpp b/ext/asio/asio/detail/posix_signal_blocker.hpp
index 135ca41b7e..d41f128476 100644
--- a/ext/asio/asio/detail/posix_signal_blocker.hpp
+++ b/ext/asio/asio/detail/posix_signal_blocker.hpp
@@ -1,8 +1,8 @@
//
-// posix_signal_blocker.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/posix_signal_blocker.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,17 @@
# 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_PTHREADS)
+#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
-#include "asio/detail/push_options.hpp"
#include <csignal>
#include <pthread.h>
#include <signal.h>
-#include "asio/detail/pop_options.hpp"
-
#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
@@ -83,8 +78,8 @@ private:
} // namespace detail
} // namespace asio
-#endif // defined(BOOST_HAS_PTHREADS)
-
#include "asio/detail/pop_options.hpp"
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
#endif // ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP
diff --git a/ext/asio/asio/detail/posix_thread.hpp b/ext/asio/asio/detail/posix_thread.hpp
index e0fea75129..743417cd62 100644
--- a/ext/asio/asio/detail/posix_thread.hpp
+++ b/ext/asio/asio/detail/posix_thread.hpp
@@ -1,8 +1,8 @@
//
-// posix_thread.hpp
-// ~~~~~~~~~~~~~~~~
+// detail/posix_thread.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,22 @@
# 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_PTHREADS)
+#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
-#include "asio/detail/push_options.hpp"
-#include <memory>
-#include <boost/throw_exception.hpp>
#include <pthread.h>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
-extern "C" void* asio_detail_posix_thread_function(void* arg);
+extern "C"
+{
+ ASIO_DECL void* asio_detail_posix_thread_function(void* arg);
+}
class posix_thread
: private noncopyable
@@ -47,36 +41,14 @@ public:
posix_thread(Function f)
: joined_(false)
{
- std::auto_ptr<func_base> arg(new func<Function>(f));
- int error = ::pthread_create(&thread_, 0,
- asio_detail_posix_thread_function, arg.get());
- if (error != 0)
- {
- asio::system_error e(
- asio::error_code(error,
- asio::error::get_system_category()),
- "thread");
- boost::throw_exception(e);
- }
- arg.release();
+ start_thread(new func<Function>(f));
}
// Destructor.
- ~posix_thread()
- {
- if (!joined_)
- ::pthread_detach(thread_);
- }
+ ASIO_DECL ~posix_thread();
// Wait for the thread to exit.
- void join()
- {
- if (!joined_)
- {
- ::pthread_join(thread_, 0);
- joined_ = true;
- }
- }
+ ASIO_DECL void join();
private:
friend void* asio_detail_posix_thread_function(void* arg);
@@ -88,6 +60,12 @@ private:
virtual void run() = 0;
};
+ struct auto_func_base_ptr
+ {
+ func_base* ptr;
+ ~auto_func_base_ptr() { delete ptr; }
+ };
+
template <typename Function>
class func
: public func_base
@@ -107,23 +85,21 @@ private:
Function f_;
};
+ ASIO_DECL void start_thread(func_base* arg);
+
::pthread_t thread_;
bool joined_;
};
-inline void* asio_detail_posix_thread_function(void* arg)
-{
- std::auto_ptr<posix_thread::func_base> f(
- static_cast<posix_thread::func_base*>(arg));
- f->run();
- return 0;
-}
-
} // namespace detail
} // namespace asio
-#endif // defined(BOOST_HAS_PTHREADS)
-
#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/posix_thread.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
#endif // ASIO_DETAIL_POSIX_THREAD_HPP
diff --git a/ext/asio/asio/detail/posix_tss_ptr.hpp b/ext/asio/asio/detail/posix_tss_ptr.hpp
index 3b4ba07b44..30d9705e7a 100644
--- a/ext/asio/asio/detail/posix_tss_ptr.hpp
+++ b/ext/asio/asio/detail/posix_tss_ptr.hpp
@@ -1,8 +1,8 @@
//
-// posix_tss_ptr.hpp
-// ~~~~~~~~~~~~~~~~~
+// detail/posix_tss_ptr.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,26 +15,21 @@
# 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_PTHREADS)
+#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
-#include "asio/detail/push_options.hpp"
-#include <boost/throw_exception.hpp>
#include <pthread.h>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
+// Helper function to create thread-specific storage.
+ASIO_DECL void posix_tss_ptr_create(pthread_key_t& key);
+
template <typename T>
class posix_tss_ptr
: private noncopyable
@@ -43,15 +38,7 @@ public:
// Constructor.
posix_tss_ptr()
{
- int error = ::pthread_key_create(&tss_key_, 0);
- if (error != 0)
- {
- asio::system_error e(
- asio::error_code(error,
- asio::error::get_system_category()),
- "tss");
- boost::throw_exception(e);
- }
+ posix_tss_ptr_create(tss_key_);
}
// Destructor.
@@ -76,13 +63,18 @@ private:
// Thread-specific storage to allow unlocked access to determine whether a
// thread is a member of the pool.
pthread_key_t tss_key_;
+
};
} // namespace detail
} // namespace asio
-#endif // defined(BOOST_HAS_PTHREADS)
-
#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/posix_tss_ptr.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
+
#endif // ASIO_DETAIL_POSIX_TSS_PTR_HPP
diff --git a/ext/asio/asio/detail/push_options.hpp b/ext/asio/asio/detail/push_options.hpp
index cb0e90242e..ebb3276052 100644
--- a/ext/asio/asio/detail/push_options.hpp
+++ b/ext/asio/asio/detail/push_options.hpp
@@ -1,8 +1,8 @@
//
-// push_options.hpp
-// ~~~~~~~~~~~~~~~~
+// detail/push_options.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)
@@ -31,6 +31,18 @@
# pragma pack (push, 8)
# endif
+# if defined(__OBJC__)
+# if !defined(__APPLE_CC__) || (__APPLE_CC__ <= 1)
+# if !defined(ASIO_DISABLE_OBJC_WORKAROUND)
+# if !defined(Protocol) && !defined(id)
+# define Protocol cpp_Protocol
+# define id cpp_id
+# define ASIO_OBJC_WORKAROUND
+# endif
+# endif
+# endif
+# endif
+
#elif defined(__KCC)
// Kai C++
diff --git a/ext/asio/asio/detail/reactive_descriptor_service.hpp b/ext/asio/asio/detail/reactive_descriptor_service.hpp
index 7ad368d7de..f7e8bf53a5 100644
--- a/ext/asio/asio/detail/reactive_descriptor_service.hpp
+++ b/ext/asio/asio/detail/reactive_descriptor_service.hpp
@@ -1,8 +1,8 @@
//
-// reactive_descriptor_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/reactive_descriptor_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,21 +15,24 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#include <boost/utility/addressof.hpp>
#include "asio/buffer.hpp"
-#include "asio/error.hpp"
#include "asio/io_service.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/buffer_sequence_adapter.hpp"
#include "asio/detail/descriptor_ops.hpp"
+#include "asio/detail/descriptor_read_op.hpp"
+#include "asio/detail/descriptor_write_op.hpp"
#include "asio/detail/fenced_block.hpp"
#include "asio/detail/noncopyable.hpp"
-#include "asio/detail/null_buffers_op.hpp"
+#include "asio/detail/reactive_null_buffers_op.hpp"
#include "asio/detail/reactor.hpp"
-#include "asio/detail/reactor_op.hpp"
-#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
@@ -48,7 +51,7 @@ public:
// Default constructor.
implementation_type()
: descriptor_(-1),
- flags_(0)
+ state_(0)
{
}
@@ -59,94 +62,29 @@ public:
// The native descriptor representation.
int descriptor_;
- enum
- {
- // The user wants a non-blocking descriptor.
- user_set_non_blocking = 1,
-
- // The descriptor has been set non-blocking.
- internal_non_blocking = 2,
-
- // Helper "flag" used to determine whether the descriptor is non-blocking.
- non_blocking = user_set_non_blocking | internal_non_blocking
- };
-
- // Flags indicating the current state of the descriptor.
- unsigned char flags_;
+ // The current state of the descriptor.
+ descriptor_ops::state_type state_;
// Per-descriptor data used by the reactor.
reactor::per_descriptor_data reactor_data_;
};
- // The maximum number of buffers to support in a single operation.
- enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
-
// Constructor.
- reactive_descriptor_service(asio::io_service& io_service)
- : io_service_impl_(asio::use_service<io_service_impl>(io_service)),
- reactor_(asio::use_service<reactor>(io_service))
- {
- reactor_.init_task();
- }
+ ASIO_DECL reactive_descriptor_service(
+ asio::io_service& io_service);
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
- {
- }
+ ASIO_DECL void shutdown_service();
// Construct a new descriptor implementation.
- void construct(implementation_type& impl)
- {
- impl.descriptor_ = -1;
- impl.flags_ = 0;
- }
+ ASIO_DECL void construct(implementation_type& impl);
// Destroy a descriptor implementation.
- void destroy(implementation_type& impl)
- {
- if (impl.descriptor_ != -1)
- {
- reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_);
-
- if (impl.flags_ & implementation_type::internal_non_blocking)
- {
- ioctl_arg_type non_blocking = 0;
- asio::error_code ignored_ec;
- descriptor_ops::ioctl(impl.descriptor_,
- FIONBIO, &non_blocking, ignored_ec);
- impl.flags_ &= ~implementation_type::internal_non_blocking;
- }
-
- asio::error_code ignored_ec;
- descriptor_ops::close(impl.descriptor_, ignored_ec);
-
- impl.descriptor_ = -1;
- }
- }
+ ASIO_DECL void destroy(implementation_type& impl);
// Assign a native descriptor to a descriptor implementation.
- asio::error_code assign(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.flags_ = 0;
- ec = asio::error_code();
- return ec;
- }
+ ASIO_DECL asio::error_code assign(implementation_type& impl,
+ const native_type& native_descriptor, asio::error_code& ec);
// Determine whether the descriptor is open.
bool is_open(const implementation_type& impl) const
@@ -155,31 +93,8 @@ public:
}
// Destroy a descriptor implementation.
- asio::error_code close(implementation_type& impl,
- asio::error_code& ec)
- {
- if (is_open(impl))
- {
- reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_);
-
- if (impl.flags_ & implementation_type::internal_non_blocking)
- {
- ioctl_arg_type non_blocking = 0;
- asio::error_code ignored_ec;
- descriptor_ops::ioctl(impl.descriptor_,
- FIONBIO, &non_blocking, ignored_ec);
- impl.flags_ &= ~implementation_type::internal_non_blocking;
- }
-
- if (descriptor_ops::close(impl.descriptor_, ec) == -1)
- return ec;
-
- impl.descriptor_ = -1;
- }
-
- ec = asio::error_code();
- return ec;
- }
+ ASIO_DECL asio::error_code close(implementation_type& impl,
+ asio::error_code& ec);
// Get the native descriptor representation.
native_type native(const implementation_type& impl) const
@@ -188,56 +103,16 @@ public:
}
// Cancel all operations associated with the descriptor.
- asio::error_code cancel(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;
- }
+ ASIO_DECL asio::error_code cancel(implementation_type& impl,
+ asio::error_code& ec);
// Perform an IO control command on the descriptor.
template <typename IO_Control_Command>
asio::error_code io_control(implementation_type& impl,
IO_Control_Command& command, asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return ec;
- }
-
- descriptor_ops::ioctl(impl.descriptor_, command.name(),
- static_cast<ioctl_arg_type*>(command.data()), ec);
-
- // 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 (!ec && command.name() == static_cast<int>(FIONBIO))
- {
- if (*static_cast<ioctl_arg_type*>(command.data()))
- {
- impl.flags_ |= implementation_type::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.
- impl.flags_ &= ~(implementation_type::user_set_non_blocking
- | implementation_type::internal_non_blocking);
- }
- }
-
+ descriptor_ops::ioctl(impl.descriptor_, impl.state_,
+ command.name(), static_cast<ioctl_arg_type*>(command.data()), ec);
return ec;
}
@@ -246,148 +121,23 @@ public:
size_t write_some(implementation_type& impl,
const ConstBufferSequence& buffers, asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
buffer_sequence_adapter<asio::const_buffer,
ConstBufferSequence> bufs(buffers);
- // A request to read_some 0 bytes on a stream is a no-op.
- if (bufs.all_empty())
- {
- ec = asio::error_code();
- return 0;
- }
-
- // Send the data.
- for (;;)
- {
- // Try to complete the operation without blocking.
- int bytes_sent = descriptor_ops::gather_write(
- impl.descriptor_, bufs.buffers(), bufs.count(), ec);
-
- // Check if operation succeeded.
- if (bytes_sent >= 0)
- return bytes_sent;
-
- // Operation failed.
- if ((impl.flags_ & implementation_type::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(impl.descriptor_, ec) < 0)
- return 0;
- }
+ return descriptor_ops::sync_write(impl.descriptor_, impl.state_,
+ bufs.buffers(), bufs.count(), bufs.all_empty(), ec);
}
// Wait until data can be written without blocking.
size_t write_some(implementation_type& impl,
const null_buffers&, asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
// Wait for descriptor to become ready.
descriptor_ops::poll_write(impl.descriptor_, ec);
return 0;
}
- template <typename ConstBufferSequence>
- class write_op_base : public reactor_op
- {
- public:
- write_op_base(int descriptor,
- const ConstBufferSequence& buffers, func_type complete_func)
- : reactor_op(&write_op_base::do_perform, complete_func),
- descriptor_(descriptor),
- buffers_(buffers)
- {
- }
-
- static bool do_perform(reactor_op* base)
- {
- write_op_base* o(static_cast<write_op_base*>(base));
-
- buffer_sequence_adapter<asio::const_buffer,
- ConstBufferSequence> bufs(o->buffers_);
-
- for (;;)
- {
- // Write the data.
- asio::error_code ec;
- int bytes = descriptor_ops::gather_write(
- o->descriptor_, bufs.buffers(), bufs.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;
-
- o->ec_ = ec;
- o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);
- return true;
- }
- }
-
- private:
- int descriptor_;
- ConstBufferSequence buffers_;
- };
-
- template <typename ConstBufferSequence, typename Handler>
- class write_op : public write_op_base<ConstBufferSequence>
- {
- public:
- write_op(int descriptor,
- const ConstBufferSequence& buffers, Handler handler)
- : write_op_base<ConstBufferSequence>(
- descriptor, buffers, &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.
- write_op* o(static_cast<write_op*>(base));
- typedef handler_alloc_traits<Handler, write_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- // 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::binder2<Handler, asio::error_code, std::size_t>
- handler(o->handler_, o->ec_, o->bytes_transferred_);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
- }
-
- private:
- Handler handler_;
- };
-
// Start an asynchronous write. The data being sent must be valid for the
// lifetime of the asynchronous operation.
template <typename ConstBufferSequence, typename Handler>
@@ -395,15 +145,16 @@ public:
const ConstBufferSequence& buffers, Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef write_op<ConstBufferSequence, 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, impl.descriptor_, buffers, handler);
+ typedef descriptor_write_op<ConstBufferSequence, Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.descriptor_, buffers, handler);
- start_op(impl, reactor::write_op, ptr.get(), true,
+ start_op(impl, reactor::write_op, p.p, true,
buffer_sequence_adapter<asio::const_buffer,
ConstBufferSequence>::all_empty(buffers));
- ptr.release();
+ p.v = p.p = 0;
}
// Start an asynchronous wait until data can be written without blocking.
@@ -412,13 +163,14 @@ public:
const null_buffers&, Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef null_buffers_op<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 reactive_null_buffers_op<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);
- start_op(impl, reactor::write_op, ptr.get(), false, false);
- ptr.release();
+ start_op(impl, reactor::write_op, p.p, false, false);
+ p.v = p.p = 0;
}
// Read some data from the stream. Returns the number of bytes read.
@@ -426,157 +178,23 @@ public:
size_t read_some(implementation_type& impl,
const MutableBufferSequence& buffers, asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
buffer_sequence_adapter<asio::mutable_buffer,
MutableBufferSequence> bufs(buffers);
- // A request to read_some 0 bytes on a stream is a no-op.
- if (bufs.all_empty())
- {
- ec = asio::error_code();
- return 0;
- }
-
- // Read some data.
- for (;;)
- {
- // Try to complete the operation without blocking.
- int bytes_read = descriptor_ops::scatter_read(
- impl.descriptor_, bufs.buffers(), bufs.count(), ec);
-
- // Check if operation succeeded.
- if (bytes_read > 0)
- return bytes_read;
-
- // Check for EOF.
- if (bytes_read == 0)
- {
- ec = asio::error::eof;
- return 0;
- }
-
- // Operation failed.
- if ((impl.flags_ & implementation_type::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(impl.descriptor_, ec) < 0)
- return 0;
- }
+ return descriptor_ops::sync_read(impl.descriptor_, impl.state_,
+ bufs.buffers(), bufs.count(), bufs.all_empty(), ec);
}
// Wait until data can be read without blocking.
size_t read_some(implementation_type& impl,
const null_buffers&, asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
// Wait for descriptor to become ready.
descriptor_ops::poll_read(impl.descriptor_, ec);
return 0;
}
- template <typename MutableBufferSequence>
- class read_op_base : public reactor_op
- {
- public:
- read_op_base(int descriptor,
- const MutableBufferSequence& buffers, func_type complete_func)
- : reactor_op(&read_op_base::do_perform, complete_func),
- descriptor_(descriptor),
- buffers_(buffers)
- {
- }
-
- static bool do_perform(reactor_op* base)
- {
- read_op_base* o(static_cast<read_op_base*>(base));
-
- buffer_sequence_adapter<asio::mutable_buffer,
- MutableBufferSequence> bufs(o->buffers_);
-
- for (;;)
- {
- // Read some data.
- asio::error_code ec;
- int bytes = descriptor_ops::scatter_read(
- o->descriptor_, bufs.buffers(), bufs.count(), ec);
- if (bytes == 0)
- ec = asio::error::eof;
-
- // 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;
-
- o->ec_ = ec;
- o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);
- return true;
- }
- }
-
- private:
- int descriptor_;
- MutableBufferSequence buffers_;
- };
-
- template <typename MutableBufferSequence, typename Handler>
- class read_op : public read_op_base<MutableBufferSequence>
- {
- public:
- read_op(int descriptor,
- const MutableBufferSequence& buffers, Handler handler)
- : read_op_base<MutableBufferSequence>(
- descriptor, buffers, &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.
- read_op* o(static_cast<read_op*>(base));
- typedef handler_alloc_traits<Handler, read_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- // 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::binder2<Handler, asio::error_code, std::size_t>
- handler(o->handler_, o->ec_, o->bytes_transferred_);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
- }
-
- private:
- Handler handler_;
- };
-
// Start an asynchronous read. The buffer for the data being read must be
// valid for the lifetime of the asynchronous operation.
template <typename MutableBufferSequence, typename Handler>
@@ -584,16 +202,16 @@ public:
const MutableBufferSequence& buffers, Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef read_op<MutableBufferSequence, 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,
- impl.descriptor_, buffers, handler);
+ typedef descriptor_read_op<MutableBufferSequence, Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.descriptor_, buffers, handler);
- start_op(impl, reactor::read_op, ptr.get(), true,
+ start_op(impl, reactor::read_op, p.p, true,
buffer_sequence_adapter<asio::mutable_buffer,
MutableBufferSequence>::all_empty(buffers));
- ptr.release();
+ p.v = p.p = 0;
}
// Wait until data can be read without blocking.
@@ -602,57 +220,20 @@ public:
const null_buffers&, Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef null_buffers_op<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 reactive_null_buffers_op<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);
- start_op(impl, reactor::read_op, ptr.get(), false, false);
- ptr.release();
+ start_op(impl, reactor::read_op, p.p, false, false);
+ p.v = p.p = 0;
}
private:
// Start the asynchronous operation.
- void start_op(implementation_type& impl, int op_type,
- reactor_op* op, bool non_blocking, bool noop)
- {
- if (!noop)
- {
- if (is_open(impl))
- {
- if (is_non_blocking(impl) || set_non_blocking(impl, op->ec_))
- {
- reactor_.start_op(op_type, impl.descriptor_,
- impl.reactor_data_, op, non_blocking);
- return;
- }
- }
- else
- op->ec_ = asio::error::bad_descriptor;
- }
-
- io_service_impl_.post_immediate_completion(op);
- }
-
- // Determine whether the descriptor has been set non-blocking.
- bool is_non_blocking(implementation_type& impl) const
- {
- return (impl.flags_ & implementation_type::non_blocking);
- }
-
- // Set the internal non-blocking flag.
- bool set_non_blocking(implementation_type& impl,
- asio::error_code& ec)
- {
- ioctl_arg_type non_blocking = 1;
- if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec))
- return false;
- impl.flags_ |= implementation_type::internal_non_blocking;
- return true;
- }
-
- // The io_service implementation used to post completions.
- io_service_impl& io_service_impl_;
+ ASIO_DECL void start_op(implementation_type& impl, int op_type,
+ reactor_op* op, bool non_blocking, bool noop);
// The selector that performs event demultiplexing for the service.
reactor& reactor_;
@@ -661,8 +242,12 @@ private:
} // 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/reactive_descriptor_service.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
#endif // ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP
diff --git a/ext/asio/asio/detail/reactive_null_buffers_op.hpp b/ext/asio/asio/detail/reactive_null_buffers_op.hpp
new file mode 100644
index 0000000000..0c83c612ab
--- /dev/null
+++ b/ext/asio/asio/detail/reactive_null_buffers_op.hpp
@@ -0,0 +1,83 @@
+//
+// detail/reactive_null_buffers_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_REACTIVE_NULL_BUFFERS_OP_HPP
+#define ASIO_DETAIL_REACTIVE_NULL_BUFFERS_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/reactor_op.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Handler>
+class reactive_null_buffers_op : public reactor_op
+{
+public:
+ ASIO_DEFINE_HANDLER_PTR(reactive_null_buffers_op);
+
+ reactive_null_buffers_op(Handler handler)
+ : reactor_op(&reactive_null_buffers_op::do_perform,
+ &reactive_null_buffers_op::do_complete),
+ handler_(handler)
+ {
+ }
+
+ static bool do_perform(reactor_op*)
+ {
+ return true;
+ }
+
+ 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.
+ reactive_null_buffers_op* o(static_cast<reactive_null_buffers_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 // ASIO_DETAIL_REACTIVE_NULL_BUFFERS_OP_HPP
diff --git a/ext/asio/asio/detail/reactive_serial_port_service.hpp b/ext/asio/asio/detail/reactive_serial_port_service.hpp
index 186460fef6..556ea06d87 100644
--- a/ext/asio/asio/detail/reactive_serial_port_service.hpp
+++ b/ext/asio/asio/detail/reactive_serial_port_service.hpp
@@ -1,8 +1,8 @@
//
-// reactive_serial_port_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/reactive_serial_port_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)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -16,23 +16,20 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <cstring>
-#include <string>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
-#include "asio/serial_port_base.hpp"
-
-#if defined(ASIO_HAS_SERIAL_PORT) \
- && !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#if defined(ASIO_HAS_SERIAL_PORT)
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#include <string>
#include "asio/error.hpp"
#include "asio/io_service.hpp"
+#include "asio/serial_port_base.hpp"
#include "asio/detail/descriptor_ops.hpp"
#include "asio/detail/reactive_descriptor_service.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
@@ -46,119 +43,55 @@ public:
// The implementation type of the serial port.
typedef reactive_descriptor_service::implementation_type implementation_type;
- reactive_serial_port_service(asio::io_service& io_service)
- : descriptor_service_(io_service)
- {
- }
+ ASIO_DECL reactive_serial_port_service(
+ asio::io_service& io_service);
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
- {
- descriptor_service_.shutdown_service();
- }
+ ASIO_DECL void shutdown_service();
- // Construct a new handle implementation.
+ // Construct a new serial port implementation.
void construct(implementation_type& impl)
{
descriptor_service_.construct(impl);
}
- // Destroy a handle implementation.
+ // Destroy a serial port implementation.
void destroy(implementation_type& impl)
{
descriptor_service_.destroy(impl);
}
// Open the serial port using the specified device name.
- asio::error_code open(implementation_type& impl,
- const std::string& device, asio::error_code& ec)
- {
- if (is_open(impl))
- {
- ec = asio::error::already_open;
- return ec;
- }
-
- 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, ignored_ec);
- return ec;
- }
-
- // Set up default serial port options.
- termios ios;
- descriptor_ops::clear_error(ec);
- 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;
- descriptor_ops::clear_error(ec);
- s = descriptor_ops::error_wrapper(::tcsetattr(fd, TCSANOW, &ios), ec);
- }
- if (s < 0)
- {
- asio::error_code ignored_ec;
- descriptor_ops::close(fd, 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, ignored_ec);
- }
-
- return ec;
- }
+ ASIO_DECL asio::error_code open(implementation_type& impl,
+ const std::string& device, asio::error_code& ec);
- // Assign a native handle to a handle implementation.
+ // Assign a native descriptor to a serial port implementation.
asio::error_code assign(implementation_type& impl,
const native_type& native_descriptor, asio::error_code& ec)
{
return descriptor_service_.assign(impl, native_descriptor, ec);
}
- // Determine whether the handle is open.
+ // Determine whether the serial port is open.
bool is_open(const implementation_type& impl) const
{
return descriptor_service_.is_open(impl);
}
- // Destroy a handle implementation.
+ // Destroy a serial port implementation.
asio::error_code close(implementation_type& impl,
asio::error_code& ec)
{
return descriptor_service_.close(impl, ec);
}
- // Get the native handle representation.
+ // Get the native serial port representation.
native_type native(implementation_type& impl)
{
return descriptor_service_.native(impl);
}
- // Cancel all operations associated with the handle.
+ // Cancel all operations associated with the serial port.
asio::error_code cancel(implementation_type& impl,
asio::error_code& ec)
{
@@ -170,20 +103,9 @@ public:
asio::error_code set_option(implementation_type& impl,
const SettableSerialPortOption& option, asio::error_code& ec)
{
- termios ios;
- descriptor_ops::clear_error(ec);
- descriptor_ops::error_wrapper(::tcgetattr(
- descriptor_service_.native(impl), &ios), ec);
- if (ec)
- return ec;
-
- if (option.store(ios, ec))
- return ec;
-
- descriptor_ops::clear_error(ec);
- descriptor_ops::error_wrapper(::tcsetattr(
- descriptor_service_.native(impl), TCSANOW, &ios), ec);
- return ec;
+ return do_set_option(impl,
+ &reactive_serial_port_service::store_option<SettableSerialPortOption>,
+ &option, ec);
}
// Get an option from the serial port.
@@ -191,21 +113,16 @@ public:
asio::error_code get_option(const implementation_type& impl,
GettableSerialPortOption& option, asio::error_code& ec) const
{
- termios ios;
- descriptor_ops::clear_error(ec);
- descriptor_ops::error_wrapper(::tcgetattr(
- descriptor_service_.native(impl), &ios), ec);
- if (ec)
- return ec;
-
- return option.load(ios, ec);
+ return do_get_option(impl,
+ &reactive_serial_port_service::load_option<GettableSerialPortOption>,
+ &option, ec);
}
// Send a break sequence to the serial port.
asio::error_code send_break(implementation_type& impl,
asio::error_code& ec)
{
- descriptor_ops::clear_error(ec);
+ errno = 0;
descriptor_ops::error_wrapper(::tcsendbreak(
descriptor_service_.native(impl), 0), ec);
return ec;
@@ -246,6 +163,41 @@ public:
}
private:
+ // Function pointer type for storing a serial port option.
+ typedef asio::error_code (*store_function_type)(
+ const void*, termios&, asio::error_code&);
+
+ // Helper function template to store a serial port option.
+ template <typename SettableSerialPortOption>
+ static asio::error_code store_option(const void* option,
+ termios& storage, asio::error_code& ec)
+ {
+ return static_cast<const SettableSerialPortOption*>(option)->store(
+ storage, ec);
+ }
+
+ // Helper function to set a serial port option.
+ ASIO_DECL asio::error_code do_set_option(
+ implementation_type& impl, store_function_type store,
+ const void* option, asio::error_code& ec);
+
+ // Function pointer type for loading a serial port option.
+ typedef asio::error_code (*load_function_type)(
+ void*, const termios&, asio::error_code&);
+
+ // Helper function template to load a serial port option.
+ template <typename GettableSerialPortOption>
+ static asio::error_code load_option(void* option,
+ const termios& storage, asio::error_code& ec)
+ {
+ return static_cast<GettableSerialPortOption*>(option)->load(storage, ec);
+ }
+
+ // Helper function to get a serial port option.
+ ASIO_DECL asio::error_code do_get_option(
+ const implementation_type& impl, load_function_type load,
+ void* option, asio::error_code& ec) const;
+
// The implementation used for initiating asynchronous operations.
reactive_descriptor_service descriptor_service_;
};
@@ -253,9 +205,13 @@ private:
} // namespace detail
} // namespace asio
-#endif // defined(ASIO_HAS_SERIAL_PORT)
- // && !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-
#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/reactive_serial_port_service.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#endif // defined(ASIO_HAS_SERIAL_PORT)
+
#endif // ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP
diff --git a/ext/asio/asio/detail/reactive_socket_accept_op.hpp b/ext/asio/asio/detail/reactive_socket_accept_op.hpp
new file mode 100644
index 0000000000..76c6741180
--- /dev/null
+++ b/ext/asio/asio/detail/reactive_socket_accept_op.hpp
@@ -0,0 +1,131 @@
+//
+// detail/reactive_socket_accept_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_REACTIVE_SOCKET_ACCEPT_OP_HPP
+#define ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/socket_holder.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Socket, typename Protocol>
+class reactive_socket_accept_op_base : public reactor_op
+{
+public:
+ reactive_socket_accept_op_base(socket_type socket,
+ socket_ops::state_type state, Socket& peer, const Protocol& protocol,
+ typename Protocol::endpoint* peer_endpoint, func_type complete_func)
+ : reactor_op(&reactive_socket_accept_op_base::do_perform, complete_func),
+ socket_(socket),
+ state_(state),
+ peer_(peer),
+ protocol_(protocol),
+ peer_endpoint_(peer_endpoint)
+ {
+ }
+
+ static bool do_perform(reactor_op* base)
+ {
+ reactive_socket_accept_op_base* o(
+ static_cast<reactive_socket_accept_op_base*>(base));
+
+ std::size_t addrlen = o->peer_endpoint_ ? o->peer_endpoint_->capacity() : 0;
+ socket_type new_socket = invalid_socket;
+ bool result = socket_ops::non_blocking_accept(o->socket_,
+ o->state_, o->peer_endpoint_ ? o->peer_endpoint_->data() : 0,
+ o->peer_endpoint_ ? &addrlen : 0, o->ec_, new_socket);
+
+ // On success, assign new connection to peer socket object.
+ if (new_socket >= 0)
+ {
+ socket_holder new_socket_holder(new_socket);
+ if (o->peer_endpoint_)
+ o->peer_endpoint_->resize(addrlen);
+ if (!o->peer_.assign(o->protocol_, new_socket, o->ec_))
+ new_socket_holder.release();
+ }
+
+ return result;
+ }
+
+private:
+ socket_type socket_;
+ socket_ops::state_type state_;
+ Socket& peer_;
+ Protocol protocol_;
+ typename Protocol::endpoint* peer_endpoint_;
+};
+
+template <typename Socket, typename Protocol, typename Handler>
+class reactive_socket_accept_op :
+ public reactive_socket_accept_op_base<Socket, Protocol>
+{
+public:
+ ASIO_DEFINE_HANDLER_PTR(reactive_socket_accept_op);
+
+ reactive_socket_accept_op(socket_type socket,
+ socket_ops::state_type state, Socket& peer, const Protocol& protocol,
+ typename Protocol::endpoint* peer_endpoint, Handler handler)
+ : reactive_socket_accept_op_base<Socket, Protocol>(socket, state, peer,
+ protocol, peer_endpoint, &reactive_socket_accept_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.
+ reactive_socket_accept_op* o(static_cast<reactive_socket_accept_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::binder1<Handler, asio::error_code>
+ handler(o->handler_, o->ec_);
+ 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 // ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP
diff --git a/ext/asio/asio/detail/reactive_socket_connect_op.hpp b/ext/asio/asio/detail/reactive_socket_connect_op.hpp
new file mode 100644
index 0000000000..8267091b21
--- /dev/null
+++ b/ext/asio/asio/detail/reactive_socket_connect_op.hpp
@@ -0,0 +1,101 @@
+//
+// detail/reactive_socket_connect_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_REACTIVE_SOCKET_CONNECT_OP_HPP
+#define ASIO_DETAIL_REACTIVE_SOCKET_CONNECT_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class reactive_socket_connect_op_base : public reactor_op
+{
+public:
+ reactive_socket_connect_op_base(socket_type socket, func_type complete_func)
+ : reactor_op(&reactive_socket_connect_op_base::do_perform, complete_func),
+ socket_(socket)
+ {
+ }
+
+ static bool do_perform(reactor_op* base)
+ {
+ reactive_socket_connect_op_base* o(
+ static_cast<reactive_socket_connect_op_base*>(base));
+
+ return socket_ops::non_blocking_connect(o->socket_, o->ec_);
+ }
+
+private:
+ socket_type socket_;
+};
+
+template <typename Handler>
+class reactive_socket_connect_op : public reactive_socket_connect_op_base
+{
+public:
+ ASIO_DEFINE_HANDLER_PTR(reactive_socket_connect_op);
+
+ reactive_socket_connect_op(socket_type socket, Handler handler)
+ : reactive_socket_connect_op_base(socket,
+ &reactive_socket_connect_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.
+ reactive_socket_connect_op* o
+ (static_cast<reactive_socket_connect_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::binder1<Handler, asio::error_code>
+ handler(o->handler_, o->ec_);
+ 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);
+ }
+ }
+
+private:
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_REACTIVE_SOCKET_CONNECT_OP_HPP
diff --git a/ext/asio/asio/detail/reactive_socket_recv_op.hpp b/ext/asio/asio/detail/reactive_socket_recv_op.hpp
new file mode 100644
index 0000000000..91a30a849e
--- /dev/null
+++ b/ext/asio/asio/detail/reactive_socket_recv_op.hpp
@@ -0,0 +1,118 @@
+//
+// detail/reactive_socket_recv_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_REACTIVE_SOCKET_RECV_OP_HPP
+#define ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence>
+class reactive_socket_recv_op_base : public reactor_op
+{
+public:
+ reactive_socket_recv_op_base(socket_type socket,
+ socket_ops::state_type state, const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op(&reactive_socket_recv_op_base::do_perform, complete_func),
+ socket_(socket),
+ state_(state),
+ buffers_(buffers),
+ flags_(flags)
+ {
+ }
+
+ static bool do_perform(reactor_op* base)
+ {
+ reactive_socket_recv_op_base* o(
+ static_cast<reactive_socket_recv_op_base*>(base));
+
+ buffer_sequence_adapter<asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ return socket_ops::non_blocking_recv(o->socket_,
+ bufs.buffers(), bufs.count(), o->flags_,
+ (o->state_ & socket_ops::stream_oriented),
+ o->ec_, o->bytes_transferred_);
+ }
+
+private:
+ socket_type socket_;
+ socket_ops::state_type state_;
+ MutableBufferSequence buffers_;
+ socket_base::message_flags flags_;
+};
+
+template <typename MutableBufferSequence, typename Handler>
+class reactive_socket_recv_op :
+ public reactive_socket_recv_op_base<MutableBufferSequence>
+{
+public:
+ ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op);
+
+ reactive_socket_recv_op(socket_type socket,
+ socket_ops::state_type state, const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, Handler handler)
+ : reactive_socket_recv_op_base<MutableBufferSequence>(socket, state,
+ buffers, flags, &reactive_socket_recv_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.
+ reactive_socket_recv_op* o(static_cast<reactive_socket_recv_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 // ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_HPP
diff --git a/ext/asio/asio/detail/reactive_socket_recvfrom_op.hpp b/ext/asio/asio/detail/reactive_socket_recvfrom_op.hpp
new file mode 100644
index 0000000000..121d6ecbd8
--- /dev/null
+++ b/ext/asio/asio/detail/reactive_socket_recvfrom_op.hpp
@@ -0,0 +1,128 @@
+//
+// detail/reactive_socket_recvfrom_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_REACTIVE_SOCKET_RECVFROM_OP_HPP
+#define ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence, typename Endpoint>
+class reactive_socket_recvfrom_op_base : public reactor_op
+{
+public:
+ reactive_socket_recvfrom_op_base(socket_type socket, int protocol_type,
+ const MutableBufferSequence& buffers, Endpoint& endpoint,
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op(&reactive_socket_recvfrom_op_base::do_perform, complete_func),
+ socket_(socket),
+ protocol_type_(protocol_type),
+ buffers_(buffers),
+ sender_endpoint_(endpoint),
+ flags_(flags)
+ {
+ }
+
+ static bool do_perform(reactor_op* base)
+ {
+ reactive_socket_recvfrom_op_base* o(
+ static_cast<reactive_socket_recvfrom_op_base*>(base));
+
+ buffer_sequence_adapter<asio::mutable_buffer,
+ MutableBufferSequence> bufs(o->buffers_);
+
+ std::size_t addr_len = o->sender_endpoint_.capacity();
+ bool result = socket_ops::non_blocking_recvfrom(o->socket_,
+ bufs.buffers(), bufs.count(), o->flags_,
+ o->sender_endpoint_.data(), &addr_len,
+ o->ec_, o->bytes_transferred_);
+
+ if (result && !o->ec_)
+ o->sender_endpoint_.resize(addr_len);
+
+ return result;
+ }
+
+private:
+ socket_type socket_;
+ int protocol_type_;
+ MutableBufferSequence buffers_;
+ Endpoint& sender_endpoint_;
+ socket_base::message_flags flags_;
+};
+
+template <typename MutableBufferSequence, typename Endpoint, typename Handler>
+class reactive_socket_recvfrom_op :
+ public reactive_socket_recvfrom_op_base<MutableBufferSequence, Endpoint>
+{
+public:
+ ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op);
+
+ reactive_socket_recvfrom_op(socket_type socket, int protocol_type,
+ const MutableBufferSequence& buffers, Endpoint& endpoint,
+ socket_base::message_flags flags, Handler handler)
+ : reactive_socket_recvfrom_op_base<MutableBufferSequence, Endpoint>(
+ socket, protocol_type, buffers, endpoint, flags,
+ &reactive_socket_recvfrom_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.
+ reactive_socket_recvfrom_op* o(
+ static_cast<reactive_socket_recvfrom_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 // ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_HPP
diff --git a/ext/asio/asio/detail/reactive_socket_send_op.hpp b/ext/asio/asio/detail/reactive_socket_send_op.hpp
new file mode 100644
index 0000000000..9a68dacccb
--- /dev/null
+++ b/ext/asio/asio/detail/reactive_socket_send_op.hpp
@@ -0,0 +1,115 @@
+//
+// detail/reactive_socket_send_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_REACTIVE_SOCKET_SEND_OP_HPP
+#define ASIO_DETAIL_REACTIVE_SOCKET_SEND_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename ConstBufferSequence>
+class reactive_socket_send_op_base : public reactor_op
+{
+public:
+ reactive_socket_send_op_base(socket_type socket,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op(&reactive_socket_send_op_base::do_perform, complete_func),
+ socket_(socket),
+ buffers_(buffers),
+ flags_(flags)
+ {
+ }
+
+ static bool do_perform(reactor_op* base)
+ {
+ reactive_socket_send_op_base* o(
+ static_cast<reactive_socket_send_op_base*>(base));
+
+ buffer_sequence_adapter<asio::const_buffer,
+ ConstBufferSequence> bufs(o->buffers_);
+
+ return socket_ops::non_blocking_send(o->socket_,
+ bufs.buffers(), bufs.count(), o->flags_,
+ o->ec_, o->bytes_transferred_);
+ }
+
+private:
+ socket_type socket_;
+ ConstBufferSequence buffers_;
+ socket_base::message_flags flags_;
+};
+
+template <typename ConstBufferSequence, typename Handler>
+class reactive_socket_send_op :
+ public reactive_socket_send_op_base<ConstBufferSequence>
+{
+public:
+ ASIO_DEFINE_HANDLER_PTR(reactive_socket_send_op);
+
+ reactive_socket_send_op(socket_type socket,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, Handler handler)
+ : reactive_socket_send_op_base<ConstBufferSequence>(socket,
+ buffers, flags, &reactive_socket_send_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.
+ reactive_socket_send_op* o(static_cast<reactive_socket_send_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 // ASIO_DETAIL_REACTIVE_SOCKET_SEND_OP_HPP
diff --git a/ext/asio/asio/detail/reactive_socket_sendto_op.hpp b/ext/asio/asio/detail/reactive_socket_sendto_op.hpp
new file mode 100644
index 0000000000..e466a2591e
--- /dev/null
+++ b/ext/asio/asio/detail/reactive_socket_sendto_op.hpp
@@ -0,0 +1,118 @@
+//
+// detail/reactive_socket_sendto_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_REACTIVE_SOCKET_SENDTO_OP_HPP
+#define ASIO_DETAIL_REACTIVE_SOCKET_SENDTO_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename ConstBufferSequence, typename Endpoint>
+class reactive_socket_sendto_op_base : public reactor_op
+{
+public:
+ reactive_socket_sendto_op_base(socket_type socket,
+ const ConstBufferSequence& buffers, const Endpoint& endpoint,
+ socket_base::message_flags flags, func_type complete_func)
+ : reactor_op(&reactive_socket_sendto_op_base::do_perform, complete_func),
+ socket_(socket),
+ buffers_(buffers),
+ destination_(endpoint),
+ flags_(flags)
+ {
+ }
+
+ static bool do_perform(reactor_op* base)
+ {
+ reactive_socket_sendto_op_base* o(
+ static_cast<reactive_socket_sendto_op_base*>(base));
+
+ buffer_sequence_adapter<asio::const_buffer,
+ ConstBufferSequence> bufs(o->buffers_);
+
+ return socket_ops::non_blocking_sendto(o->socket_,
+ bufs.buffers(), bufs.count(), o->flags_,
+ o->destination_.data(), o->destination_.size(),
+ o->ec_, o->bytes_transferred_);
+ }
+
+private:
+ socket_type socket_;
+ ConstBufferSequence buffers_;
+ Endpoint destination_;
+ socket_base::message_flags flags_;
+};
+
+template <typename ConstBufferSequence, typename Endpoint, typename Handler>
+class reactive_socket_sendto_op :
+ public reactive_socket_sendto_op_base<ConstBufferSequence, Endpoint>
+{
+public:
+ ASIO_DEFINE_HANDLER_PTR(reactive_socket_sendto_op);
+
+ reactive_socket_sendto_op(socket_type socket,
+ const ConstBufferSequence& buffers, const Endpoint& endpoint,
+ socket_base::message_flags flags, Handler handler)
+ : reactive_socket_sendto_op_base<ConstBufferSequence, Endpoint>(socket,
+ buffers, endpoint, flags, &reactive_socket_sendto_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.
+ reactive_socket_sendto_op* o(static_cast<reactive_socket_sendto_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 // ASIO_DETAIL_REACTIVE_SOCKET_SENDTO_OP_HPP
diff --git a/ext/asio/asio/detail/reactive_socket_service.hpp b/ext/asio/asio/detail/reactive_socket_service.hpp
index 20bd512ef6..daa9f607ad 100644
--- a/ext/asio/asio/detail/reactive_socket_service.hpp
+++ b/ext/asio/asio/detail/reactive_socket_service.hpp
@@ -1,8 +1,8 @@
//
-// reactive_socket_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/reactive_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,28 +15,37 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if !defined(ASIO_HAS_IOCP)
+#include <boost/utility/addressof.hpp>
#include "asio/buffer.hpp"
#include "asio/error.hpp"
#include "asio/io_service.hpp"
#include "asio/socket_base.hpp"
-#include "asio/detail/bind_handler.hpp"
#include "asio/detail/buffer_sequence_adapter.hpp"
-#include "asio/detail/fenced_block.hpp"
#include "asio/detail/noncopyable.hpp"
-#include "asio/detail/null_buffers_op.hpp"
+#include "asio/detail/reactive_null_buffers_op.hpp"
+#include "asio/detail/reactive_socket_accept_op.hpp"
+#include "asio/detail/reactive_socket_connect_op.hpp"
+#include "asio/detail/reactive_socket_recvfrom_op.hpp"
+#include "asio/detail/reactive_socket_sendto_op.hpp"
+#include "asio/detail/reactive_socket_service_base.hpp"
#include "asio/detail/reactor.hpp"
#include "asio/detail/reactor_op.hpp"
#include "asio/detail/socket_holder.hpp"
#include "asio/detail/socket_ops.hpp"
#include "asio/detail/socket_types.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
template <typename Protocol>
-class reactive_socket_service
+class reactive_socket_service :
+ public reactive_socket_service_base
{
public:
// The protocol type.
@@ -49,132 +58,32 @@ public:
typedef socket_type native_type;
// The implementation type of the socket.
- class implementation_type
- : private asio::detail::noncopyable
+ struct implementation_type :
+ reactive_socket_service_base::base_implementation_type
{
- public:
// Default constructor.
implementation_type()
- : socket_(invalid_socket),
- flags_(0),
- protocol_(endpoint_type().protocol())
+ : protocol_(endpoint_type().protocol())
{
}
- private:
- // Only this service will have access to the internal values.
- friend class reactive_socket_service<Protocol>;
-
- // The native socket representation.
- socket_type socket_;
-
- enum
- {
- // The user wants a non-blocking socket.
- user_set_non_blocking = 1,
-
- // The implementation wants a non-blocking socket (in order to be able to
- // perform asynchronous read and write operations).
- internal_non_blocking = 2,
-
- // Helper "flag" used to determine whether the socket is non-blocking.
- non_blocking = user_set_non_blocking | internal_non_blocking,
-
- // User wants connection_aborted errors, which are disabled by default.
- enable_connection_aborted = 4,
-
- // The user set the linger option. Needs to be checked when closing.
- user_set_linger = 8
- };
-
- // Flags indicating the current state of the socket.
- unsigned char flags_;
-
// The protocol associated with the socket.
protocol_type protocol_;
-
- // Per-descriptor data used by the reactor.
- reactor::per_descriptor_data reactor_data_;
};
// Constructor.
reactive_socket_service(asio::io_service& io_service)
- : io_service_impl_(use_service<io_service_impl>(io_service)),
- reactor_(use_service<reactor>(io_service))
- {
- reactor_.init_task();
- }
-
- // Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
- {
- }
-
- // Construct a new socket implementation.
- void construct(implementation_type& impl)
+ : reactive_socket_service_base(io_service)
{
- impl.socket_ = invalid_socket;
- impl.flags_ = 0;
- }
-
- // Destroy a socket implementation.
- void destroy(implementation_type& impl)
- {
- if (impl.socket_ != invalid_socket)
- {
- reactor_.close_descriptor(impl.socket_, impl.reactor_data_);
-
- if (impl.flags_ & implementation_type::non_blocking)
- {
- ioctl_arg_type non_blocking = 0;
- asio::error_code ignored_ec;
- socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec);
- impl.flags_ &= ~implementation_type::non_blocking;
- }
-
- if (impl.flags_ & implementation_type::user_set_linger)
- {
- ::linger opt;
- opt.l_onoff = 0;
- opt.l_linger = 0;
- asio::error_code ignored_ec;
- socket_ops::setsockopt(impl.socket_,
- SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec);
- }
-
- asio::error_code ignored_ec;
- socket_ops::close(impl.socket_, ignored_ec);
-
- impl.socket_ = invalid_socket;
- }
}
// Open a new socket implementation.
asio::error_code open(implementation_type& impl,
const protocol_type& protocol, asio::error_code& ec)
{
- if (is_open(impl))
- {
- ec = asio::error::already_open;
- return ec;
- }
-
- socket_holder sock(socket_ops::socket(protocol.family(),
- protocol.type(), protocol.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();
- impl.flags_ = 0;
- impl.protocol_ = protocol;
- ec = asio::error_code();
+ if (!do_open(impl, protocol.family(),
+ protocol.type(), protocol.protocol(), ec))
+ impl.protocol_ = protocol;
return ec;
}
@@ -183,56 +92,8 @@ public:
const protocol_type& protocol, const 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;
- impl.flags_ = 0;
- impl.protocol_ = protocol;
- ec = asio::error_code();
- return ec;
- }
-
- // Determine whether the socket is open.
- bool is_open(const implementation_type& impl) const
- {
- return impl.socket_ != invalid_socket;
- }
-
- // Destroy a socket implementation.
- asio::error_code close(implementation_type& impl,
- asio::error_code& ec)
- {
- if (is_open(impl))
- {
- reactor_.close_descriptor(impl.socket_, impl.reactor_data_);
-
- if (impl.flags_ & implementation_type::non_blocking)
- {
- ioctl_arg_type non_blocking = 0;
- asio::error_code ignored_ec;
- socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec);
- impl.flags_ &= ~implementation_type::non_blocking;
- }
-
- if (socket_ops::close(impl.socket_, ec) == socket_error_retval)
- return ec;
-
- impl.socket_ = invalid_socket;
- }
-
- ec = asio::error_code();
+ if (!do_assign(impl, protocol.type(), native_socket, ec))
+ impl.protocol_ = protocol;
return ec;
}
@@ -242,153 +103,23 @@ public:
return impl.socket_;
}
- // Cancel all operations associated with the socket.
- asio::error_code cancel(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;
- }
-
- // Determine whether the socket is at the out-of-band data mark.
- bool at_mark(const implementation_type& impl,
- asio::error_code& ec) const
- {
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return false;
- }
-
-#if defined(SIOCATMARK)
- asio::detail::ioctl_arg_type value = 0;
- socket_ops::ioctl(impl.socket_, SIOCATMARK, &value, ec);
-# if defined(ENOTTY)
- if (ec.value() == ENOTTY)
- ec = asio::error::not_socket;
-# endif // defined(ENOTTY)
-#else // defined(SIOCATMARK)
- int value = sockatmark(impl.socket_);
- if (value == -1)
- ec = asio::error_code(errno,
- asio::error::get_system_category());
- else
- ec = asio::error_code();
-#endif // defined(SIOCATMARK)
- return ec ? false : value != 0;
- }
-
- // Determine the number of bytes available for reading.
- std::size_t available(const implementation_type& impl,
- asio::error_code& ec) const
- {
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
- asio::detail::ioctl_arg_type value = 0;
- socket_ops::ioctl(impl.socket_, FIONREAD, &value, ec);
-#if defined(ENOTTY)
- if (ec.value() == ENOTTY)
- ec = asio::error::not_socket;
-#endif // defined(ENOTTY)
- return ec ? static_cast<std::size_t>(0) : static_cast<std::size_t>(value);
- }
-
// Bind the socket to the specified local endpoint.
asio::error_code bind(implementation_type& impl,
const endpoint_type& endpoint, asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return ec;
- }
-
socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
return ec;
}
- // Place the socket into the state where it will listen for new connections.
- asio::error_code listen(implementation_type& impl, int backlog,
- asio::error_code& ec)
- {
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return ec;
- }
-
- socket_ops::listen(impl.socket_, backlog, ec);
- return ec;
- }
-
// Set a socket option.
template <typename Option>
asio::error_code set_option(implementation_type& impl,
const Option& option, asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return ec;
- }
-
- if (option.level(impl.protocol_) == custom_socket_option_level
- && option.name(impl.protocol_) == enable_connection_aborted_option)
- {
- if (option.size(impl.protocol_) != sizeof(int))
- {
- ec = asio::error::invalid_argument;
- }
- else
- {
- if (*reinterpret_cast<const int*>(option.data(impl.protocol_)))
- impl.flags_ |= implementation_type::enable_connection_aborted;
- else
- impl.flags_ &= ~implementation_type::enable_connection_aborted;
- ec = asio::error_code();
- }
- return ec;
- }
- else
- {
- if (option.level(impl.protocol_) == SOL_SOCKET
- && option.name(impl.protocol_) == SO_LINGER)
- {
- impl.flags_ |= implementation_type::user_set_linger;
- }
-
- socket_ops::setsockopt(impl.socket_,
- option.level(impl.protocol_), option.name(impl.protocol_),
- option.data(impl.protocol_), option.size(impl.protocol_), ec);
-
-#if defined(__MACH__) && defined(__APPLE__) \
-|| defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
- // To implement portable behaviour for SO_REUSEADDR with UDP sockets we
- // need to also set SO_REUSEPORT on BSD-based platforms.
- if (!ec && impl.protocol_.type() == SOCK_DGRAM
- && option.level(impl.protocol_) == SOL_SOCKET
- && option.name(impl.protocol_) == SO_REUSEADDR)
- {
- asio::error_code ignored_ec;
- socket_ops::setsockopt(impl.socket_, SOL_SOCKET, SO_REUSEPORT,
- option.data(impl.protocol_), option.size(impl.protocol_),
- ignored_ec);
- }
-#endif
-
- return ec;
- }
+ socket_ops::setsockopt(impl.socket_, impl.state_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), option.size(impl.protocol_), ec);
+ return ec;
}
// Set a socket option.
@@ -396,78 +127,12 @@ public:
asio::error_code get_option(const implementation_type& impl,
Option& option, asio::error_code& ec) const
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return ec;
- }
-
- if (option.level(impl.protocol_) == custom_socket_option_level
- && option.name(impl.protocol_) == enable_connection_aborted_option)
- {
- if (option.size(impl.protocol_) != sizeof(int))
- {
- ec = asio::error::invalid_argument;
- }
- else
- {
- int* target = reinterpret_cast<int*>(option.data(impl.protocol_));
- if (impl.flags_ & implementation_type::enable_connection_aborted)
- *target = 1;
- else
- *target = 0;
- option.resize(impl.protocol_, sizeof(int));
- ec = asio::error_code();
- }
- return ec;
- }
- else
- {
- size_t size = option.size(impl.protocol_);
- socket_ops::getsockopt(impl.socket_,
- option.level(impl.protocol_), option.name(impl.protocol_),
- option.data(impl.protocol_), &size, ec);
- if (!ec)
- option.resize(impl.protocol_, size);
- return ec;
- }
- }
-
- // Perform an IO control command on the socket.
- template <typename IO_Control_Command>
- asio::error_code io_control(implementation_type& impl,
- IO_Control_Command& command, asio::error_code& ec)
- {
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return ec;
- }
-
- socket_ops::ioctl(impl.socket_, command.name(),
- static_cast<ioctl_arg_type*>(command.data()), ec);
-
- // When updating the non-blocking mode we always perform the ioctl
- // syscall, even if the flags would otherwise indicate that the socket is
- // already in the correct state. This ensures that the underlying socket
- // 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 (!ec && command.name() == static_cast<int>(FIONBIO))
- {
- if (*static_cast<ioctl_arg_type*>(command.data()))
- {
- impl.flags_ |= implementation_type::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.
- impl.flags_ &= ~(implementation_type::user_set_non_blocking
- | implementation_type::internal_non_blocking);
- }
- }
-
+ std::size_t size = option.size(impl.protocol_);
+ socket_ops::getsockopt(impl.socket_, impl.state_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), &size, ec);
+ if (!ec)
+ option.resize(impl.protocol_, size);
return ec;
}
@@ -475,12 +140,6 @@ public:
endpoint_type local_endpoint(const implementation_type& impl,
asio::error_code& ec) const
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return endpoint_type();
- }
-
endpoint_type endpoint;
std::size_t addr_len = endpoint.capacity();
if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
@@ -493,218 +152,15 @@ public:
endpoint_type remote_endpoint(const implementation_type& impl,
asio::error_code& ec) const
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return endpoint_type();
- }
-
endpoint_type endpoint;
std::size_t addr_len = endpoint.capacity();
- if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec))
+ if (socket_ops::getpeername(impl.socket_,
+ endpoint.data(), &addr_len, false, ec))
return endpoint_type();
endpoint.resize(addr_len);
return endpoint;
}
- /// Disable sends or receives on the socket.
- asio::error_code shutdown(implementation_type& impl,
- socket_base::shutdown_type what, asio::error_code& ec)
- {
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return ec;
- }
-
- socket_ops::shutdown(impl.socket_, what, ec);
- return ec;
- }
-
- // Send the given data to the peer.
- template <typename ConstBufferSequence>
- size_t send(implementation_type& impl, const ConstBufferSequence& buffers,
- socket_base::message_flags flags, asio::error_code& ec)
- {
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
- buffer_sequence_adapter<asio::const_buffer,
- ConstBufferSequence> bufs(buffers);
-
- // A request to receive 0 bytes on a stream socket is a no-op.
- if (impl.protocol_.type() == SOCK_STREAM && bufs.all_empty())
- {
- ec = asio::error_code();
- return 0;
- }
-
- // Send the data.
- for (;;)
- {
- // Try to complete the operation without blocking.
- int bytes_sent = socket_ops::send(impl.socket_,
- bufs.buffers(), bufs.count(), flags, ec);
-
- // Check if operation succeeded.
- if (bytes_sent >= 0)
- return bytes_sent;
-
- // Operation failed.
- if ((impl.flags_ & implementation_type::user_set_non_blocking)
- || (ec != asio::error::would_block
- && ec != asio::error::try_again))
- return 0;
-
- // Wait for socket to become ready.
- if (socket_ops::poll_write(impl.socket_, ec) < 0)
- return 0;
- }
- }
-
- // Wait until data can be sent without blocking.
- size_t send(implementation_type& impl, const null_buffers&,
- socket_base::message_flags, asio::error_code& ec)
- {
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
- // Wait for socket to become ready.
- socket_ops::poll_write(impl.socket_, ec);
-
- return 0;
- }
-
- template <typename ConstBufferSequence>
- class send_op_base : public reactor_op
- {
- public:
- send_op_base(socket_type socket, const ConstBufferSequence& buffers,
- socket_base::message_flags flags, func_type complete_func)
- : reactor_op(&send_op_base::do_perform, complete_func),
- socket_(socket),
- buffers_(buffers),
- flags_(flags)
- {
- }
-
- static bool do_perform(reactor_op* base)
- {
- send_op_base* o(static_cast<send_op_base*>(base));
-
- buffer_sequence_adapter<asio::const_buffer,
- ConstBufferSequence> bufs(o->buffers_);
-
- for (;;)
- {
- // Send the data.
- asio::error_code ec;
- int bytes = socket_ops::send(o->socket_,
- bufs.buffers(), bufs.count(), o->flags_, 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;
-
- o->ec_ = ec;
- o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);
- return true;
- }
- }
-
- private:
- socket_type socket_;
- ConstBufferSequence buffers_;
- socket_base::message_flags flags_;
- };
-
- template <typename ConstBufferSequence, typename Handler>
- class send_op : public send_op_base<ConstBufferSequence>
- {
- public:
- send_op(socket_type socket, const ConstBufferSequence& buffers,
- socket_base::message_flags flags, Handler handler)
- : send_op_base<ConstBufferSequence>(socket,
- buffers, flags, &send_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.
- send_op* o(static_cast<send_op*>(base));
- typedef handler_alloc_traits<Handler, send_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- // 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::binder2<Handler, asio::error_code, std::size_t>
- handler(o->handler_, o->ec_, o->bytes_transferred_);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
- }
-
- private:
- Handler handler_;
- };
-
- // Start an asynchronous send. The data being sent must be valid for the
- // lifetime of the asynchronous operation.
- template <typename ConstBufferSequence, typename Handler>
- void async_send(implementation_type& impl, const ConstBufferSequence& buffers,
- socket_base::message_flags flags, Handler handler)
- {
- // Allocate and construct an operation to wrap the handler.
- typedef send_op<ConstBufferSequence, 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,
- impl.socket_, buffers, flags, handler);
-
- start_op(impl, reactor::write_op, ptr.get(), true,
- (impl.protocol_.type() == SOCK_STREAM
- && buffer_sequence_adapter<asio::const_buffer,
- ConstBufferSequence>::all_empty(buffers)));
- ptr.release();
- }
-
- // Start an asynchronous wait until data can be sent without blocking.
- template <typename Handler>
- void async_send(implementation_type& impl, const null_buffers&,
- socket_base::message_flags, Handler handler)
- {
- // Allocate and construct an operation to wrap the handler.
- typedef null_buffers_op<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);
-
- start_op(impl, reactor::write_op, ptr.get(), false, false);
- ptr.release();
- }
-
// Send a datagram to the specified endpoint. Returns the number of bytes
// sent.
template <typename ConstBufferSequence>
@@ -712,148 +168,25 @@ public:
const endpoint_type& destination, socket_base::message_flags flags,
asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
buffer_sequence_adapter<asio::const_buffer,
ConstBufferSequence> bufs(buffers);
- // Send the data.
- for (;;)
- {
- // Try to complete the operation without blocking.
- int bytes_sent = socket_ops::sendto(impl.socket_, bufs.buffers(),
- bufs.count(), flags, destination.data(), destination.size(), ec);
-
- // Check if operation succeeded.
- if (bytes_sent >= 0)
- return bytes_sent;
-
- // Operation failed.
- if ((impl.flags_ & implementation_type::user_set_non_blocking)
- || (ec != asio::error::would_block
- && ec != asio::error::try_again))
- return 0;
-
- // Wait for socket to become ready.
- if (socket_ops::poll_write(impl.socket_, ec) < 0)
- return 0;
- }
+ return socket_ops::sync_sendto(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags,
+ destination.data(), destination.size(), ec);
}
// Wait until data can be sent without blocking.
size_t send_to(implementation_type& impl, const null_buffers&,
- socket_base::message_flags, const endpoint_type&,
+ const endpoint_type&, socket_base::message_flags,
asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
// Wait for socket to become ready.
socket_ops::poll_write(impl.socket_, ec);
return 0;
}
- template <typename ConstBufferSequence>
- class send_to_op_base : public reactor_op
- {
- public:
- send_to_op_base(socket_type socket, const ConstBufferSequence& buffers,
- const endpoint_type& endpoint, socket_base::message_flags flags,
- func_type complete_func)
- : reactor_op(&send_to_op_base::do_perform, complete_func),
- socket_(socket),
- buffers_(buffers),
- destination_(endpoint),
- flags_(flags)
- {
- }
-
- static bool do_perform(reactor_op* base)
- {
- send_to_op_base* o(static_cast<send_to_op_base*>(base));
-
- buffer_sequence_adapter<asio::const_buffer,
- ConstBufferSequence> bufs(o->buffers_);
-
- for (;;)
- {
- // Send the data.
- asio::error_code ec;
- int bytes = socket_ops::sendto(o->socket_, bufs.buffers(), bufs.count(),
- o->flags_, o->destination_.data(), o->destination_.size(), 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;
-
- o->ec_ = ec;
- o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);
- return true;
- }
- }
-
- private:
- socket_type socket_;
- ConstBufferSequence buffers_;
- endpoint_type destination_;
- socket_base::message_flags flags_;
- };
-
- template <typename ConstBufferSequence, typename Handler>
- class send_to_op : public send_to_op_base<ConstBufferSequence>
- {
- public:
- send_to_op(socket_type socket, const ConstBufferSequence& buffers,
- const endpoint_type& endpoint, socket_base::message_flags flags,
- Handler handler)
- : send_to_op_base<ConstBufferSequence>(socket,
- buffers, endpoint, flags, &send_to_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.
- send_to_op* o(static_cast<send_to_op*>(base));
- typedef handler_alloc_traits<Handler, send_to_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- // 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::binder2<Handler, asio::error_code, std::size_t>
- handler(o->handler_, o->ec_, o->bytes_transferred_);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
- }
-
- private:
- Handler handler_;
- };
-
// Start an asynchronous send. The data being sent must be valid for the
// lifetime of the asynchronous operation.
template <typename ConstBufferSequence, typename Handler>
@@ -863,235 +196,31 @@ public:
Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef send_to_op<ConstBufferSequence, 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, impl.socket_,
- buffers, destination, flags, handler);
+ typedef reactive_socket_sendto_op<ConstBufferSequence,
+ endpoint_type, Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.socket_, buffers, destination, flags, handler);
- start_op(impl, reactor::write_op, ptr.get(), true, false);
- ptr.release();
+ start_op(impl, reactor::write_op, p.p, true, false);
+ p.v = p.p = 0;
}
// Start an asynchronous wait until data can be sent without blocking.
template <typename Handler>
void async_send_to(implementation_type& impl, const null_buffers&,
- socket_base::message_flags, const endpoint_type&, Handler handler)
+ const endpoint_type&, socket_base::message_flags, Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef null_buffers_op<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);
-
- start_op(impl, reactor::write_op, ptr.get(), false, false);
- ptr.release();
- }
-
- // Receive some data from the peer. Returns the number of bytes received.
- template <typename MutableBufferSequence>
- size_t receive(implementation_type& impl,
- const MutableBufferSequence& buffers,
- socket_base::message_flags flags, asio::error_code& ec)
- {
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
- buffer_sequence_adapter<asio::mutable_buffer,
- MutableBufferSequence> bufs(buffers);
-
- // A request to receive 0 bytes on a stream socket is a no-op.
- if (impl.protocol_.type() == SOCK_STREAM && bufs.all_empty())
- {
- ec = asio::error_code();
- return 0;
- }
-
- // Receive some data.
- for (;;)
- {
- // Try to complete the operation without blocking.
- int bytes_recvd = socket_ops::recv(impl.socket_,
- bufs.buffers(), bufs.count(), flags, ec);
-
- // Check if operation succeeded.
- if (bytes_recvd > 0)
- return bytes_recvd;
-
- // Check for EOF.
- if (bytes_recvd == 0 && impl.protocol_.type() == SOCK_STREAM)
- {
- ec = asio::error::eof;
- return 0;
- }
-
- // Operation failed.
- if ((impl.flags_ & implementation_type::user_set_non_blocking)
- || (ec != asio::error::would_block
- && ec != asio::error::try_again))
- return 0;
-
- // Wait for socket to become ready.
- if (socket_ops::poll_read(impl.socket_, ec) < 0)
- return 0;
- }
- }
-
- // Wait until data can be received without blocking.
- size_t receive(implementation_type& impl, const null_buffers&,
- socket_base::message_flags, asio::error_code& ec)
- {
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
- // Wait for socket to become ready.
- socket_ops::poll_read(impl.socket_, ec);
+ typedef reactive_null_buffers_op<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);
- return 0;
- }
-
- template <typename MutableBufferSequence>
- class receive_op_base : public reactor_op
- {
- public:
- receive_op_base(socket_type socket, int protocol_type,
- const MutableBufferSequence& buffers,
- socket_base::message_flags flags, func_type complete_func)
- : reactor_op(&receive_op_base::do_perform, complete_func),
- socket_(socket),
- protocol_type_(protocol_type),
- buffers_(buffers),
- flags_(flags)
- {
- }
-
- static bool do_perform(reactor_op* base)
- {
- receive_op_base* o(static_cast<receive_op_base*>(base));
-
- buffer_sequence_adapter<asio::mutable_buffer,
- MutableBufferSequence> bufs(o->buffers_);
-
- for (;;)
- {
- // Receive some data.
- asio::error_code ec;
- int bytes = socket_ops::recv(o->socket_,
- bufs.buffers(), bufs.count(), o->flags_, ec);
- if (bytes == 0 && o->protocol_type_ == SOCK_STREAM)
- ec = asio::error::eof;
-
- // 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;
-
- o->ec_ = ec;
- o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);
- return true;
- }
- }
-
- private:
- socket_type socket_;
- int protocol_type_;
- MutableBufferSequence buffers_;
- socket_base::message_flags flags_;
- };
-
- template <typename MutableBufferSequence, typename Handler>
- class receive_op : public receive_op_base<MutableBufferSequence>
- {
- public:
- receive_op(socket_type socket, int protocol_type,
- const MutableBufferSequence& buffers,
- socket_base::message_flags flags, Handler handler)
- : receive_op_base<MutableBufferSequence>(socket,
- protocol_type, buffers, flags, &receive_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.
- receive_op* o(static_cast<receive_op*>(base));
- typedef handler_alloc_traits<Handler, receive_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- // 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::binder2<Handler, asio::error_code, std::size_t>
- handler(o->handler_, o->ec_, o->bytes_transferred_);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
- }
-
- private:
- Handler handler_;
- };
-
- // Start an asynchronous receive. The buffer for the data being received
- // must be valid for the lifetime of the asynchronous operation.
- template <typename MutableBufferSequence, typename Handler>
- void async_receive(implementation_type& impl,
- const MutableBufferSequence& buffers,
- socket_base::message_flags flags, Handler handler)
- {
- // Allocate and construct an operation to wrap the handler.
- typedef receive_op<MutableBufferSequence, Handler> value_type;
- typedef handler_alloc_traits<Handler, value_type> alloc_traits;
- raw_handler_ptr<alloc_traits> raw_ptr(handler);
- int protocol_type = impl.protocol_.type();
- handler_ptr<alloc_traits> ptr(raw_ptr, impl.socket_,
- protocol_type, buffers, flags, handler);
-
- start_op(impl,
- (flags & socket_base::message_out_of_band)
- ? reactor::except_op : reactor::read_op,
- ptr.get(), (flags & socket_base::message_out_of_band) == 0,
- (impl.protocol_.type() == SOCK_STREAM
- && buffer_sequence_adapter<asio::mutable_buffer,
- MutableBufferSequence>::all_empty(buffers)));
- ptr.release();
- }
-
- // Wait until data can be received without blocking.
- template <typename Handler>
- void async_receive(implementation_type& impl, const null_buffers&,
- socket_base::message_flags flags, Handler handler)
- {
- // Allocate and construct an operation to wrap the handler.
- typedef null_buffers_op<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);
-
- start_op(impl,
- (flags & socket_base::message_out_of_band)
- ? reactor::except_op : reactor::read_op,
- ptr.get(), false, false);
- ptr.release();
+ start_op(impl, reactor::write_op, p.p, false, false);
+ p.v = p.p = 0;
}
// Receive a datagram with the endpoint of the sender. Returns the number of
@@ -1102,47 +231,18 @@ public:
endpoint_type& sender_endpoint, socket_base::message_flags flags,
asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
buffer_sequence_adapter<asio::mutable_buffer,
MutableBufferSequence> bufs(buffers);
- // Receive some data.
- for (;;)
- {
- // Try to complete the operation without blocking.
- std::size_t addr_len = sender_endpoint.capacity();
- int bytes_recvd = socket_ops::recvfrom(impl.socket_, bufs.buffers(),
- bufs.count(), flags, sender_endpoint.data(), &addr_len, ec);
+ std::size_t addr_len = sender_endpoint.capacity();
+ std::size_t bytes_recvd = socket_ops::sync_recvfrom(
+ impl.socket_, impl.state_, bufs.buffers(), bufs.count(),
+ flags, sender_endpoint.data(), &addr_len, ec);
- // Check if operation succeeded.
- if (bytes_recvd > 0)
- {
- sender_endpoint.resize(addr_len);
- return bytes_recvd;
- }
+ if (!ec)
+ sender_endpoint.resize(addr_len);
- // Check for EOF.
- if (bytes_recvd == 0 && impl.protocol_.type() == SOCK_STREAM)
- {
- ec = asio::error::eof;
- return 0;
- }
-
- // Operation failed.
- if ((impl.flags_ & implementation_type::user_set_non_blocking)
- || (ec != asio::error::would_block
- && ec != asio::error::try_again))
- return 0;
-
- // Wait for socket to become ready.
- if (socket_ops::poll_read(impl.socket_, ec) < 0)
- return 0;
- }
+ return bytes_recvd;
}
// Wait until data can be received without blocking.
@@ -1150,12 +250,6 @@ public:
endpoint_type& sender_endpoint, socket_base::message_flags,
asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
// Wait for socket to become ready.
socket_ops::poll_read(impl.socket_, ec);
@@ -1165,105 +259,6 @@ public:
return 0;
}
- template <typename MutableBufferSequence>
- class receive_from_op_base : public reactor_op
- {
- public:
- receive_from_op_base(socket_type socket, int protocol_type,
- const MutableBufferSequence& buffers, endpoint_type& endpoint,
- socket_base::message_flags flags, func_type complete_func)
- : reactor_op(&receive_from_op_base::do_perform, complete_func),
- socket_(socket),
- protocol_type_(protocol_type),
- buffers_(buffers),
- sender_endpoint_(endpoint),
- flags_(flags)
- {
- }
-
- static bool do_perform(reactor_op* base)
- {
- receive_from_op_base* o(static_cast<receive_from_op_base*>(base));
-
- buffer_sequence_adapter<asio::mutable_buffer,
- MutableBufferSequence> bufs(o->buffers_);
-
- for (;;)
- {
- // Receive some data.
- asio::error_code ec;
- std::size_t addr_len = o->sender_endpoint_.capacity();
- int bytes = socket_ops::recvfrom(o->socket_, bufs.buffers(),
- bufs.count(), o->flags_, o->sender_endpoint_.data(), &addr_len, ec);
- if (bytes == 0 && o->protocol_type_ == SOCK_STREAM)
- ec = asio::error::eof;
-
- // 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;
-
- o->sender_endpoint_.resize(addr_len);
- o->ec_ = ec;
- o->bytes_transferred_ = (bytes < 0 ? 0 : bytes);
- return true;
- }
- }
-
- private:
- socket_type socket_;
- int protocol_type_;
- MutableBufferSequence buffers_;
- endpoint_type& sender_endpoint_;
- socket_base::message_flags flags_;
- };
-
- template <typename MutableBufferSequence, typename Handler>
- class receive_from_op : public receive_from_op_base<MutableBufferSequence>
- {
- public:
- receive_from_op(socket_type socket, int protocol_type,
- const MutableBufferSequence& buffers, endpoint_type& endpoint,
- socket_base::message_flags flags, Handler handler)
- : receive_from_op_base<MutableBufferSequence>(socket, protocol_type,
- buffers, endpoint, flags, &receive_from_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.
- receive_from_op* o(static_cast<receive_from_op*>(base));
- typedef handler_alloc_traits<Handler, receive_from_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- // 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::binder2<Handler, asio::error_code, std::size_t>
- handler(o->handler_, o->ec_, o->bytes_transferred_);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
- }
-
- private:
- Handler handler_;
- };
-
// Start an asynchronous receive. The buffer for the data being received and
// the sender_endpoint object must both be valid for the lifetime of the
// asynchronous operation.
@@ -1273,18 +268,20 @@ public:
socket_base::message_flags flags, Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef receive_from_op<MutableBufferSequence, Handler> value_type;
- typedef handler_alloc_traits<Handler, value_type> alloc_traits;
- raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ typedef reactive_socket_recvfrom_op<MutableBufferSequence,
+ endpoint_type, Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
int protocol_type = impl.protocol_.type();
- handler_ptr<alloc_traits> ptr(raw_ptr, impl.socket_,
- protocol_type, buffers, sender_endpoint, flags, handler);
+ p.p = new (p.v) op(impl.socket_, protocol_type,
+ buffers, sender_endpoint, flags, handler);
start_op(impl,
(flags & socket_base::message_out_of_band)
? reactor::except_op : reactor::read_op,
- ptr.get(), true, false);
- ptr.release();
+ p.p, true, false);
+ p.v = p.p = 0;
}
// Wait until data can be received without blocking.
@@ -1294,10 +291,11 @@ public:
socket_base::message_flags flags, Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef null_buffers_op<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 reactive_null_buffers_op<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);
// Reset endpoint since it can be given no sensible value at this time.
sender_endpoint = endpoint_type();
@@ -1305,8 +303,8 @@ public:
start_op(impl,
(flags & socket_base::message_out_of_band)
? reactor::except_op : reactor::read_op,
- ptr.get(), false, false);
- ptr.release();
+ p.p, false, false);
+ p.v = p.p = 0;
}
// Accept a new connection.
@@ -1314,12 +312,6 @@ public:
asio::error_code accept(implementation_type& impl,
Socket& peer, endpoint_type* peer_endpoint, asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return ec;
- }
-
// We cannot accept a socket that is already open.
if (peer.is_open())
{
@@ -1327,181 +319,22 @@ public:
return ec;
}
- // Accept a socket.
- for (;;)
- {
- // Try to complete the operation without blocking.
- socket_holder new_socket;
- std::size_t addr_len = 0;
- if (peer_endpoint)
- {
- addr_len = peer_endpoint->capacity();
- new_socket.reset(socket_ops::accept(impl.socket_,
- peer_endpoint->data(), &addr_len, ec));
- }
- else
- {
- new_socket.reset(socket_ops::accept(impl.socket_, 0, 0, ec));
- }
-
- // Check if operation succeeded.
- if (new_socket.get() >= 0)
- {
- if (peer_endpoint)
- peer_endpoint->resize(addr_len);
- peer.assign(impl.protocol_, new_socket.get(), ec);
- if (!ec)
- new_socket.release();
- return ec;
- }
+ std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
+ socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
+ impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
+ peer_endpoint ? &addr_len : 0, ec));
- // Operation failed.
- if (ec == asio::error::would_block
- || ec == asio::error::try_again)
- {
- if (impl.flags_ & implementation_type::user_set_non_blocking)
- return ec;
- // Fall through to retry operation.
- }
- else if (ec == asio::error::connection_aborted)
- {
- if (impl.flags_ & implementation_type::enable_connection_aborted)
- return ec;
- // Fall through to retry operation.
- }
-#if defined(EPROTO)
- else if (ec.value() == EPROTO)
- {
- if (impl.flags_ & implementation_type::enable_connection_aborted)
- return ec;
- // Fall through to retry operation.
- }
-#endif // defined(EPROTO)
- else
- return ec;
-
- // Wait for socket to become ready.
- if (socket_ops::poll_read(impl.socket_, ec) < 0)
- return ec;
- }
- }
-
- template <typename Socket>
- class accept_op_base : public reactor_op
- {
- public:
- accept_op_base(socket_type socket, Socket& peer,
- const protocol_type& protocol, endpoint_type* peer_endpoint,
- bool enable_connection_aborted, func_type complete_func)
- : reactor_op(&accept_op_base::do_perform, complete_func),
- socket_(socket),
- peer_(peer),
- protocol_(protocol),
- peer_endpoint_(peer_endpoint),
- enable_connection_aborted_(enable_connection_aborted)
- {
- }
-
- static bool do_perform(reactor_op* base)
+ // On success, assign new connection to peer socket object.
+ if (new_socket.get() != invalid_socket)
{
- accept_op_base* o(static_cast<accept_op_base*>(base));
-
- for (;;)
- {
- // Accept the waiting connection.
- asio::error_code ec;
- socket_holder new_socket;
- std::size_t addr_len = 0;
- std::size_t* addr_len_p = 0;
- socket_addr_type* addr = 0;
- if (o->peer_endpoint_)
- {
- addr_len = o->peer_endpoint_->capacity();
- addr_len_p = &addr_len;
- addr = o->peer_endpoint_->data();
- }
- new_socket.reset(socket_ops::accept(o->socket_, addr, addr_len_p, 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;
- if (ec == asio::error::connection_aborted
- && !o->enable_connection_aborted_)
- return false;
-#if defined(EPROTO)
- if (ec.value() == EPROTO && !o->enable_connection_aborted_)
- return false;
-#endif // defined(EPROTO)
-
- // Transfer ownership of the new socket to the peer object.
- if (!ec)
- {
- if (o->peer_endpoint_)
- o->peer_endpoint_->resize(addr_len);
- o->peer_.assign(o->protocol_, new_socket.get(), ec);
- if (!ec)
- new_socket.release();
- }
-
- o->ec_ = ec;
- return true;
- }
- }
-
- private:
- socket_type socket_;
- Socket& peer_;
- protocol_type protocol_;
- endpoint_type* peer_endpoint_;
- bool enable_connection_aborted_;
- };
-
- template <typename Socket, typename Handler>
- class accept_op : public accept_op_base<Socket>
- {
- public:
- accept_op(socket_type socket, Socket& peer, const protocol_type& protocol,
- endpoint_type* peer_endpoint, bool enable_connection_aborted,
- Handler handler)
- : accept_op_base<Socket>(socket, peer, protocol, peer_endpoint,
- enable_connection_aborted, &accept_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.
- accept_op* o(static_cast<accept_op*>(base));
- typedef handler_alloc_traits<Handler, accept_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- // 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(o->handler_, o->ec_);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
+ if (peer_endpoint)
+ peer_endpoint->resize(addr_len);
+ if (!peer.assign(impl.protocol_, new_socket.get(), ec))
+ new_socket.release();
}
- private:
- Handler handler_;
- };
+ return ec;
+ }
// Start an asynchronous accept. The peer and peer_endpoint objects
// must be valid until the accept's handler is invoked.
@@ -1510,230 +343,41 @@ public:
endpoint_type* peer_endpoint, Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef accept_op<Socket, Handler> value_type;
- typedef handler_alloc_traits<Handler, value_type> alloc_traits;
- raw_handler_ptr<alloc_traits> raw_ptr(handler);
- bool enable_connection_aborted =
- (impl.flags_ & implementation_type::enable_connection_aborted) != 0;
- handler_ptr<alloc_traits> ptr(raw_ptr, impl.socket_, peer,
- impl.protocol_, peer_endpoint, enable_connection_aborted, handler);
+ typedef reactive_socket_accept_op<Socket, Protocol, Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_, peer,
+ impl.protocol_, peer_endpoint, handler);
- start_accept_op(impl, ptr.get(), peer.is_open());
- ptr.release();
+ start_accept_op(impl, p.p, peer.is_open());
+ p.v = p.p = 0;
}
// Connect the socket to the specified endpoint.
asio::error_code connect(implementation_type& impl,
const endpoint_type& peer_endpoint, asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return ec;
- }
-
- // Perform the connect operation.
- socket_ops::connect(impl.socket_,
+ socket_ops::sync_connect(impl.socket_,
peer_endpoint.data(), peer_endpoint.size(), ec);
- if (ec != asio::error::in_progress
- && ec != asio::error::would_block)
- {
- // The connect operation finished immediately.
- return ec;
- }
-
- // Wait for socket to become ready.
- if (socket_ops::poll_connect(impl.socket_, ec) < 0)
- return ec;
-
- // Get the error code from the connect operation.
- int connect_error = 0;
- size_t connect_error_len = sizeof(connect_error);
- if (socket_ops::getsockopt(impl.socket_, SOL_SOCKET, SO_ERROR,
- &connect_error, &connect_error_len, ec) == socket_error_retval)
- return ec;
-
- // Return the result of the connect operation.
- ec = asio::error_code(connect_error,
- asio::error::get_system_category());
return ec;
}
- class connect_op_base : public reactor_op
- {
- public:
- connect_op_base(socket_type socket, func_type complete_func)
- : reactor_op(&connect_op_base::do_perform, complete_func),
- socket_(socket)
- {
- }
-
- static bool do_perform(reactor_op* base)
- {
- connect_op_base* o(static_cast<connect_op_base*>(base));
-
- // Get the error code from the connect operation.
- int connect_error = 0;
- size_t connect_error_len = sizeof(connect_error);
- if (socket_ops::getsockopt(o->socket_, SOL_SOCKET, SO_ERROR,
- &connect_error, &connect_error_len, o->ec_) == socket_error_retval)
- return true;
-
- // The connection failed so the handler will be posted with an error code.
- if (connect_error)
- {
- o->ec_ = asio::error_code(connect_error,
- asio::error::get_system_category());
- }
-
- return true;
- }
-
- private:
- socket_type socket_;
- };
-
- template <typename Handler>
- class connect_op : public connect_op_base
- {
- public:
- connect_op(socket_type socket, Handler handler)
- : connect_op_base(socket, &connect_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.
- connect_op* o(static_cast<connect_op*>(base));
- typedef handler_alloc_traits<Handler, connect_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- // 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(o->handler_, o->ec_);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
- }
-
- private:
- Handler handler_;
- };
-
// Start an asynchronous connect.
template <typename Handler>
void async_connect(implementation_type& impl,
const endpoint_type& peer_endpoint, Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef connect_op<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, impl.socket_, handler);
-
- start_connect_op(impl, ptr.get(), peer_endpoint);
- ptr.release();
- }
-
-private:
- // Start the asynchronous read or write operation.
- void start_op(implementation_type& impl, int op_type,
- reactor_op* op, bool non_blocking, bool noop)
- {
- if (!noop)
- {
- if (is_open(impl))
- {
- if (!non_blocking || is_non_blocking(impl)
- || set_non_blocking(impl, op->ec_))
- {
- reactor_.start_op(op_type, impl.socket_,
- impl.reactor_data_, op, non_blocking);
- return;
- }
- }
- else
- op->ec_ = asio::error::bad_descriptor;
- }
+ typedef reactive_socket_connect_op<Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.socket_, handler);
- io_service_impl_.post_immediate_completion(op);
+ start_connect_op(impl, p.p, peer_endpoint.data(), peer_endpoint.size());
+ p.v = p.p = 0;
}
-
- // Start the asynchronous accept operation.
- void start_accept_op(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;
- io_service_impl_.post_immediate_completion(op);
- }
- }
-
- // Start the asynchronous connect operation.
- void start_connect_op(implementation_type& impl,
- reactor_op* op, const endpoint_type& peer_endpoint)
- {
- if (is_open(impl))
- {
- if (is_non_blocking(impl) || set_non_blocking(impl, op->ec_))
- {
- if (socket_ops::connect(impl.socket_, peer_endpoint.data(),
- peer_endpoint.size(), 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;
- }
- }
- }
- }
- else
- op->ec_ = asio::error::bad_descriptor;
-
- io_service_impl_.post_immediate_completion(op);
- }
-
- // Determine whether the socket has been set non-blocking.
- bool is_non_blocking(implementation_type& impl) const
- {
- return (impl.flags_ & implementation_type::non_blocking);
- }
-
- // Set the internal non-blocking flag.
- bool set_non_blocking(implementation_type& impl,
- asio::error_code& ec)
- {
- ioctl_arg_type non_blocking = 1;
- if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
- return false;
- impl.flags_ |= implementation_type::internal_non_blocking;
- return true;
- }
-
- // The io_service implementation used to post completions.
- io_service_impl& io_service_impl_;
-
- // The selector that performs event demultiplexing for the service.
- reactor& reactor_;
};
} // namespace detail
@@ -1741,4 +385,6 @@ private:
#include "asio/detail/pop_options.hpp"
+#endif // !defined(ASIO_HAS_IOCP)
+
#endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP
diff --git a/ext/asio/asio/detail/reactive_socket_service_base.hpp b/ext/asio/asio/detail/reactive_socket_service_base.hpp
new file mode 100644
index 0000000000..b26d73e74a
--- /dev/null
+++ b/ext/asio/asio/detail/reactive_socket_service_base.hpp
@@ -0,0 +1,298 @@
+//
+// detail/reactive_socket_service_base.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_REACTIVE_SOCKET_SERVICE_BASE_HPP
+#define ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_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 <boost/utility/addressof.hpp>
+#include "asio/buffer.hpp"
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/socket_base.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/reactive_null_buffers_op.hpp"
+#include "asio/detail/reactive_socket_recv_op.hpp"
+#include "asio/detail/reactive_socket_send_op.hpp"
+#include "asio/detail/reactor.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/socket_holder.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/socket_types.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class reactive_socket_service_base
+{
+public:
+ // The native type of a socket.
+ typedef socket_type native_type;
+
+ // The implementation type of the socket.
+ struct base_implementation_type
+ {
+ // The native socket representation.
+ socket_type socket_;
+
+ // The current state of the socket.
+ socket_ops::state_type state_;
+
+ // Per-descriptor data used by the reactor.
+ reactor::per_descriptor_data reactor_data_;
+ };
+
+ // Constructor.
+ ASIO_DECL reactive_socket_service_base(
+ asio::io_service& io_service);
+
+ // Destroy all user-defined handler objects owned by the service.
+ ASIO_DECL void shutdown_service();
+
+ // Construct a new socket implementation.
+ ASIO_DECL void construct(base_implementation_type& impl);
+
+ // Destroy a socket implementation.
+ ASIO_DECL void destroy(base_implementation_type& impl);
+
+ // Determine whether the socket is open.
+ bool is_open(const base_implementation_type& impl) const
+ {
+ return impl.socket_ != invalid_socket;
+ }
+
+ // Destroy a socket implementation.
+ ASIO_DECL asio::error_code close(
+ base_implementation_type& impl, asio::error_code& ec);
+
+ // Get the native socket representation.
+ native_type native(base_implementation_type& impl)
+ {
+ return impl.socket_;
+ }
+
+ // Cancel all operations associated with the socket.
+ ASIO_DECL asio::error_code cancel(
+ base_implementation_type& impl, asio::error_code& ec);
+
+ // Determine whether the socket is at the out-of-band data mark.
+ bool at_mark(const base_implementation_type& impl,
+ asio::error_code& ec) const
+ {
+ return socket_ops::sockatmark(impl.socket_, ec);
+ }
+
+ // Determine the number of bytes available for reading.
+ std::size_t available(const base_implementation_type& impl,
+ asio::error_code& ec) const
+ {
+ return socket_ops::available(impl.socket_, ec);
+ }
+
+ // Place the socket into the state where it will listen for new connections.
+ asio::error_code listen(base_implementation_type& impl,
+ int backlog, asio::error_code& ec)
+ {
+ socket_ops::listen(impl.socket_, backlog, ec);
+ return ec;
+ }
+
+ // Perform an IO control command on the socket.
+ template <typename IO_Control_Command>
+ asio::error_code io_control(base_implementation_type& impl,
+ IO_Control_Command& command, asio::error_code& ec)
+ {
+ socket_ops::ioctl(impl.socket_, impl.state_, command.name(),
+ static_cast<ioctl_arg_type*>(command.data()), ec);
+ return ec;
+ }
+
+ /// Disable sends or receives on the socket.
+ asio::error_code shutdown(base_implementation_type& impl,
+ socket_base::shutdown_type what, asio::error_code& ec)
+ {
+ socket_ops::shutdown(impl.socket_, what, ec);
+ return ec;
+ }
+
+ // Send the given data to the peer.
+ template <typename ConstBufferSequence>
+ size_t send(base_implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, asio::error_code& ec)
+ {
+ buffer_sequence_adapter<asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_send(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+ }
+
+ // Wait until data can be sent without blocking.
+ size_t send(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, asio::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_write(impl.socket_, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_send(base_implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, Handler handler)
+ {
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_send_op<ConstBufferSequence, Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.socket_, buffers, flags, handler);
+
+ start_op(impl, reactor::write_op, p.p, true,
+ ((impl.state_ & socket_ops::stream_oriented)
+ && buffer_sequence_adapter<asio::const_buffer,
+ ConstBufferSequence>::all_empty(buffers)));
+ p.v = p.p = 0;
+ }
+
+ // Start an asynchronous wait until data can be sent without blocking.
+ template <typename Handler>
+ void async_send(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, Handler handler)
+ {
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<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);
+
+ start_op(impl, reactor::write_op, p.p, false, false);
+ p.v = p.p = 0;
+ }
+
+ // Receive some data from the peer. Returns the number of bytes received.
+ template <typename MutableBufferSequence>
+ size_t receive(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, asio::error_code& ec)
+ {
+ buffer_sequence_adapter<asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_recv(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, asio::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received
+ // must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, Handler handler)
+ {
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_recv_op<MutableBufferSequence, Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_, buffers, flags, handler);
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, (flags & socket_base::message_out_of_band) == 0,
+ ((impl.state_ & socket_ops::stream_oriented)
+ && buffer_sequence_adapter<asio::mutable_buffer,
+ MutableBufferSequence>::all_empty(buffers)));
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler>
+ void async_receive(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags flags, Handler handler)
+ {
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_null_buffers_op<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);
+
+ start_op(impl,
+ (flags & socket_base::message_out_of_band)
+ ? reactor::except_op : reactor::read_op,
+ p.p, false, false);
+ p.v = p.p = 0;
+ }
+
+protected:
+ // Open a new socket implementation.
+ ASIO_DECL asio::error_code do_open(
+ base_implementation_type& impl, int af,
+ int type, int protocol, asio::error_code& ec);
+
+ // Assign a native socket to a socket implementation.
+ ASIO_DECL asio::error_code do_assign(
+ base_implementation_type& impl, int type,
+ const native_type& native_socket, asio::error_code& ec);
+
+ // Start the asynchronous read or write operation.
+ ASIO_DECL void start_op(base_implementation_type& impl, int op_type,
+ reactor_op* op, bool non_blocking, bool noop);
+
+ // Start the asynchronous accept operation.
+ ASIO_DECL void start_accept_op(base_implementation_type& impl,
+ reactor_op* op, bool peer_is_open);
+
+ // Start the asynchronous connect operation.
+ ASIO_DECL void start_connect_op(base_implementation_type& impl,
+ reactor_op* op, const socket_addr_type* addr, size_t addrlen);
+
+ // The selector that performs event demultiplexing for the service.
+ reactor& reactor_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/reactive_socket_service_base.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // !defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP
diff --git a/ext/asio/asio/detail/reactor.hpp b/ext/asio/asio/detail/reactor.hpp
index 98ac360b9e..0e938c9542 100644
--- a/ext/asio/asio/detail/reactor.hpp
+++ b/ext/asio/asio/detail/reactor.hpp
@@ -1,8 +1,8 @@
//
-// reactor.hpp
-// ~~~~~~~~~~~
+// detail/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,8 +15,6 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
#include "asio/detail/reactor_fwd.hpp"
#if defined(ASIO_HAS_EPOLL)
@@ -29,6 +27,4 @@
# include "asio/detail/select_reactor.hpp"
#endif
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_DETAIL_REACTOR_HPP
diff --git a/ext/asio/asio/detail/reactor_fwd.hpp b/ext/asio/asio/detail/reactor_fwd.hpp
index 9c33be54ca..d45d768289 100644
--- a/ext/asio/asio/detail/reactor_fwd.hpp
+++ b/ext/asio/asio/detail/reactor_fwd.hpp
@@ -1,8 +1,8 @@
//
-// reactor_fwd.hpp
-// ~~~~~~~~~~~~~~~
+// detail/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,25 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
-#include "asio/detail/dev_poll_reactor_fwd.hpp"
-#include "asio/detail/epoll_reactor_fwd.hpp"
-#include "asio/detail/kqueue_reactor_fwd.hpp"
-#include "asio/detail/select_reactor_fwd.hpp"
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#if defined(ASIO_HAS_IOCP)
+# include "asio/detail/select_reactor_fwd.hpp"
+#elif defined(ASIO_HAS_EPOLL)
+# include "asio/detail/epoll_reactor_fwd.hpp"
+#elif defined(ASIO_HAS_KQUEUE)
+# include "asio/detail/kqueue_reactor_fwd.hpp"
+#elif defined(ASIO_HAS_DEV_POLL)
+# include "asio/detail/dev_poll_reactor_fwd.hpp"
+#else
+# include "asio/detail/select_reactor_fwd.hpp"
+#endif
namespace asio {
namespace detail {
#if defined(ASIO_HAS_IOCP)
-typedef select_reactor<true> reactor;
+typedef select_reactor reactor;
#elif defined(ASIO_HAS_EPOLL)
typedef epoll_reactor reactor;
#elif defined(ASIO_HAS_KQUEUE)
@@ -35,12 +41,10 @@ typedef kqueue_reactor reactor;
#elif defined(ASIO_HAS_DEV_POLL)
typedef dev_poll_reactor reactor;
#else
-typedef select_reactor<false> reactor;
+typedef select_reactor reactor;
#endif
} // namespace detail
} // namespace asio
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_DETAIL_REACTOR_FWD_HPP
diff --git a/ext/asio/asio/detail/reactor_op.hpp b/ext/asio/asio/detail/reactor_op.hpp
index cd557fa6ae..3009cf9c12 100644
--- a/ext/asio/asio/detail/reactor_op.hpp
+++ b/ext/asio/asio/detail/reactor_op.hpp
@@ -1,8 +1,8 @@
//
-// reactor_op.hpp
-// ~~~~~~~~~~~~
+// detail/reactor_op.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/detail/operation.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
diff --git a/ext/asio/asio/detail/reactor_op_queue.hpp b/ext/asio/asio/detail/reactor_op_queue.hpp
index 233c0aec16..6eed398997 100644
--- a/ext/asio/asio/detail/reactor_op_queue.hpp
+++ b/ext/asio/asio/detail/reactor_op_queue.hpp
@@ -1,8 +1,8 @@
//
-// reactor_op_queue.hpp
-// ~~~~~~~~~~~~~~~~~~~~
+// detail/reactor_op_queue.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/error.hpp"
+#include "asio/detail/config.hpp"
#include "asio/detail/hash_map.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/op_queue.hpp"
#include "asio/detail/reactor_op.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
diff --git a/ext/asio/asio/detail/regex_fwd.hpp b/ext/asio/asio/detail/regex_fwd.hpp
new file mode 100644
index 0000000000..9da295b26c
--- /dev/null
+++ b/ext/asio/asio/detail/regex_fwd.hpp
@@ -0,0 +1,31 @@
+//
+// detail/regex_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_REGEX_FWD_HPP
+#define ASIO_DETAIL_REGEX_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/regex_fwd.hpp>
+#include <boost/regex/v4/match_flags.hpp>
+
+namespace boost {
+
+template <class BidiIterator>
+struct sub_match;
+
+template <class BidiIterator, class Allocator>
+class match_results;
+
+} // namespace boost
+
+#endif // ASIO_DETAIL_REGEX_FWD_HPP
diff --git a/ext/asio/asio/detail/resolve_endpoint_op.hpp b/ext/asio/asio/detail/resolve_endpoint_op.hpp
new file mode 100644
index 0000000000..0931fd03db
--- /dev/null
+++ b/ext/asio/asio/detail/resolve_endpoint_op.hpp
@@ -0,0 +1,116 @@
+//
+// detail/resolve_endpoint_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_RESOLVER_ENDPOINT_OP_HPP
+#define ASIO_DETAIL_RESOLVER_ENDPOINT_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/ip/basic_resolver_iterator.hpp"
+#include "asio/detail/bind_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/operation.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Protocol, typename Handler>
+class resolve_endpoint_op : public operation
+{
+public:
+ ASIO_DEFINE_HANDLER_PTR(resolve_endpoint_op);
+
+ typedef typename Protocol::endpoint endpoint_type;
+ typedef asio::ip::basic_resolver_iterator<Protocol> iterator_type;
+
+ resolve_endpoint_op(socket_ops::weak_cancel_token_type cancel_token,
+ const endpoint_type& endpoint, io_service_impl& ios, Handler handler)
+ : operation(&resolve_endpoint_op::do_complete),
+ cancel_token_(cancel_token),
+ endpoint_(endpoint),
+ io_service_impl_(ios),
+ 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 operation object.
+ resolve_endpoint_op* o(static_cast<resolve_endpoint_op*>(base));
+ ptr p = { boost::addressof(o->handler_), o, o };
+
+ if (owner && owner != &o->io_service_impl_)
+ {
+ // The operation is being run on the worker io_service. Time to perform
+ // the resolver operation.
+
+ // Perform the blocking endpoint resolution operation.
+ char host_name[NI_MAXHOST];
+ char service_name[NI_MAXSERV];
+ socket_ops::background_getnameinfo(o->cancel_token_, o->endpoint_.data(),
+ o->endpoint_.size(), host_name, NI_MAXHOST, service_name, NI_MAXSERV,
+ o->endpoint_.protocol().type(), o->ec_);
+ o->iter_ = iterator_type::create(o->endpoint_, host_name, service_name);
+
+ // Pass operation back to main io_service for completion.
+ o->io_service_impl_.post_deferred_completion(o);
+ p.v = p.p = 0;
+ }
+ else
+ {
+ // The operation has been returned to the main io_service. The completion
+ // handler is ready to be delivered.
+
+ // 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, iterator_type>
+ handler(o->handler_, o->ec_, o->iter_);
+ p.h = boost::addressof(handler.handler_);
+ p.reset();
+
+ if (owner)
+ {
+ asio::detail::fenced_block b;
+ asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ }
+ }
+ }
+
+private:
+ socket_ops::weak_cancel_token_type cancel_token_;
+ endpoint_type endpoint_;
+ io_service_impl& io_service_impl_;
+ Handler handler_;
+ asio::error_code ec_;
+ iterator_type iter_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_RESOLVER_ENDPOINT_OP_HPP
diff --git a/ext/asio/asio/detail/resolve_op.hpp b/ext/asio/asio/detail/resolve_op.hpp
new file mode 100644
index 0000000000..a04fbc3b52
--- /dev/null
+++ b/ext/asio/asio/detail/resolve_op.hpp
@@ -0,0 +1,126 @@
+//
+// detail/resolve_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_RESOLVE_OP_HPP
+#define ASIO_DETAIL_RESOLVE_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/ip/basic_resolver_iterator.hpp"
+#include "asio/ip/basic_resolver_query.hpp"
+#include "asio/detail/bind_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/operation.hpp"
+#include "asio/detail/socket_ops.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Protocol, typename Handler>
+class resolve_op : public operation
+{
+public:
+ ASIO_DEFINE_HANDLER_PTR(resolve_op);
+
+ typedef asio::ip::basic_resolver_query<Protocol> query_type;
+ typedef asio::ip::basic_resolver_iterator<Protocol> iterator_type;
+
+ resolve_op(socket_ops::weak_cancel_token_type cancel_token,
+ const query_type& query, io_service_impl& ios, Handler handler)
+ : operation(&resolve_op::do_complete),
+ cancel_token_(cancel_token),
+ query_(query),
+ io_service_impl_(ios),
+ handler_(handler),
+ addrinfo_(0)
+ {
+ }
+
+ ~resolve_op()
+ {
+ if (addrinfo_)
+ socket_ops::freeaddrinfo(addrinfo_);
+ }
+
+ static void do_complete(io_service_impl* owner, operation* base,
+ asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the operation object.
+ resolve_op* o(static_cast<resolve_op*>(base));
+ ptr p = { boost::addressof(o->handler_), o, o };
+
+ if (owner && owner != &o->io_service_impl_)
+ {
+ // The operation is being run on the worker io_service. Time to perform
+ // the resolver operation.
+
+ // Perform the blocking host resolution operation.
+ socket_ops::background_getaddrinfo(o->cancel_token_,
+ o->query_.host_name().c_str(), o->query_.service_name().c_str(),
+ o->query_.hints(), &o->addrinfo_, o->ec_);
+
+ // Pass operation back to main io_service for completion.
+ o->io_service_impl_.post_deferred_completion(o);
+ p.v = p.p = 0;
+ }
+ else
+ {
+ // The operation has been returned to the main io_service. The completion
+ // handler is ready to be delivered.
+
+ // 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, iterator_type>
+ handler(o->handler_, o->ec_, iterator_type());
+ p.h = boost::addressof(handler.handler_);
+ if (o->addrinfo_)
+ {
+ handler.arg2_ = iterator_type::create(o->addrinfo_,
+ o->query_.host_name(), o->query_.service_name());
+ }
+ p.reset();
+
+ if (owner)
+ {
+ asio::detail::fenced_block b;
+ asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ }
+ }
+ }
+
+private:
+ socket_ops::weak_cancel_token_type cancel_token_;
+ query_type query_;
+ io_service_impl& io_service_impl_;
+ Handler handler_;
+ asio::error_code ec_;
+ asio::detail::addrinfo_type* addrinfo_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_DETAIL_RESOLVE_OP_HPP
diff --git a/ext/asio/asio/detail/resolver_service.hpp b/ext/asio/asio/detail/resolver_service.hpp
index 562dc10476..c2c3b0c98a 100644
--- a/ext/asio/asio/detail/resolver_service.hpp
+++ b/ext/asio/asio/detail/resolver_service.hpp
@@ -1,8 +1,8 @@
//
-// resolver_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~
+// detail/resolver_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,68 +15,25 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <cstring>
-#include <boost/scoped_ptr.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/weak_ptr.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/io_service.hpp"
+#include "asio/detail/config.hpp"
#include "asio/ip/basic_resolver_iterator.hpp"
#include "asio/ip/basic_resolver_query.hpp"
-#include "asio/detail/bind_handler.hpp"
-#include "asio/detail/fenced_block.hpp"
-#include "asio/detail/mutex.hpp"
-#include "asio/detail/noncopyable.hpp"
-#include "asio/detail/operation.hpp"
-#include "asio/detail/service_base.hpp"
-#include "asio/detail/socket_ops.hpp"
-#include "asio/detail/socket_types.hpp"
-#include "asio/detail/thread.hpp"
+#include "asio/detail/resolve_endpoint_op.hpp"
+#include "asio/detail/resolve_op.hpp"
+#include "asio/detail/resolver_service_base.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
template <typename Protocol>
-class resolver_service
- : public asio::detail::service_base<resolver_service<Protocol> >
+class resolver_service : public resolver_service_base
{
-private:
- // Helper class to perform exception-safe cleanup of addrinfo objects.
- class auto_addrinfo
- : private asio::detail::noncopyable
- {
- public:
- explicit auto_addrinfo(asio::detail::addrinfo_type* ai)
- : ai_(ai)
- {
- }
-
- ~auto_addrinfo()
- {
- if (ai_)
- socket_ops::freeaddrinfo(ai_);
- }
-
- operator asio::detail::addrinfo_type*()
- {
- return ai_;
- }
-
- private:
- asio::detail::addrinfo_type* ai_;
- };
-
public:
- // The implementation type of the resolver. The shared pointer is used as a
- // cancellation token to indicate to the background thread that the operation
- // has been cancelled.
- typedef boost::shared_ptr<void> implementation_type;
- struct noop_deleter { void operator()(void*) {} };
+ // The implementation type of the resolver. A cancellation token is used to
+ // indicate to the background thread that the operation has been cancelled.
+ typedef socket_ops::shared_cancel_token_type implementation_type;
// The endpoint type.
typedef typename Protocol::endpoint endpoint_type;
@@ -89,55 +46,8 @@ public:
// Constructor.
resolver_service(asio::io_service& io_service)
- : asio::detail::service_base<
- resolver_service<Protocol> >(io_service),
- mutex_(),
- 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)
- {
- }
-
- // Destructor.
- ~resolver_service()
+ : resolver_service_base(io_service)
{
- shutdown_service();
- }
-
- // Destroy all user-defined handler objects owned by the service.
- void 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();
- }
- }
-
- // Construct a new resolver implementation.
- void construct(implementation_type& impl)
- {
- impl.reset(static_cast<void*>(0), noop_deleter());
- }
-
- // Destroy a resolver implementation.
- void destroy(implementation_type&)
- {
- }
-
- // Cancel pending asynchronous operations.
- void cancel(implementation_type& impl)
- {
- impl.reset(static_cast<void*>(0), noop_deleter());
}
// Resolve a query to a list of entries.
@@ -145,293 +55,60 @@ public:
asio::error_code& ec)
{
asio::detail::addrinfo_type* address_info = 0;
- std::string host_name = query.host_name();
- std::string service_name = query.service_name();
- asio::detail::addrinfo_type hints = query.hints();
- socket_ops::getaddrinfo(!host_name.empty() ? host_name.c_str() : 0,
- service_name.c_str(), &hints, &address_info, ec);
+ socket_ops::getaddrinfo(query.host_name().c_str(),
+ query.service_name().c_str(), query.hints(), &address_info, ec);
auto_addrinfo auto_address_info(address_info);
- if (ec)
- return iterator_type();
-
- return iterator_type::create(address_info, host_name, service_name);
+ return ec ? iterator_type() : iterator_type::create(
+ address_info, query.host_name(), query.service_name());
}
- template <typename Handler>
- class resolve_op
- : public operation
- {
- public:
- resolve_op(implementation_type impl, const query_type& query,
- io_service_impl& io_service_impl, Handler handler)
- : operation(&resolve_op::do_complete),
- impl_(impl),
- query_(query),
- io_service_impl_(io_service_impl),
- 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 operation object.
- resolve_op* o(static_cast<resolve_op*>(base));
- typedef handler_alloc_traits<Handler, resolve_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- if (owner)
- {
- if (owner != &o->io_service_impl_)
- {
- // The operation is being run on the worker io_service. Time to
- // perform the resolver operation.
-
- if (o->impl_.expired())
- {
- // THe operation has been cancelled.
- o->ec_ = asio::error::operation_aborted;
- }
- else
- {
- // Perform the blocking host resolution operation.
- asio::detail::addrinfo_type* address_info = 0;
- std::string host_name = o->query_.host_name();
- std::string service_name = o->query_.service_name();
- asio::detail::addrinfo_type hints = o->query_.hints();
- socket_ops::getaddrinfo(!host_name.empty() ? host_name.c_str() : 0,
- service_name.c_str(), &hints, &address_info, o->ec_);
- auto_addrinfo auto_address_info(address_info);
- o->iter_ = iterator_type::create(
- address_info, host_name, service_name);
- }
-
- o->io_service_impl_.post_deferred_completion(o);
- ptr.release();
- }
- else
- {
- // The operation has been returned to the main io_serice. The
- // completion handler is ready to be delivered.
-
- // 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, iterator_type>
- handler(o->handler_, o->ec_, o->iter_);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
- }
- }
-
- private:
- boost::weak_ptr<void> impl_;
- query_type query_;
- io_service_impl& io_service_impl_;
- Handler handler_;
- asio::error_code ec_;
- iterator_type iter_;
- };
-
// Asynchronously resolve a query to a list of entries.
template <typename Handler>
void async_resolve(implementation_type& impl, const query_type& query,
Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef resolve_op<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,
- impl, query, io_service_impl_, handler);
-
- if (work_io_service_)
- {
- start_work_thread();
- io_service_impl_.work_started();
- work_io_service_impl_.post_immediate_completion(ptr.get());
- ptr.release();
- }
+ typedef resolve_op<Protocol, Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl, query, io_service_impl_, handler);
+
+ start_resolve_op(p.p);
+ p.v = p.p = 0;
}
// Resolve an endpoint to a list of entries.
iterator_type resolve(implementation_type&,
const endpoint_type& endpoint, asio::error_code& ec)
{
- // First try resolving with the service name. If that fails try resolving
- // but allow the service to be returned as a number.
char host_name[NI_MAXHOST];
char service_name[NI_MAXSERV];
- int flags = endpoint.protocol().type() == SOCK_DGRAM ? NI_DGRAM : 0;
- socket_ops::getnameinfo(endpoint.data(), endpoint.size(),
- host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec);
- if (ec)
- {
- flags |= NI_NUMERICSERV;
- socket_ops::getnameinfo(endpoint.data(), endpoint.size(),
- host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec);
- }
+ socket_ops::sync_getnameinfo(endpoint.data(), endpoint.size(),
+ host_name, NI_MAXHOST, service_name, NI_MAXSERV,
+ endpoint.protocol().type(), ec);
- if (ec)
- return iterator_type();
-
- return iterator_type::create(endpoint, host_name, service_name);
+ return ec ? iterator_type() : iterator_type::create(
+ endpoint, host_name, service_name);
}
- template <typename Handler>
- class resolve_endpoint_op
- : public operation
- {
- public:
- resolve_endpoint_op(implementation_type impl, const endpoint_type& ep,
- io_service_impl& io_service_impl, Handler handler)
- : operation(&resolve_endpoint_op::do_complete),
- impl_(impl),
- ep_(ep),
- io_service_impl_(io_service_impl),
- 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 operation object.
- resolve_endpoint_op* o(static_cast<resolve_endpoint_op*>(base));
- typedef handler_alloc_traits<Handler, resolve_endpoint_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- if (owner)
- {
- if (owner != &o->io_service_impl_)
- {
- // The operation is being run on the worker io_service. Time to
- // perform the resolver operation.
-
- if (o->impl_.expired())
- {
- // THe operation has been cancelled.
- o->ec_ = asio::error::operation_aborted;
- }
- else
- {
- // Perform the blocking endoint resolution operation.
- char host_name[NI_MAXHOST];
- char service_name[NI_MAXSERV];
- int flags = o->ep_.protocol().type() == SOCK_DGRAM ? NI_DGRAM : 0;
- socket_ops::getnameinfo(o->ep_.data(), o->ep_.size(),
- host_name, NI_MAXHOST, service_name,
- NI_MAXSERV, flags, o->ec_);
- if (o->ec_)
- {
- flags |= NI_NUMERICSERV;
- socket_ops::getnameinfo(o->ep_.data(), o->ep_.size(),
- host_name, NI_MAXHOST, service_name,
- NI_MAXSERV, flags, o->ec_);
- }
- o->iter_ = iterator_type::create(o->ep_, host_name, service_name);
- }
-
- o->io_service_impl_.post_deferred_completion(o);
- ptr.release();
- }
- else
- {
- // The operation has been returned to the main io_serice. The
- // completion handler is ready to be delivered.
-
- // 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, iterator_type>
- handler(o->handler_, o->ec_, o->iter_);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
- }
- }
-
- private:
- boost::weak_ptr<void> impl_;
- endpoint_type ep_;
- io_service_impl& io_service_impl_;
- Handler handler_;
- asio::error_code ec_;
- iterator_type iter_;
- };
-
// Asynchronously resolve an endpoint to a list of entries.
template <typename Handler>
void async_resolve(implementation_type& impl, const endpoint_type& endpoint,
Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef resolve_endpoint_op<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,
- impl, endpoint, io_service_impl_, handler);
-
- if (work_io_service_)
- {
- start_work_thread();
- io_service_impl_.work_started();
- work_io_service_impl_.post_immediate_completion(ptr.get());
- ptr.release();
- }
- }
-
-private:
- // Helper class to run the work io_service in a thread.
- class 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_;
- };
-
- // Start the work thread if it's not already running.
- void 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_)));
- }
+ typedef resolve_endpoint_op<Protocol, Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl, endpoint, io_service_impl_, handler);
+
+ start_resolve_op(p.p);
+ p.v = p.p = 0;
}
-
- // Mutex to protect access to internal data.
- asio::detail::mutex mutex_;
-
- // The io_service implementation used to post completions.
- io_service_impl& io_service_impl_;
-
- // Private io_service used for performing asynchronous host resolution.
- boost::scoped_ptr<asio::io_service> work_io_service_;
-
- // The work io_service implementation used to post completions.
- io_service_impl& work_io_service_impl_;
-
- // Work for the private io_service to perform.
- boost::scoped_ptr<asio::io_service::work> work_;
-
- // Thread used for running the work io_service's run loop.
- boost::scoped_ptr<asio::detail::thread> work_thread_;
};
} // namespace detail
diff --git a/ext/asio/asio/detail/resolver_service_base.hpp b/ext/asio/asio/detail/resolver_service_base.hpp
new file mode 100644
index 0000000000..d6f20bdb70
--- /dev/null
+++ b/ext/asio/asio/detail/resolver_service_base.hpp
@@ -0,0 +1,123 @@
+//
+// detail/resolver_service_base.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_RESOLVER_SERVICE_BASE_HPP
+#define ASIO_DETAIL_RESOLVER_SERVICE_BASE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/scoped_ptr.hpp>
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/detail/mutex.hpp"
+#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/operation.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/socket_types.hpp"
+#include "asio/detail/thread.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class resolver_service_base
+{
+public:
+ // The implementation type of the resolver. A cancellation token is used to
+ // indicate to the background thread that the operation has been cancelled.
+ typedef socket_ops::shared_cancel_token_type implementation_type;
+
+ // Constructor.
+ ASIO_DECL resolver_service_base(asio::io_service& io_service);
+
+ // Destructor.
+ ASIO_DECL ~resolver_service_base();
+
+ // Destroy all user-defined handler objects owned by the service.
+ ASIO_DECL void shutdown_service();
+
+ // Construct a new resolver implementation.
+ ASIO_DECL void construct(implementation_type& impl);
+
+ // Destroy a resolver implementation.
+ ASIO_DECL void destroy(implementation_type&);
+
+ // Cancel pending asynchronous operations.
+ ASIO_DECL void cancel(implementation_type& impl);
+
+protected:
+ // Helper function to start an asynchronous resolve operation.
+ ASIO_DECL void start_resolve_op(operation* op);
+
+ // Helper class to perform exception-safe cleanup of addrinfo objects.
+ class auto_addrinfo
+ : private asio::detail::noncopyable
+ {
+ public:
+ explicit auto_addrinfo(asio::detail::addrinfo_type* ai)
+ : ai_(ai)
+ {
+ }
+
+ ~auto_addrinfo()
+ {
+ if (ai_)
+ socket_ops::freeaddrinfo(ai_);
+ }
+
+ operator asio::detail::addrinfo_type*()
+ {
+ return ai_;
+ }
+
+ private:
+ asio::detail::addrinfo_type* ai_;
+ };
+
+ // Helper class to run the work io_service in a thread.
+ class work_io_service_runner;
+
+ // Start the work thread if it's not already running.
+ ASIO_DECL void start_work_thread();
+
+ // The io_service implementation used to post completions.
+ io_service_impl& io_service_impl_;
+
+private:
+ // Mutex to protect access to internal data.
+ asio::detail::mutex mutex_;
+
+ // Private io_service used for performing asynchronous host resolution.
+ boost::scoped_ptr<asio::io_service> work_io_service_;
+
+ // The work io_service implementation used to post completions.
+ io_service_impl& work_io_service_impl_;
+
+ // Work for the private io_service to perform.
+ boost::scoped_ptr<asio::io_service::work> work_;
+
+ // Thread used for running the work io_service's run loop.
+ boost::scoped_ptr<asio::detail::thread> work_thread_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/resolver_service_base.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // ASIO_DETAIL_RESOLVER_SERVICE_BASE_HPP
diff --git a/ext/asio/asio/detail/scoped_lock.hpp b/ext/asio/asio/detail/scoped_lock.hpp
index e6f6ba59a0..69b572530b 100644
--- a/ext/asio/asio/detail/scoped_lock.hpp
+++ b/ext/asio/asio/detail/scoped_lock.hpp
@@ -1,8 +1,8 @@
//
-// scoped_lock.hpp
-// ~~~~~~~~~~~~~~~
+// detail/scoped_lock.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,10 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
diff --git a/ext/asio/asio/detail/select_interrupter.hpp b/ext/asio/asio/detail/select_interrupter.hpp
index ff5505bebc..e975ddca00 100644
--- a/ext/asio/asio/detail/select_interrupter.hpp
+++ b/ext/asio/asio/detail/select_interrupter.hpp
@@ -1,8 +1,8 @@
//
-// select_interrupter.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~
+// detail/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)
//
// 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/config.hpp"
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) || defined(__SYMBIAN32__)
# include "asio/detail/socket_select_interrupter.hpp"
-#else
+#elif defined(ASIO_HAS_EVENTFD)
# include "asio/detail/eventfd_select_interrupter.hpp"
+#else
# include "asio/detail/pipe_select_interrupter.hpp"
#endif
namespace asio {
namespace detail {
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) || defined(__SYMBIAN32__)
typedef socket_select_interrupter select_interrupter;
#elif defined(ASIO_HAS_EVENTFD)
typedef eventfd_select_interrupter select_interrupter;
@@ -42,6 +39,4 @@ typedef pipe_select_interrupter select_interrupter;
} // namespace detail
} // namespace asio
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_DETAIL_SELECT_INTERRUPTER_HPP
diff --git a/ext/asio/asio/detail/select_reactor.hpp b/ext/asio/asio/detail/select_reactor.hpp
index 798611b281..161305f8c7 100644
--- a/ext/asio/asio/detail/select_reactor.hpp
+++ b/ext/asio/asio/detail/select_reactor.hpp
@@ -1,8 +1,8 @@
//
-// select_reactor.hpp
-// ~~~~~~~~~~~~~~~~~~
+// detail/select_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,41 +15,38 @@
# 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.
+#if defined(ASIO_HAS_IOCP) \
+ || (!defined(ASIO_HAS_DEV_POLL) \
+ && !defined(ASIO_HAS_EPOLL) \
+ && !defined(ASIO_HAS_KQUEUE))
-#include "asio/detail/push_options.hpp"
#include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/io_service.hpp"
-#include "asio/detail/bind_handler.hpp"
-#include "asio/detail/fd_set_adapter.hpp"
#include "asio/detail/mutex.hpp"
-#include "asio/detail/noncopyable.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/select_reactor_fwd.hpp"
-#include "asio/detail/service_base.hpp"
-#include "asio/detail/signal_blocker.hpp"
-#include "asio/detail/socket_ops.hpp"
#include "asio/detail/socket_types.hpp"
-#include "asio/detail/thread.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"
+
+#if defined(ASIO_HAS_IOCP)
+# include "asio/detail/thread.hpp"
+#endif // defined(ASIO_HAS_IOCP)
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
-template <bool Own_Thread>
class select_reactor
- : public asio::detail::service_base<select_reactor<Own_Thread> >
+ : public asio::detail::service_base<select_reactor>
{
public:
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -66,280 +63,91 @@ public:
};
// Constructor.
- select_reactor(asio::io_service& io_service)
- : asio::detail::service_base<
- select_reactor<Own_Thread> >(io_service),
- io_service_(use_service<io_service_impl>(io_service)),
- mutex_(),
- interrupter_(),
- stop_thread_(false),
- thread_(0),
- shutdown_(false)
- {
- if (Own_Thread)
- {
- asio::detail::signal_blocker sb;
- thread_ = new asio::detail::thread(
- bind_handler(&select_reactor::call_run_thread, this));
- }
- }
+ ASIO_DECL select_reactor(asio::io_service& io_service);
// Destructor.
- ~select_reactor()
- {
- shutdown_service();
- }
+ ASIO_DECL ~select_reactor();
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
- {
- asio::detail::mutex::scoped_lock lock(mutex_);
- shutdown_ = true;
- stop_thread_ = true;
- lock.unlock();
-
- if (Own_Thread)
- {
- if (thread_)
- {
- interrupter_.interrupt();
- thread_->join();
- delete thread_;
- thread_ = 0;
- }
- }
-
- 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, but only if the reactor is not in its own thread.
- 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)
- {
- asio::detail::mutex::scoped_lock lock(mutex_);
- if (!shutdown_)
- {
- bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
- io_service_.work_started();
- if (first)
- interrupter_.interrupt();
- }
- }
+ ASIO_DECL void start_op(int op_type, socket_type descriptor,
+ per_descriptor_data&, reactor_op* op, bool);
// 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_);
- 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 select 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_);
-
- // Check if the thread is supposed to stop.
- if (Own_Thread)
- if (stop_thread_)
- return;
-
- // 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);
- }
+ ASIO_DECL void run(bool block, op_queue<operation>& ops);
// Interrupt the select loop.
- void interrupt()
- {
- interrupter_.interrupt();
- }
+ ASIO_DECL void interrupt();
private:
+#if defined(ASIO_HAS_IOCP)
// Run the select loop in the thread.
- void run_thread()
- {
- if (Own_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();
- }
- }
- }
+ ASIO_DECL void run_thread();
// Entry point for the select loop thread.
- static void call_run_thread(select_reactor* reactor)
- {
- if (Own_Thread)
- {
- reactor->run_thread();
- }
- }
+ ASIO_DECL static void call_run_thread(select_reactor* reactor);
+#endif // defined(ASIO_HAS_IOCP)
+
+ // 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 select call.
- timeval* 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;
- }
+ ASIO_DECL timeval* get_timeout(timeval& tv);
// Cancel all operations associated with the given descriptor. This function
// does not acquire the select_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);
// The io_service implementation used to post completions.
io_service_impl& io_service_;
@@ -356,11 +164,13 @@ private:
// The timer queues.
timer_queue_set timer_queues_;
+#if defined(ASIO_HAS_IOCP)
// Does the reactor loop thread need to stop.
bool stop_thread_;
// The thread that is running the reactor loop.
asio::detail::thread* thread_;
+#endif // defined(ASIO_HAS_IOCP)
// Whether the service has been shut down.
bool shutdown_;
@@ -371,4 +181,14 @@ private:
#include "asio/detail/pop_options.hpp"
+#include "asio/detail/impl/select_reactor.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/select_reactor.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_IOCP)
+ // || (!defined(ASIO_HAS_DEV_POLL)
+ // && !defined(ASIO_HAS_EPOLL)
+ // && !defined(ASIO_HAS_KQUEUE))
+
#endif // ASIO_DETAIL_SELECT_REACTOR_HPP
diff --git a/ext/asio/asio/detail/select_reactor_fwd.hpp b/ext/asio/asio/detail/select_reactor_fwd.hpp
index 0b72e7e8aa..04e5ecdcac 100644
--- a/ext/asio/asio/detail/select_reactor_fwd.hpp
+++ b/ext/asio/asio/detail/select_reactor_fwd.hpp
@@ -1,8 +1,8 @@
//
-// select_reactor_fwd.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~
+// detail/select_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,17 +15,12 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
namespace asio {
namespace detail {
-template <bool Own_Thread>
class select_reactor;
} // namespace detail
} // namespace asio
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_DETAIL_SELECT_REACTOR_FWD_HPP
diff --git a/ext/asio/asio/detail/service_registry.hpp b/ext/asio/asio/detail/service_registry.hpp
index f80b4b6953..34b946d19b 100644
--- a/ext/asio/asio/detail/service_registry.hpp
+++ b/ext/asio/asio/detail/service_registry.hpp
@@ -1,8 +1,8 @@
//
-// service_registry.hpp
-// ~~~~~~~~~~~~~~~~~~~~
+// detail/service_registry.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,11 @@
# 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 <typeinfo>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/io_service.hpp"
#include "asio/detail/mutex.hpp"
#include "asio/detail/noncopyable.hpp"
-#include "asio/detail/service_id.hpp"
+#include "asio/io_service.hpp"
#if defined(BOOST_NO_TYPEID)
# if !defined(ASIO_NO_TYPEID)
@@ -32,6 +27,8 @@
# endif // !defined(ASIO_NO_TYPEID)
#endif // defined(BOOST_NO_TYPEID)
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
@@ -55,98 +52,43 @@ class service_registry
{
public:
// Constructor.
- service_registry(asio::io_service& o)
- : owner_(o),
- first_service_(0)
- {
- }
+ ASIO_DECL service_registry(asio::io_service& o);
// Destructor.
- ~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;
- }
- }
+ ASIO_DECL ~service_registry();
// Get the service object corresponding to the specified service type. Will
// create a new service object automatically if no such object already
// exists. Ownership of the service object is not transferred to the caller.
template <typename Service>
- Service& 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));
- }
+ Service& use_service();
- // Add a service object. Returns false on error, in which case ownership of
- // the object is retained by the caller.
+ // Add a service object. Throws on error, in which case ownership of the
+ // object is retained by the caller.
template <typename Service>
- bool add_service(Service* new_service)
- {
- asio::io_service::service::key key;
- init_key(key, Service::id);
- return do_add_service(key, new_service);
- }
+ void add_service(Service* new_service);
// Check whether a service object of the specified type already exists.
template <typename Service>
- bool has_service() const
- {
- asio::io_service::service::key key;
- init_key(key, Service::id);
- return do_has_service(key);
- }
+ bool has_service() const;
private:
// Initialise a service's key based on its id.
- void init_key(asio::io_service::service::key& key,
- const asio::io_service::id& id)
- {
- key.type_info_ = 0;
- key.id_ = &id;
- }
+ ASIO_DECL static void init_key(
+ asio::io_service::service::key& key,
+ const asio::io_service::id& id);
#if !defined(ASIO_NO_TYPEID)
// Initialise a service's key based on its id.
template <typename Service>
- void 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;
- }
+ static void init_key(asio::io_service::service::key& key,
+ const asio::detail::service_id<Service>& /*id*/);
#endif // !defined(ASIO_NO_TYPEID)
// Check if a service matches the given id.
- static bool keys_match(
+ ASIO_DECL static bool 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;
- }
+ const asio::io_service::service::key& key2);
// The type of a factory function used for creating a service instance.
typedef asio::io_service::service*
@@ -155,18 +97,15 @@ private:
// Factory function for creating a service instance.
template <typename Service>
static asio::io_service::service* create(
- asio::io_service& owner)
- {
- return new Service(owner);
- }
+ asio::io_service& owner);
// Destroy a service instance.
- static void destroy(asio::io_service::service* service)
- {
- delete service;
- }
+ ASIO_DECL static void destroy(
+ asio::io_service::service* service);
// Helper class to manage service pointers.
+ struct auto_service_ptr;
+ friend struct auto_service_ptr;
struct auto_service_ptr
{
asio::io_service::service* ptr_;
@@ -176,86 +115,19 @@ private:
// Get the service object corresponding to the specified service key. Will
// create a new service object automatically if no such object already
// exists. Ownership of the service object is not transferred to the caller.
- asio::io_service::service* do_use_service(
+ ASIO_DECL asio::io_service::service* 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_;
- }
+ factory_type factory);
// Add a service object. Returns false on error, in which case ownership of
// the object is retained by the caller.
- bool do_add_service(
+ ASIO_DECL void do_add_service(
const asio::io_service::service::key& key,
- asio::io_service::service* new_service)
- {
- 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))
- return false;
- service = service->next_;
- }
-
- // Take ownership of the service object.
- new_service->key_ = key;
- new_service->next_ = first_service_;
- first_service_ = new_service;
-
- return true;
- }
+ asio::io_service::service* new_service);
// Check whether a service object with the specified key already exists.
- bool 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;
- }
+ ASIO_DECL bool do_has_service(
+ const asio::io_service::service::key& key) const;
// Mutex to protect access to internal data.
mutable asio::detail::mutex mutex_;
@@ -272,4 +144,9 @@ private:
#include "asio/detail/pop_options.hpp"
+#include "asio/detail/impl/service_registry.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/service_registry.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
#endif // ASIO_DETAIL_SERVICE_REGISTRY_HPP
diff --git a/ext/asio/asio/detail/service_registry_fwd.hpp b/ext/asio/asio/detail/service_registry_fwd.hpp
index 423bb4beef..4108c1a100 100644
--- a/ext/asio/asio/detail/service_registry_fwd.hpp
+++ b/ext/asio/asio/detail/service_registry_fwd.hpp
@@ -1,8 +1,8 @@
//
-// service_registry_fwd.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/service_registry_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 {
namespace detail {
@@ -25,6 +23,4 @@ class service_registry;
} // namespace detail
} // namespace asio
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_DETAIL_SERVICE_REGISTRY_FWD_HPP
diff --git a/ext/asio/asio/detail/shared_ptr.hpp b/ext/asio/asio/detail/shared_ptr.hpp
new file mode 100644
index 0000000000..cd496f5d1f
--- /dev/null
+++ b/ext/asio/asio/detail/shared_ptr.hpp
@@ -0,0 +1,38 @@
+//
+// detail/shared_ptr.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_SHARED_PTR_HPP
+#define ASIO_DETAIL_SHARED_PTR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1600)
+# include <memory>
+#else
+# include <boost/shared_ptr.hpp>
+#endif
+
+namespace asio {
+namespace detail {
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1600)
+using std::shared_ptr;
+#else
+using boost::shared_ptr;
+#endif
+
+} // namespace detail
+} // namespace asio
+
+#endif // ASIO_DETAIL_SHARED_PTR_HPP
diff --git a/ext/asio/asio/detail/signal_blocker.hpp b/ext/asio/asio/detail/signal_blocker.hpp
index 52f70c8578..89f45ca1dc 100644
--- a/ext/asio/asio/detail/signal_blocker.hpp
+++ b/ext/asio/asio/detail/signal_blocker.hpp
@@ -1,8 +1,8 @@
//
-// signal_blocker.hpp
-// ~~~~~~~~~~~~~~~~~~
+// detail/signal_blocker.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,11 @@
# 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(BOOST_WINDOWS) || defined(__CYGWIN__) || defined(__SYMBIAN32__)
# include "asio/detail/null_signal_blocker.hpp"
-#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-# include "asio/detail/win_signal_blocker.hpp"
#elif defined(BOOST_HAS_PTHREADS)
# include "asio/detail/posix_signal_blocker.hpp"
#else
@@ -34,10 +29,9 @@
namespace asio {
namespace detail {
-#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
+#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS) \
+ || defined(BOOST_WINDOWS) || defined(__CYGWIN__) || defined(__SYMBIAN32__)
typedef null_signal_blocker signal_blocker;
-#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-typedef win_signal_blocker signal_blocker;
#elif defined(BOOST_HAS_PTHREADS)
typedef posix_signal_blocker signal_blocker;
#endif
@@ -45,6 +39,4 @@ typedef posix_signal_blocker signal_blocker;
} // namespace detail
} // namespace asio
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_DETAIL_SIGNAL_BLOCKER_HPP
diff --git a/ext/asio/asio/detail/signal_init.hpp b/ext/asio/asio/detail/signal_init.hpp
index 12f17d37ac..80925f6978 100644
--- a/ext/asio/asio/detail/signal_init.hpp
+++ b/ext/asio/asio/detail/signal_init.hpp
@@ -1,8 +1,8 @@
//
-// signal_init.hpp
-// ~~~~~~~~~~~~~~~
+// detail/signal_init.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 <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-#include "asio/detail/push_options.hpp"
#include <csignal>
-#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
@@ -44,8 +40,8 @@ public:
} // namespace detail
} // namespace asio
-#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-
#include "asio/detail/pop_options.hpp"
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
#endif // ASIO_DETAIL_SIGNAL_INIT_HPP
diff --git a/ext/asio/asio/detail/socket_holder.hpp b/ext/asio/asio/detail/socket_holder.hpp
index 82a38848a5..cb401759d0 100644
--- a/ext/asio/asio/detail/socket_holder.hpp
+++ b/ext/asio/asio/detail/socket_holder.hpp
@@ -1,8 +1,8 @@
//
-// socket_holder.hpp
-// ~~~~~~~~~~~~~~~~~
+// detail/socket_holder.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/socket_ops.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
@@ -46,7 +47,8 @@ public:
if (socket_ != invalid_socket)
{
asio::error_code ec;
- socket_ops::close(socket_, ec);
+ socket_ops::state_type state = 0;
+ socket_ops::close(socket_, state, true, ec);
}
}
@@ -62,7 +64,8 @@ public:
if (socket_ != invalid_socket)
{
asio::error_code ec;
- socket_ops::close(socket_, ec);
+ socket_ops::state_type state = 0;
+ socket_ops::close(socket_, state, true, ec);
socket_ = invalid_socket;
}
}
diff --git a/ext/asio/asio/detail/socket_ops.hpp b/ext/asio/asio/detail/socket_ops.hpp
index 1a863a9175..8ad464c909 100644
--- a/ext/asio/asio/detail/socket_ops.hpp
+++ b/ext/asio/asio/detail/socket_ops.hpp
@@ -1,8 +1,8 @@
//
-// socket_ops.hpp
-// ~~~~~~~~~~~~~~
+// detail/socket_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,193 +15,102 @@
# 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/assert.hpp>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <cerrno>
-#include <boost/detail/workaround.hpp>
-#include <new>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
-#include "asio/error.hpp"
+#include "asio/error_code.hpp"
+#include "asio/detail/shared_ptr.hpp"
#include "asio/detail/socket_types.hpp"
+#include "asio/detail/weak_ptr.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
namespace socket_ops {
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-struct msghdr { int msg_namelen; };
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+// Socket state bits.
+enum
+{
+ // The user wants a non-blocking socket.
+ user_set_non_blocking = 1,
-#if defined(__hpux)
-// HP-UX doesn't declare these functions extern "C", so they are declared again
-// here to avoid linker errors about undefined symbols.
-extern "C" char* if_indextoname(unsigned int, char*);
-extern "C" unsigned int if_nametoindex(const char*);
-#endif // defined(__hpux)
+ // The socket has been set non-blocking.
+ internal_non_blocking = 2,
-inline void clear_error(asio::error_code& ec)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- WSASetLastError(0);
-#else
- errno = 0;
-#endif
- ec = asio::error_code();
-}
-
-template <typename ReturnType>
-inline ReturnType error_wrapper(ReturnType return_value,
- asio::error_code& ec)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- ec = asio::error_code(WSAGetLastError(),
- asio::error::get_system_category());
-#else
- ec = asio::error_code(errno,
- asio::error::get_system_category());
-#endif
- return return_value;
-}
-
-template <typename SockLenType>
-inline socket_type call_accept(SockLenType msghdr::*,
- socket_type s, socket_addr_type* addr, std::size_t* addrlen)
-{
- SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0;
- socket_type result = ::accept(s, addr, addrlen ? &tmp_addrlen : 0);
- if (addrlen)
- *addrlen = (std::size_t)tmp_addrlen;
- return result;
-}
-
-inline socket_type accept(socket_type s, socket_addr_type* addr,
- std::size_t* addrlen, asio::error_code& ec)
-{
- clear_error(ec);
-
- socket_type new_s = error_wrapper(call_accept(
- &msghdr::msg_namelen, s, addr, addrlen), ec);
- if (new_s == invalid_socket)
- return new_s;
-
-#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
- int optval = 1;
- int result = error_wrapper(::setsockopt(new_s,
- SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec);
- if (result != 0)
- {
- ::close(new_s);
- return invalid_socket;
- }
-#endif
-
- clear_error(ec);
- return new_s;
-}
-
-template <typename SockLenType>
-inline int call_bind(SockLenType msghdr::*,
- socket_type s, const socket_addr_type* addr, std::size_t addrlen)
-{
- return ::bind(s, addr, (SockLenType)addrlen);
-}
+ // Helper "state" used to determine whether the socket is non-blocking.
+ non_blocking = user_set_non_blocking | internal_non_blocking,
-inline int bind(socket_type s, const socket_addr_type* addr,
- std::size_t addrlen, asio::error_code& ec)
-{
- clear_error(ec);
- int result = error_wrapper(call_bind(
- &msghdr::msg_namelen, s, addr, addrlen), ec);
- if (result == 0)
- clear_error(ec);
- return result;
-}
-
-inline int close(socket_type s, asio::error_code& ec)
-{
- clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- int result = error_wrapper(::closesocket(s), ec);
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- int result = error_wrapper(::close(s), ec);
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- if (result == 0)
- clear_error(ec);
- return result;
-}
+ // User wants connection_aborted errors, which are disabled by default.
+ enable_connection_aborted = 4,
-inline int shutdown(socket_type s, int what, asio::error_code& ec)
-{
- clear_error(ec);
- int result = error_wrapper(::shutdown(s, what), ec);
- if (result == 0)
- clear_error(ec);
- return result;
-}
-
-template <typename SockLenType>
-inline int call_connect(SockLenType msghdr::*,
- socket_type s, const socket_addr_type* addr, std::size_t addrlen)
-{
- return ::connect(s, addr, (SockLenType)addrlen);
-}
+ // The user set the linger option. Needs to be checked when closing.
+ user_set_linger = 8,
-inline int connect(socket_type s, const socket_addr_type* addr,
- std::size_t addrlen, asio::error_code& ec)
-{
- clear_error(ec);
- int result = error_wrapper(call_connect(
- &msghdr::msg_namelen, s, addr, addrlen), ec);
- if (result == 0)
- clear_error(ec);
- return result;
-}
-
-inline int socketpair(int af, int type, int protocol,
- socket_type sv[2], asio::error_code& ec)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- (void)(af);
- (void)(type);
- (void)(protocol);
- (void)(sv);
- ec = asio::error::operation_not_supported;
- return -1;
-#else
- clear_error(ec);
- int result = error_wrapper(::socketpair(af, type, protocol, sv), ec);
- if (result == 0)
- clear_error(ec);
- return result;
-#endif
-}
-
-inline int listen(socket_type s, int backlog, asio::error_code& ec)
-{
- clear_error(ec);
- int result = error_wrapper(::listen(s, backlog), ec);
- if (result == 0)
- clear_error(ec);
- return result;
-}
-
-inline void init_buf_iov_base(void*& base, void* addr)
-{
- base = addr;
-}
+ // The socket is stream-oriented.
+ stream_oriented = 16,
-template <typename T>
-inline void init_buf_iov_base(T& base, void* addr)
-{
- base = static_cast<T>(addr);
-}
+ // The socket is datagram-oriented.
+ datagram_oriented = 32
+};
+
+typedef unsigned char state_type;
+
+struct noop_deleter { void operator()(void*) {} };
+typedef shared_ptr<void> shared_cancel_token_type;
+typedef weak_ptr<void> weak_cancel_token_type;
+
+ASIO_DECL socket_type accept(socket_type s, socket_addr_type* addr,
+ std::size_t* addrlen, asio::error_code& ec);
+
+ASIO_DECL socket_type sync_accept(socket_type s,
+ state_type state, socket_addr_type* addr,
+ std::size_t* addrlen, asio::error_code& ec);
+
+#if defined(ASIO_HAS_IOCP)
+
+ASIO_DECL void complete_iocp_accept(socket_type s,
+ void* output_buffer, DWORD address_length,
+ socket_addr_type* addr, std::size_t* addrlen,
+ socket_type new_socket, asio::error_code& ec);
+
+#else // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL bool non_blocking_accept(socket_type s,
+ state_type state, socket_addr_type* addr, std::size_t* addrlen,
+ asio::error_code& ec, socket_type& new_socket);
+
+#endif // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL int bind(socket_type s, const socket_addr_type* addr,
+ std::size_t addrlen, asio::error_code& ec);
+
+ASIO_DECL int close(socket_type s, state_type& state,
+ bool destruction, asio::error_code& ec);
+
+ASIO_DECL bool set_internal_non_blocking(socket_type s,
+ state_type& state, asio::error_code& ec);
+
+ASIO_DECL int shutdown(socket_type s,
+ int what, asio::error_code& ec);
+
+ASIO_DECL int connect(socket_type s, const socket_addr_type* addr,
+ std::size_t addrlen, asio::error_code& ec);
+
+ASIO_DECL void sync_connect(socket_type s, const socket_addr_type* addr,
+ std::size_t addrlen, asio::error_code& ec);
+
+ASIO_DECL bool non_blocking_connect(
+ socket_type s, asio::error_code& ec);
+
+ASIO_DECL int socketpair(int af, int type, int protocol,
+ socket_type sv[2], asio::error_code& ec);
+
+ASIO_DECL bool sockatmark(socket_type s, asio::error_code& ec);
+
+ASIO_DECL size_t available(socket_type s, asio::error_code& ec);
+
+ASIO_DECL int listen(socket_type s,
+ int backlog, asio::error_code& ec);
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
typedef WSABUF buf;
@@ -209,1699 +118,163 @@ typedef WSABUF buf;
typedef iovec buf;
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-inline void init_buf(buf& b, void* data, size_t size)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- b.buf = static_cast<char*>(data);
- b.len = static_cast<u_long>(size);
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- init_buf_iov_base(b.iov_base, data);
- b.iov_len = size;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ASIO_DECL void init_buf(buf& b, void* data, size_t size);
-inline void init_buf(buf& b, const void* data, size_t size)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- b.buf = static_cast<char*>(const_cast<void*>(data));
- b.len = static_cast<u_long>(size);
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- init_buf_iov_base(b.iov_base, const_cast<void*>(data));
- b.iov_len = size;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ASIO_DECL void init_buf(buf& b, const void* data, size_t size);
-inline void init_msghdr_msg_name(void*& name, socket_addr_type* addr)
-{
- name = addr;
-}
+ASIO_DECL int recv(socket_type s, buf* bufs, size_t count, int flags,
+ asio::error_code& ec);
-inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr)
-{
- name = const_cast<socket_addr_type*>(addr);
-}
+ASIO_DECL size_t sync_recv(socket_type s, state_type state, buf* bufs,
+ size_t count, int flags, bool all_empty, asio::error_code& ec);
-template <typename T>
-inline void init_msghdr_msg_name(T& name, socket_addr_type* addr)
-{
- name = reinterpret_cast<T>(addr);
-}
+#if defined(ASIO_HAS_IOCP)
-template <typename T>
-inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr)
-{
- name = reinterpret_cast<T>(const_cast<socket_addr_type*>(addr));
-}
+ASIO_DECL void complete_iocp_recv(state_type state,
+ const weak_cancel_token_type& cancel_token, bool all_empty,
+ asio::error_code& ec, size_t bytes_transferred);
-inline int recv(socket_type s, buf* bufs, size_t count, int flags,
- asio::error_code& ec)
-{
- clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- // Receive some data.
- DWORD recv_buf_count = static_cast<DWORD>(count);
- DWORD bytes_transferred = 0;
- DWORD recv_flags = flags;
- int result = error_wrapper(::WSARecv(s, bufs,
- recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec);
- if (result != 0)
- return -1;
- clear_error(ec);
- return bytes_transferred;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- msghdr msg = msghdr();
- msg.msg_iov = bufs;
- msg.msg_iovlen = count;
- int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
- if (result >= 0)
- clear_error(ec);
- return result;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+#else // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL bool non_blocking_recv(socket_type s,
+ buf* bufs, size_t count, int flags, bool is_stream,
+ asio::error_code& ec, size_t& bytes_transferred);
+
+#endif // defined(ASIO_HAS_IOCP)
-inline int recvfrom(socket_type s, buf* bufs, size_t count, int flags,
+ASIO_DECL int recvfrom(socket_type s, buf* bufs, size_t count, int flags,
socket_addr_type* addr, std::size_t* addrlen,
- asio::error_code& ec)
-{
- clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- // Receive some data.
- DWORD recv_buf_count = static_cast<DWORD>(count);
- DWORD bytes_transferred = 0;
- DWORD recv_flags = flags;
- int tmp_addrlen = (int)*addrlen;
- int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count,
- &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0), ec);
- *addrlen = (std::size_t)tmp_addrlen;
- if (result != 0)
- return -1;
- clear_error(ec);
- return bytes_transferred;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- msghdr msg = msghdr();
- init_msghdr_msg_name(msg.msg_name, addr);
- msg.msg_namelen = *addrlen;
- msg.msg_iov = bufs;
- msg.msg_iovlen = count;
- int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
- *addrlen = msg.msg_namelen;
- if (result >= 0)
- clear_error(ec);
- return result;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ asio::error_code& ec);
-inline int send(socket_type s, const buf* bufs, size_t count, int flags,
- asio::error_code& ec)
-{
- clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- // Send the data.
- DWORD send_buf_count = static_cast<DWORD>(count);
- DWORD bytes_transferred = 0;
- DWORD send_flags = flags;
- int result = error_wrapper(::WSASend(s, const_cast<buf*>(bufs),
- send_buf_count, &bytes_transferred, send_flags, 0, 0), ec);
- if (result != 0)
- return -1;
- clear_error(ec);
- return bytes_transferred;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- msghdr msg = msghdr();
- msg.msg_iov = const_cast<buf*>(bufs);
- msg.msg_iovlen = count;
-#if defined(__linux__)
- flags |= MSG_NOSIGNAL;
-#endif // defined(__linux__)
- int result = error_wrapper(::sendmsg(s, &msg, flags), ec);
- if (result >= 0)
- clear_error(ec);
- return result;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state,
+ buf* bufs, size_t count, int flags, socket_addr_type* addr,
+ std::size_t* addrlen, asio::error_code& ec);
+
+#if defined(ASIO_HAS_IOCP)
+
+ASIO_DECL void complete_iocp_recvfrom(
+ const weak_cancel_token_type& cancel_token,
+ asio::error_code& ec);
+
+#else // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL bool non_blocking_recvfrom(socket_type s,
+ buf* bufs, size_t count, int flags,
+ socket_addr_type* addr, std::size_t* addrlen,
+ asio::error_code& ec, size_t& bytes_transferred);
+
+#endif // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL int send(socket_type s, const buf* bufs,
+ size_t count, int flags, asio::error_code& ec);
+
+ASIO_DECL size_t sync_send(socket_type s, state_type state,
+ const buf* bufs, size_t count, int flags,
+ bool all_empty, asio::error_code& ec);
+
+#if defined(ASIO_HAS_IOCP)
+
+ASIO_DECL void complete_iocp_send(
+ const weak_cancel_token_type& cancel_token,
+ asio::error_code& ec);
+
+#else // defined(ASIO_HAS_IOCP)
-inline int sendto(socket_type s, const buf* bufs, size_t count, int flags,
+ASIO_DECL bool non_blocking_send(socket_type s,
+ const buf* bufs, size_t count, int flags,
+ asio::error_code& ec, size_t& bytes_transferred);
+
+#endif // defined(ASIO_HAS_IOCP)
+
+ASIO_DECL int sendto(socket_type s, const buf* bufs, size_t count,
+ int flags, const socket_addr_type* addr, std::size_t addrlen,
+ asio::error_code& ec);
+
+ASIO_DECL size_t sync_sendto(socket_type s, state_type state,
+ const buf* bufs, size_t count, int flags, const socket_addr_type* addr,
+ std::size_t addrlen, asio::error_code& ec);
+
+#if !defined(ASIO_HAS_IOCP)
+
+ASIO_DECL bool non_blocking_sendto(socket_type s,
+ const buf* bufs, size_t count, int flags,
const socket_addr_type* addr, std::size_t addrlen,
- asio::error_code& ec)
-{
- clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- // Send the data.
- DWORD send_buf_count = static_cast<DWORD>(count);
- DWORD bytes_transferred = 0;
- int result = error_wrapper(::WSASendTo(s, const_cast<buf*>(bufs),
- send_buf_count, &bytes_transferred, flags, addr,
- static_cast<int>(addrlen), 0, 0), ec);
- if (result != 0)
- return -1;
- clear_error(ec);
- return bytes_transferred;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- msghdr msg = msghdr();
- init_msghdr_msg_name(msg.msg_name, addr);
- msg.msg_namelen = addrlen;
- msg.msg_iov = const_cast<buf*>(bufs);
- msg.msg_iovlen = count;
-#if defined(__linux__)
- flags |= MSG_NOSIGNAL;
-#endif // defined(__linux__)
- int result = error_wrapper(::sendmsg(s, &msg, flags), ec);
- if (result >= 0)
- clear_error(ec);
- return result;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ asio::error_code& ec, size_t& bytes_transferred);
-inline socket_type socket(int af, int type, int protocol,
- asio::error_code& ec)
-{
- clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- socket_type s = error_wrapper(::WSASocket(af, type, protocol, 0, 0,
- WSA_FLAG_OVERLAPPED), ec);
- if (s == invalid_socket)
- return s;
-
- if (af == AF_INET6)
- {
- // Try to enable the POSIX default behaviour of having IPV6_V6ONLY set to
- // false. This will only succeed on Windows Vista and later versions of
- // Windows, where a dual-stack IPv4/v6 implementation is available.
- DWORD optval = 0;
- ::setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
- reinterpret_cast<const char*>(&optval), sizeof(optval));
- }
-
- clear_error(ec);
-
- return s;
-#elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
- socket_type s = error_wrapper(::socket(af, type, protocol), ec);
- if (s == invalid_socket)
- return s;
-
- int optval = 1;
- int result = error_wrapper(::setsockopt(s,
- SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec);
- if (result != 0)
- {
- ::close(s);
- return invalid_socket;
- }
-
- return s;
-#else
- int s = error_wrapper(::socket(af, type, protocol), ec);
- if (s >= 0)
- clear_error(ec);
- return s;
-#endif
-}
-
-template <typename SockLenType>
-inline int call_setsockopt(SockLenType msghdr::*,
- socket_type s, int level, int optname,
- const void* optval, std::size_t optlen)
-{
- return ::setsockopt(s, level, optname,
- (const char*)optval, (SockLenType)optlen);
-}
+#endif // !defined(ASIO_HAS_IOCP)
-inline int setsockopt(socket_type s, int level, int optname,
- const void* optval, std::size_t optlen, asio::error_code& ec)
-{
- if (level == custom_socket_option_level && optname == always_fail_option)
- {
- ec = asio::error::invalid_argument;
- return -1;
- }
-
-#if defined(__BORLANDC__)
- // Mysteriously, using the getsockopt and setsockopt functions directly with
- // Borland C++ results in incorrect values being set and read. The bug can be
- // worked around by using function addresses resolved with GetProcAddress.
- if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
- {
- typedef int (WSAAPI *sso_t)(SOCKET, int, int, const char*, int);
- if (sso_t sso = (sso_t)::GetProcAddress(winsock_module, "setsockopt"))
- {
- clear_error(ec);
- return error_wrapper(sso(s, level, optname,
- reinterpret_cast<const char*>(optval),
- static_cast<int>(optlen)), ec);
- }
- }
- ec = asio::error::fault;
- return -1;
-#else // defined(__BORLANDC__)
- clear_error(ec);
- int result = error_wrapper(call_setsockopt(&msghdr::msg_namelen,
- s, level, optname, optval, optlen), ec);
- if (result == 0)
- clear_error(ec);
- return result;
-#endif // defined(__BORLANDC__)
-}
-
-template <typename SockLenType>
-inline int call_getsockopt(SockLenType msghdr::*,
- socket_type s, int level, int optname,
- void* optval, std::size_t* optlen)
-{
- SockLenType tmp_optlen = (SockLenType)*optlen;
- int result = ::getsockopt(s, level, optname, (char*)optval, &tmp_optlen);
- *optlen = (std::size_t)tmp_optlen;
- return result;
-}
-
-inline int getsockopt(socket_type s, int level, int optname, void* optval,
- size_t* optlen, asio::error_code& ec)
-{
- if (level == custom_socket_option_level && optname == always_fail_option)
- {
- ec = asio::error::invalid_argument;
- return -1;
- }
-
-#if defined(__BORLANDC__)
- // Mysteriously, using the getsockopt and setsockopt functions directly with
- // Borland C++ results in incorrect values being set and read. The bug can be
- // worked around by using function addresses resolved with GetProcAddress.
- if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
- {
- typedef int (WSAAPI *gso_t)(SOCKET, int, int, char*, int*);
- if (gso_t gso = (gso_t)::GetProcAddress(winsock_module, "getsockopt"))
- {
- clear_error(ec);
- int tmp_optlen = static_cast<int>(*optlen);
- int result = error_wrapper(gso(s, level, optname,
- reinterpret_cast<char*>(optval), &tmp_optlen), ec);
- *optlen = static_cast<size_t>(tmp_optlen);
- if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
- && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
- {
- // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are
- // only supported on Windows Vista and later. To simplify program logic
- // we will fake success of getting this option and specify that the
- // value is non-zero (i.e. true). This corresponds to the behavior of
- // IPv6 sockets on Windows platforms pre-Vista.
- *static_cast<DWORD*>(optval) = 1;
- clear_error(ec);
- }
- return result;
- }
- }
- ec = asio::error::fault;
- return -1;
-#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- clear_error(ec);
- int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
- s, level, optname, optval, optlen), ec);
- if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
- && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
- {
- // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are only
- // supported on Windows Vista and later. To simplify program logic we will
- // fake success of getting this option and specify that the value is
- // non-zero (i.e. true). This corresponds to the behavior of IPv6 sockets
- // on Windows platforms pre-Vista.
- *static_cast<DWORD*>(optval) = 1;
- clear_error(ec);
- }
- if (result == 0)
- clear_error(ec);
- return result;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- clear_error(ec);
- int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
- s, level, optname, optval, optlen), ec);
-#if defined(__linux__)
- if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int)
- && (optname == SO_SNDBUF || optname == SO_RCVBUF))
- {
- // On Linux, setting SO_SNDBUF or SO_RCVBUF to N actually causes the kernel
- // to set the buffer size to N*2. Linux puts additional stuff into the
- // buffers so that only about half is actually available to the application.
- // The retrieved value is divided by 2 here to make it appear as though the
- // correct value has been set.
- *static_cast<int*>(optval) /= 2;
- }
-#endif // defined(__linux__)
- if (result == 0)
- clear_error(ec);
- return result;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ASIO_DECL socket_type socket(int af, int type, int protocol,
+ asio::error_code& ec);
-template <typename SockLenType>
-inline int call_getpeername(SockLenType msghdr::*,
- socket_type s, socket_addr_type* addr, std::size_t* addrlen)
-{
- SockLenType tmp_addrlen = (SockLenType)*addrlen;
- int result = ::getpeername(s, addr, &tmp_addrlen);
- *addrlen = (std::size_t)tmp_addrlen;
- return result;
-}
-
-inline int getpeername(socket_type s, socket_addr_type* addr,
- std::size_t* addrlen, asio::error_code& ec)
-{
- clear_error(ec);
- int result = error_wrapper(call_getpeername(
- &msghdr::msg_namelen, s, addr, addrlen), ec);
- if (result == 0)
- clear_error(ec);
- return result;
-}
-
-template <typename SockLenType>
-inline int call_getsockname(SockLenType msghdr::*,
- socket_type s, socket_addr_type* addr, std::size_t* addrlen)
-{
- SockLenType tmp_addrlen = (SockLenType)*addrlen;
- int result = ::getsockname(s, addr, &tmp_addrlen);
- *addrlen = (std::size_t)tmp_addrlen;
- return result;
-}
-
-inline int getsockname(socket_type s, socket_addr_type* addr,
- std::size_t* addrlen, asio::error_code& ec)
-{
- clear_error(ec);
- int result = error_wrapper(call_getsockname(
- &msghdr::msg_namelen, s, addr, addrlen), ec);
- if (result == 0)
- clear_error(ec);
- return result;
-}
-
-inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg,
- asio::error_code& ec)
-{
- clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- int result = error_wrapper(::ioctlsocket(s, cmd, arg), ec);
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- int result = error_wrapper(::ioctl(s, cmd, arg), ec);
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- if (result >= 0)
- clear_error(ec);
- return result;
-}
+ASIO_DECL int setsockopt(socket_type s, state_type& state,
+ int level, int optname, const void* optval,
+ std::size_t optlen, asio::error_code& ec);
-inline int select(int nfds, fd_set* readfds, fd_set* writefds,
- fd_set* exceptfds, timeval* timeout, asio::error_code& ec)
-{
- clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- if (!readfds && !writefds && !exceptfds && timeout)
- {
- DWORD milliseconds = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
- if (milliseconds == 0)
- milliseconds = 1; // Force context switch.
- ::Sleep(milliseconds);
- ec = asio::error_code();
- return 0;
- }
-
- // The select() call allows timeout values measured in microseconds, but the
- // system clock (as wrapped by boost::posix_time::microsec_clock) typically
- // has a resolution of 10 milliseconds. This can lead to a spinning select
- // reactor, meaning increased CPU usage, when waiting for the earliest
- // scheduled timeout if it's less than 10 milliseconds away. To avoid a tight
- // spin we'll use a minimum timeout of 1 millisecond.
- if (timeout && timeout->tv_sec == 0
- && timeout->tv_usec > 0 && timeout->tv_usec < 1000)
- timeout->tv_usec = 1000;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ASIO_DECL int getsockopt(socket_type s, state_type state,
+ int level, int optname, void* optval,
+ size_t* optlen, asio::error_code& ec);
-#if defined(__hpux) && defined(__HP_aCC)
- timespec ts;
- ts.tv_sec = timeout ? timeout->tv_sec : 0;
- ts.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0;
- return error_wrapper(::pselect(nfds, readfds,
- writefds, exceptfds, timeout ? &ts : 0, 0), ec);
-#else
- int result = error_wrapper(::select(nfds, readfds,
- writefds, exceptfds, timeout), ec);
- if (result >= 0)
- clear_error(ec);
- return result;
-#endif
-}
-
-inline int poll_read(socket_type s, asio::error_code& ec)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- FD_SET fds;
- FD_ZERO(&fds);
- FD_SET(s, &fds);
- clear_error(ec);
- int result = error_wrapper(::select(s, &fds, 0, 0, 0), ec);
- if (result >= 0)
- clear_error(ec);
- return result;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- pollfd fds;
- fds.fd = s;
- 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;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ASIO_DECL int getpeername(socket_type s, socket_addr_type* addr,
+ std::size_t* addrlen, bool cached, asio::error_code& ec);
-inline int poll_write(socket_type s, asio::error_code& ec)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- FD_SET fds;
- FD_ZERO(&fds);
- FD_SET(s, &fds);
- clear_error(ec);
- int result = error_wrapper(::select(s, 0, &fds, 0, 0), ec);
- if (result >= 0)
- clear_error(ec);
- return result;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- pollfd fds;
- fds.fd = s;
- 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;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ASIO_DECL int getsockname(socket_type s, socket_addr_type* addr,
+ std::size_t* addrlen, asio::error_code& ec);
-inline int poll_connect(socket_type s, asio::error_code& ec)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- FD_SET write_fds;
- FD_ZERO(&write_fds);
- FD_SET(s, &write_fds);
- FD_SET except_fds;
- FD_ZERO(&except_fds);
- FD_SET(s, &except_fds);
- clear_error(ec);
- int result = error_wrapper(::select(s, 0, &write_fds, &except_fds, 0), ec);
- if (result >= 0)
- clear_error(ec);
- return result;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- pollfd fds;
- fds.fd = s;
- 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;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ASIO_DECL int ioctl(socket_type s, state_type& state,
+ int cmd, ioctl_arg_type* arg, asio::error_code& ec);
-inline const char* inet_ntop(int af, const void* src, char* dest, size_t length,
- unsigned long scope_id, asio::error_code& ec)
-{
- clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- using namespace std; // For memcpy.
-
- if (af != AF_INET && af != AF_INET6)
- {
- ec = asio::error::address_family_not_supported;
- return 0;
- }
-
- union
- {
- socket_addr_type base;
- sockaddr_storage_type storage;
- sockaddr_in4_type v4;
- sockaddr_in6_type v6;
- } address;
- DWORD address_length;
- if (af == AF_INET)
- {
- address_length = sizeof(sockaddr_in4_type);
- address.v4.sin_family = AF_INET;
- address.v4.sin_port = 0;
- memcpy(&address.v4.sin_addr, src, sizeof(in4_addr_type));
- }
- else // AF_INET6
- {
- address_length = sizeof(sockaddr_in6_type);
- address.v6.sin6_family = AF_INET6;
- address.v6.sin6_port = 0;
- address.v6.sin6_flowinfo = 0;
- address.v6.sin6_scope_id = scope_id;
- memcpy(&address.v6.sin6_addr, src, sizeof(in6_addr_type));
- }
-
- DWORD string_length = static_cast<DWORD>(length);
-#if defined(BOOST_NO_ANSI_APIS)
- LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR));
- int result = error_wrapper(::WSAAddressToStringW(&address.base,
- address_length, 0, string_buffer, &string_length), ec);
- ::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1, dest, length, 0, 0);
-#else
- int result = error_wrapper(::WSAAddressToStringA(
- &address.base, address_length, 0, dest, &string_length), ec);
-#endif
-
- // Windows may set error code on success.
- if (result != socket_error_retval)
- clear_error(ec);
-
- // Windows may not set an error code on failure.
- else if (result == socket_error_retval && !ec)
- ec = asio::error::invalid_argument;
-
- return result == socket_error_retval ? 0 : dest;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- const char* result = error_wrapper(::inet_ntop(af, src, dest, length), ec);
- if (result == 0 && !ec)
- ec = asio::error::invalid_argument;
- if (result != 0 && af == AF_INET6 && scope_id != 0)
- {
- using namespace std; // For strcat and sprintf.
- char if_name[IF_NAMESIZE + 1] = "%";
- const in6_addr_type* ipv6_address = static_cast<const in6_addr_type*>(src);
- bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address);
- if (!is_link_local || if_indextoname(scope_id, if_name + 1) == 0)
- sprintf(if_name + 1, "%lu", scope_id);
- strcat(dest, if_name);
- }
- return result;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ASIO_DECL int select(int nfds, fd_set* readfds, fd_set* writefds,
+ fd_set* exceptfds, timeval* timeout, asio::error_code& ec);
-inline int inet_pton(int af, const char* src, void* dest,
- unsigned long* scope_id, asio::error_code& ec)
-{
- clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- using namespace std; // For memcpy and strcmp.
-
- if (af != AF_INET && af != AF_INET6)
- {
- ec = asio::error::address_family_not_supported;
- return -1;
- }
-
- union
- {
- socket_addr_type base;
- sockaddr_storage_type storage;
- sockaddr_in4_type v4;
- sockaddr_in6_type v6;
- } address;
- int address_length = sizeof(sockaddr_storage_type);
-#if defined(BOOST_NO_ANSI_APIS)
- int num_wide_chars = strlen(src) + 1;
- LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR));
- ::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars);
- int result = error_wrapper(::WSAStringToAddressW(
- wide_buffer, af, 0, &address.base, &address_length), ec);
-#else
- int result = error_wrapper(::WSAStringToAddressA(
- const_cast<char*>(src), af, 0, &address.base, &address_length), ec);
-#endif
-
- if (af == AF_INET)
- {
- if (result != socket_error_retval)
- {
- memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type));
- clear_error(ec);
- }
- else if (strcmp(src, "255.255.255.255") == 0)
- {
- static_cast<in4_addr_type*>(dest)->s_addr = INADDR_NONE;
- clear_error(ec);
- }
- }
- else // AF_INET6
- {
- if (result != socket_error_retval)
- {
- memcpy(dest, &address.v6.sin6_addr, sizeof(in6_addr_type));
- if (scope_id)
- *scope_id = address.v6.sin6_scope_id;
- clear_error(ec);
- }
- }
-
- // Windows may not set an error code on failure.
- if (result == socket_error_retval && !ec)
- ec = asio::error::invalid_argument;
-
- if (result != socket_error_retval)
- clear_error(ec);
-
- return result == socket_error_retval ? -1 : 1;
-#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- int result = error_wrapper(::inet_pton(af, src, dest), ec);
- if (result <= 0 && !ec)
- ec = asio::error::invalid_argument;
- if (result > 0 && af == AF_INET6 && scope_id)
- {
- using namespace std; // For strchr and atoi.
- *scope_id = 0;
- if (const char* if_name = strchr(src, '%'))
- {
- in6_addr_type* ipv6_address = static_cast<in6_addr_type*>(dest);
- bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address);
- if (is_link_local)
- *scope_id = if_nametoindex(if_name + 1);
- if (*scope_id == 0)
- *scope_id = atoi(if_name + 1);
- }
- }
- return result;
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-}
+ASIO_DECL int poll_read(socket_type s, asio::error_code& ec);
-inline int gethostname(char* name, int namelen, asio::error_code& ec)
-{
- clear_error(ec);
- int result = error_wrapper(::gethostname(name, namelen), ec);
-#if defined(BOOST_WINDOWS)
- if (result == 0)
- clear_error(ec);
-#endif
- return result;
-}
-
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) \
- || defined(__MACH__) && defined(__APPLE__)
-
-// The following functions are only needed for emulation of getaddrinfo and
-// getnameinfo.
-
-inline asio::error_code translate_netdb_error(int error)
-{
- switch (error)
- {
- case 0:
- return asio::error_code();
- case HOST_NOT_FOUND:
- return asio::error::host_not_found;
- case TRY_AGAIN:
- return asio::error::host_not_found_try_again;
- case NO_RECOVERY:
- return asio::error::no_recovery;
- case NO_DATA:
- return asio::error::no_data;
- default:
- BOOST_ASSERT(false);
- return asio::error::invalid_argument;
- }
-}
-
-inline hostent* gethostbyaddr(const char* addr, int length, int af,
- hostent* result, char* buffer, int buflength, asio::error_code& ec)
-{
- clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- (void)(buffer);
- (void)(buflength);
- hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec);
- if (!retval)
- return 0;
- clear_error(ec);
- *result = *retval;
- return retval;
-#elif defined(__sun) || defined(__QNX__)
- int error = 0;
- hostent* retval = error_wrapper(::gethostbyaddr_r(addr, length, af, result,
- buffer, buflength, &error), ec);
- if (error)
- ec = translate_netdb_error(error);
- return retval;
-#elif defined(__MACH__) && defined(__APPLE__)
- (void)(buffer);
- (void)(buflength);
- int error = 0;
- hostent* retval = error_wrapper(::getipnodebyaddr(
- addr, length, af, &error), ec);
- if (error)
- ec = translate_netdb_error(error);
- if (!retval)
- return 0;
- *result = *retval;
- return retval;
-#else
- hostent* retval = 0;
- int error = 0;
- error_wrapper(::gethostbyaddr_r(addr, length, af, result, buffer,
- buflength, &retval, &error), ec);
- if (error)
- ec = translate_netdb_error(error);
- return retval;
-#endif
-}
-
-inline hostent* gethostbyname(const char* name, int af, struct hostent* result,
- char* buffer, int buflength, int ai_flags, asio::error_code& ec)
-{
- clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- (void)(buffer);
- (void)(buflength);
- (void)(ai_flags);
- if (af != AF_INET)
- {
- ec = asio::error::address_family_not_supported;
- return 0;
- }
- hostent* retval = error_wrapper(::gethostbyname(name), ec);
- if (!retval)
- return 0;
- clear_error(ec);
- *result = *retval;
- return result;
-#elif defined(__sun) || defined(__QNX__)
- (void)(ai_flags);
- if (af != AF_INET)
- {
- ec = asio::error::address_family_not_supported;
- return 0;
- }
- int error = 0;
- hostent* retval = error_wrapper(::gethostbyname_r(name, result, buffer,
- buflength, &error), ec);
- if (error)
- ec = translate_netdb_error(error);
- return retval;
-#elif defined(__MACH__) && defined(__APPLE__)
- (void)(buffer);
- (void)(buflength);
- int error = 0;
- hostent* retval = error_wrapper(::getipnodebyname(
- name, af, ai_flags, &error), ec);
- if (error)
- ec = translate_netdb_error(error);
- if (!retval)
- return 0;
- *result = *retval;
- return retval;
-#else
- (void)(ai_flags);
- if (af != AF_INET)
- {
- ec = asio::error::address_family_not_supported;
- return 0;
- }
- hostent* retval = 0;
- int error = 0;
- error_wrapper(::gethostbyname_r(name, result,
- buffer, buflength, &retval, &error), ec);
- if (error)
- ec = translate_netdb_error(error);
- return retval;
-#endif
-}
-
-inline void freehostent(hostent* h)
-{
-#if defined(__MACH__) && defined(__APPLE__)
- if (h)
- ::freehostent(h);
-#else
- (void)(h);
-#endif
-}
-
-// Emulation of getaddrinfo based on implementation in:
-// Stevens, W. R., UNIX Network Programming Vol. 1, 2nd Ed., Prentice-Hall 1998.
-
-struct gai_search
-{
- const char* host;
- int family;
-};
+ASIO_DECL int poll_write(socket_type s, asio::error_code& ec);
-inline int gai_nsearch(const char* host,
- const addrinfo_type* hints, gai_search (&search)[2])
-{
- int search_count = 0;
- if (host == 0 || host[0] == '\0')
- {
- if (hints->ai_flags & AI_PASSIVE)
- {
- // No host and AI_PASSIVE implies wildcard bind.
- switch (hints->ai_family)
- {
- case AF_INET:
- search[search_count].host = "0.0.0.0";
- search[search_count].family = AF_INET;
- ++search_count;
- break;
- case AF_INET6:
- search[search_count].host = "0::0";
- search[search_count].family = AF_INET6;
- ++search_count;
- break;
- case AF_UNSPEC:
- search[search_count].host = "0::0";
- search[search_count].family = AF_INET6;
- ++search_count;
- search[search_count].host = "0.0.0.0";
- search[search_count].family = AF_INET;
- ++search_count;
- break;
- default:
- break;
- }
- }
- else
- {
- // No host and not AI_PASSIVE means connect to local host.
- switch (hints->ai_family)
- {
- case AF_INET:
- search[search_count].host = "localhost";
- search[search_count].family = AF_INET;
- ++search_count;
- break;
- case AF_INET6:
- search[search_count].host = "localhost";
- search[search_count].family = AF_INET6;
- ++search_count;
- break;
- case AF_UNSPEC:
- search[search_count].host = "localhost";
- search[search_count].family = AF_INET6;
- ++search_count;
- search[search_count].host = "localhost";
- search[search_count].family = AF_INET;
- ++search_count;
- break;
- default:
- break;
- }
- }
- }
- else
- {
- // Host is specified.
- switch (hints->ai_family)
- {
- case AF_INET:
- search[search_count].host = host;
- search[search_count].family = AF_INET;
- ++search_count;
- break;
- case AF_INET6:
- search[search_count].host = host;
- search[search_count].family = AF_INET6;
- ++search_count;
- break;
- case AF_UNSPEC:
- search[search_count].host = host;
- search[search_count].family = AF_INET6;
- ++search_count;
- search[search_count].host = host;
- search[search_count].family = AF_INET;
- ++search_count;
- break;
- default:
- break;
- }
- }
- return search_count;
-}
-
-template <typename T>
-inline T* gai_alloc(std::size_t size = sizeof(T))
-{
- using namespace std;
- T* p = static_cast<T*>(::operator new(size, std::nothrow));
- if (p)
- memset(p, 0, size);
- return p;
-}
-
-inline void gai_free(void* p)
-{
- ::operator delete(p);
-}
+ASIO_DECL int poll_connect(socket_type s, asio::error_code& ec);
-inline void gai_strcpy(char* target, const char* source, std::size_t max_size)
-{
- using namespace std;
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
- strcpy_s(target, max_size, source);
-#else
- *target = 0;
- strncat(target, source, max_size);
-#endif
-}
-
-enum { gai_clone_flag = 1 << 30 };
-
-inline int gai_aistruct(addrinfo_type*** next, const addrinfo_type* hints,
- const void* addr, int family)
-{
- using namespace std;
-
- addrinfo_type* ai = gai_alloc<addrinfo_type>();
- if (ai == 0)
- return EAI_MEMORY;
-
- ai->ai_next = 0;
- **next = ai;
- *next = &ai->ai_next;
-
- ai->ai_canonname = 0;
- ai->ai_socktype = hints->ai_socktype;
- if (ai->ai_socktype == 0)
- ai->ai_flags |= gai_clone_flag;
- ai->ai_protocol = hints->ai_protocol;
- ai->ai_family = family;
-
- switch (ai->ai_family)
- {
- case AF_INET:
- {
- sockaddr_in4_type* sinptr = gai_alloc<sockaddr_in4_type>();
- if (sinptr == 0)
- return EAI_MEMORY;
- sinptr->sin_family = AF_INET;
- memcpy(&sinptr->sin_addr, addr, sizeof(in4_addr_type));
- ai->ai_addr = reinterpret_cast<sockaddr*>(sinptr);
- ai->ai_addrlen = sizeof(sockaddr_in4_type);
- break;
- }
- case AF_INET6:
- {
- sockaddr_in6_type* sin6ptr = gai_alloc<sockaddr_in6_type>();
- if (sin6ptr == 0)
- return EAI_MEMORY;
- sin6ptr->sin6_family = AF_INET6;
- memcpy(&sin6ptr->sin6_addr, addr, sizeof(in6_addr_type));
- ai->ai_addr = reinterpret_cast<sockaddr*>(sin6ptr);
- ai->ai_addrlen = sizeof(sockaddr_in6_type);
- break;
- }
- default:
- break;
- }
-
- return 0;
-}
-
-inline addrinfo_type* gai_clone(addrinfo_type* ai)
-{
- using namespace std;
+ASIO_DECL const char* inet_ntop(int af, const void* src, char* dest,
+ size_t length, unsigned long scope_id, asio::error_code& ec);
- addrinfo_type* new_ai = gai_alloc<addrinfo_type>();
- if (new_ai == 0)
- return new_ai;
+ASIO_DECL int inet_pton(int af, const char* src, void* dest,
+ unsigned long* scope_id, asio::error_code& ec);
- new_ai->ai_next = ai->ai_next;
- ai->ai_next = new_ai;
+ASIO_DECL int gethostname(char* name,
+ int namelen, asio::error_code& ec);
- new_ai->ai_flags = 0;
- new_ai->ai_family = ai->ai_family;
- new_ai->ai_socktype = ai->ai_socktype;
- new_ai->ai_protocol = ai->ai_protocol;
- new_ai->ai_canonname = 0;
- new_ai->ai_addrlen = ai->ai_addrlen;
- new_ai->ai_addr = gai_alloc<sockaddr>(ai->ai_addrlen);
- memcpy(new_ai->ai_addr, ai->ai_addr, ai->ai_addrlen);
+ASIO_DECL asio::error_code getaddrinfo(const char* host,
+ const char* service, const addrinfo_type& hints,
+ addrinfo_type** result, asio::error_code& ec);
- return new_ai;
-}
+ASIO_DECL asio::error_code background_getaddrinfo(
+ const weak_cancel_token_type& cancel_token, const char* host,
+ const char* service, const addrinfo_type& hints,
+ addrinfo_type** result, asio::error_code& ec);
-inline int gai_port(addrinfo_type* aihead, int port, int socktype)
-{
- int num_found = 0;
-
- for (addrinfo_type* ai = aihead; ai; ai = ai->ai_next)
- {
- if (ai->ai_flags & gai_clone_flag)
- {
- if (ai->ai_socktype != 0)
- {
- ai = gai_clone(ai);
- if (ai == 0)
- return -1;
- // ai now points to newly cloned entry.
- }
- }
- else if (ai->ai_socktype != socktype)
- {
- // Ignore if mismatch on socket type.
- continue;
- }
-
- ai->ai_socktype = socktype;
-
- switch (ai->ai_family)
- {
- case AF_INET:
- {
- sockaddr_in4_type* sinptr =
- reinterpret_cast<sockaddr_in4_type*>(ai->ai_addr);
- sinptr->sin_port = port;
- ++num_found;
- break;
- }
- case AF_INET6:
- {
- sockaddr_in6_type* sin6ptr =
- reinterpret_cast<sockaddr_in6_type*>(ai->ai_addr);
- sin6ptr->sin6_port = port;
- ++num_found;
- break;
- }
- default:
- break;
- }
- }
-
- return num_found;
-}
-
-inline int gai_serv(addrinfo_type* aihead,
- const addrinfo_type* hints, const char* serv)
-{
- using namespace std;
-
- int num_found = 0;
-
- if (
-#if defined(AI_NUMERICSERV)
- (hints->ai_flags & AI_NUMERICSERV) ||
-#endif
- isdigit(serv[0]))
- {
- int port = htons(atoi(serv));
- if (hints->ai_socktype)
- {
- // Caller specifies socket type.
- int rc = gai_port(aihead, port, hints->ai_socktype);
- if (rc < 0)
- return EAI_MEMORY;
- num_found += rc;
- }
- else
- {
- // Caller does not specify socket type.
- int rc = gai_port(aihead, port, SOCK_STREAM);
- if (rc < 0)
- return EAI_MEMORY;
- num_found += rc;
- rc = gai_port(aihead, port, SOCK_DGRAM);
- if (rc < 0)
- return EAI_MEMORY;
- num_found += rc;
- }
- }
- else
- {
- // Try service name with TCP first, then UDP.
- if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_STREAM)
- {
- servent* sptr = getservbyname(serv, "tcp");
- if (sptr != 0)
- {
- int rc = gai_port(aihead, sptr->s_port, SOCK_STREAM);
- if (rc < 0)
- return EAI_MEMORY;
- num_found += rc;
- }
- }
- if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_DGRAM)
- {
- servent* sptr = getservbyname(serv, "udp");
- if (sptr != 0)
- {
- int rc = gai_port(aihead, sptr->s_port, SOCK_DGRAM);
- if (rc < 0)
- return EAI_MEMORY;
- num_found += rc;
- }
- }
- }
-
- if (num_found == 0)
- {
- if (hints->ai_socktype == 0)
- {
- // All calls to getservbyname() failed.
- return EAI_NONAME;
- }
- else
- {
- // Service not supported for socket type.
- return EAI_SERVICE;
- }
- }
-
- return 0;
-}
-
-inline int gai_echeck(const char* host, const char* service,
- int flags, int family, int socktype, int protocol)
-{
- (void)(flags);
- (void)(protocol);
-
- // Host or service must be specified.
- if (host == 0 || host[0] == '\0')
- if (service == 0 || service[0] == '\0')
- return EAI_NONAME;
-
- // Check combination of family and socket type.
- switch (family)
- {
- case AF_UNSPEC:
- break;
- case AF_INET:
- case AF_INET6:
- if (service != 0 && service[0] != '\0')
- if (socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM)
- return EAI_SOCKTYPE;
- break;
- default:
- return EAI_FAMILY;
- }
-
- return 0;
-}
-
-inline void freeaddrinfo_emulation(addrinfo_type* aihead)
-{
- addrinfo_type* ai = aihead;
- while (ai)
- {
- gai_free(ai->ai_addr);
- gai_free(ai->ai_canonname);
- addrinfo_type* ainext = ai->ai_next;
- gai_free(ai);
- ai = ainext;
- }
-}
-
-inline int getaddrinfo_emulation(const char* host, const char* service,
- const addrinfo_type* hintsp, addrinfo_type** result)
-{
- // Set up linked list of addrinfo structures.
- addrinfo_type* aihead = 0;
- addrinfo_type** ainext = &aihead;
- char* canon = 0;
-
- // Supply default hints if not specified by caller.
- addrinfo_type hints = addrinfo_type();
- hints.ai_family = AF_UNSPEC;
- if (hintsp)
- hints = *hintsp;
-
- // If the resolution is not specifically for AF_INET6, remove the AI_V4MAPPED
- // and AI_ALL flags.
-#if defined(AI_V4MAPPED)
- if (hints.ai_family != AF_INET6)
- hints.ai_flags &= ~AI_V4MAPPED;
-#endif
-#if defined(AI_ALL)
- if (hints.ai_family != AF_INET6)
- hints.ai_flags &= ~AI_ALL;
-#endif
-
- // Basic error checking.
- int rc = gai_echeck(host, service, hints.ai_flags, hints.ai_family,
- hints.ai_socktype, hints.ai_protocol);
- if (rc != 0)
- {
- freeaddrinfo_emulation(aihead);
- return rc;
- }
-
- gai_search search[2];
- int search_count = gai_nsearch(host, &hints, search);
- for (gai_search* sptr = search; sptr < search + search_count; ++sptr)
- {
- // Check for IPv4 dotted decimal string.
- in4_addr_type inaddr;
- asio::error_code ec;
- if (socket_ops::inet_pton(AF_INET, sptr->host, &inaddr, 0, ec) == 1)
- {
- if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET)
- {
- freeaddrinfo_emulation(aihead);
- gai_free(canon);
- return EAI_FAMILY;
- }
- if (sptr->family == AF_INET)
- {
- rc = gai_aistruct(&ainext, &hints, &inaddr, AF_INET);
- if (rc != 0)
- {
- freeaddrinfo_emulation(aihead);
- gai_free(canon);
- return rc;
- }
- }
- continue;
- }
-
- // Check for IPv6 hex string.
- in6_addr_type in6addr;
- if (socket_ops::inet_pton(AF_INET6, sptr->host, &in6addr, 0, ec) == 1)
- {
- if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET6)
- {
- freeaddrinfo_emulation(aihead);
- gai_free(canon);
- return EAI_FAMILY;
- }
- if (sptr->family == AF_INET6)
- {
- rc = gai_aistruct(&ainext, &hints, &in6addr, AF_INET6);
- if (rc != 0)
- {
- freeaddrinfo_emulation(aihead);
- gai_free(canon);
- return rc;
- }
- }
- continue;
- }
-
- // Look up hostname.
- hostent hent;
- char hbuf[8192] = "";
- hostent* hptr = socket_ops::gethostbyname(sptr->host,
- sptr->family, &hent, hbuf, sizeof(hbuf), hints.ai_flags, ec);
- if (hptr == 0)
- {
- if (search_count == 2)
- {
- // Failure is OK if there are multiple searches.
- continue;
- }
- freeaddrinfo_emulation(aihead);
- gai_free(canon);
- if (ec == asio::error::host_not_found)
- return EAI_NONAME;
- if (ec == asio::error::host_not_found_try_again)
- return EAI_AGAIN;
- if (ec == asio::error::no_recovery)
- return EAI_FAIL;
- if (ec == asio::error::no_data)
- return EAI_NONAME;
- return EAI_NONAME;
- }
-
- // Check for address family mismatch if one was specified.
- if (hints.ai_family != AF_UNSPEC && hints.ai_family != hptr->h_addrtype)
- {
- freeaddrinfo_emulation(aihead);
- gai_free(canon);
- socket_ops::freehostent(hptr);
- return EAI_FAMILY;
- }
-
- // Save canonical name first time.
- if (host != 0 && host[0] != '\0' && hptr->h_name && hptr->h_name[0]
- && (hints.ai_flags & AI_CANONNAME) && canon == 0)
- {
- std::size_t canon_len = strlen(hptr->h_name) + 1;
- canon = gai_alloc<char>(canon_len);
- if (canon == 0)
- {
- freeaddrinfo_emulation(aihead);
- socket_ops::freehostent(hptr);
- return EAI_MEMORY;
- }
- gai_strcpy(canon, hptr->h_name, canon_len);
- }
-
- // Create an addrinfo structure for each returned address.
- for (char** ap = hptr->h_addr_list; *ap; ++ap)
- {
- rc = gai_aistruct(&ainext, &hints, *ap, hptr->h_addrtype);
- if (rc != 0)
- {
- freeaddrinfo_emulation(aihead);
- gai_free(canon);
- socket_ops::freehostent(hptr);
- return EAI_FAMILY;
- }
- }
-
- socket_ops::freehostent(hptr);
- }
-
- // Check if we found anything.
- if (aihead == 0)
- {
- gai_free(canon);
- return EAI_NONAME;
- }
-
- // Return canonical name in first entry.
- if (host != 0 && host[0] != '\0' && (hints.ai_flags & AI_CANONNAME))
- {
- if (canon)
- {
- aihead->ai_canonname = canon;
- canon = 0;
- }
- else
- {
- std::size_t canonname_len = strlen(search[0].host) + 1;
- aihead->ai_canonname = gai_alloc<char>(canonname_len);
- if (aihead->ai_canonname == 0)
- {
- freeaddrinfo_emulation(aihead);
- return EAI_MEMORY;
- }
- gai_strcpy(aihead->ai_canonname, search[0].host, canonname_len);
- }
- }
- gai_free(canon);
-
- // Process the service name.
- if (service != 0 && service[0] != '\0')
- {
- rc = gai_serv(aihead, &hints, service);
- if (rc != 0)
- {
- freeaddrinfo_emulation(aihead);
- return rc;
- }
- }
-
- // Return result to caller.
- *result = aihead;
- return 0;
-}
-
-inline asio::error_code getnameinfo_emulation(
- const socket_addr_type* sa, std::size_t salen, char* host,
- std::size_t hostlen, char* serv, std::size_t servlen, int flags,
- asio::error_code& ec)
-{
- using namespace std;
-
- const char* addr;
- size_t addr_len;
- unsigned short port;
- switch (sa->sa_family)
- {
- case AF_INET:
- if (salen != sizeof(sockaddr_in4_type))
- {
- return ec = asio::error::invalid_argument;
- }
- addr = reinterpret_cast<const char*>(
- &reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_addr);
- addr_len = sizeof(in4_addr_type);
- port = reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_port;
- break;
- case AF_INET6:
- if (salen != sizeof(sockaddr_in6_type))
- {
- return ec = asio::error::invalid_argument;
- }
- addr = reinterpret_cast<const char*>(
- &reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_addr);
- addr_len = sizeof(in6_addr_type);
- port = reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_port;
- break;
- default:
- return ec = asio::error::address_family_not_supported;
- }
-
- if (host && hostlen > 0)
- {
- if (flags & NI_NUMERICHOST)
- {
- if (socket_ops::inet_ntop(sa->sa_family, addr, host, hostlen, 0, ec) == 0)
- {
- return ec;
- }
- }
- else
- {
- hostent hent;
- char hbuf[8192] = "";
- hostent* hptr = socket_ops::gethostbyaddr(addr,
- static_cast<int>(addr_len), sa->sa_family,
- &hent, hbuf, sizeof(hbuf), ec);
- if (hptr && hptr->h_name && hptr->h_name[0] != '\0')
- {
- if (flags & NI_NOFQDN)
- {
- char* dot = strchr(hptr->h_name, '.');
- if (dot)
- {
- *dot = 0;
- }
- }
- gai_strcpy(host, hptr->h_name, hostlen);
- socket_ops::freehostent(hptr);
- }
- else
- {
- socket_ops::freehostent(hptr);
- if (flags & NI_NAMEREQD)
- {
- return ec = asio::error::host_not_found;
- }
- if (socket_ops::inet_ntop(sa->sa_family,
- addr, host, hostlen, 0, ec) == 0)
- {
- return ec;
- }
- }
- }
- }
-
- if (serv && servlen > 0)
- {
- if (flags & NI_NUMERICSERV)
- {
- if (servlen < 6)
- {
- return ec = asio::error::no_buffer_space;
- }
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
- sprintf_s(serv, servlen, "%u", ntohs(port));
-#else
- sprintf(serv, "%u", ntohs(port));
-#endif
- }
- else
- {
-#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
- static ::pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- ::pthread_mutex_lock(&mutex);
-#endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
- servent* sptr = ::getservbyport(port, (flags & NI_DGRAM) ? "udp" : 0);
- if (sptr && sptr->s_name && sptr->s_name[0] != '\0')
- {
- gai_strcpy(serv, sptr->s_name, servlen);
- }
- else
- {
- if (servlen < 6)
- {
- return ec = asio::error::no_buffer_space;
- }
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
- sprintf_s(serv, servlen, "%u", ntohs(port));
-#else
- sprintf(serv, "%u", ntohs(port));
-#endif
- }
-#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
- ::pthread_mutex_unlock(&mutex);
-#endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
- }
- }
-
- clear_error(ec);
- return ec;
-}
+ASIO_DECL void freeaddrinfo(addrinfo_type* ai);
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- // || defined(__MACH__) && defined(__APPLE__)
+ASIO_DECL asio::error_code getnameinfo(
+ const socket_addr_type* addr, std::size_t addrlen,
+ char* host, std::size_t hostlen, char* serv,
+ std::size_t servlen, int flags, asio::error_code& ec);
-inline asio::error_code translate_addrinfo_error(int error)
-{
- switch (error)
- {
- case 0:
- return asio::error_code();
- case EAI_AGAIN:
- return asio::error::host_not_found_try_again;
- case EAI_BADFLAGS:
- return asio::error::invalid_argument;
- case EAI_FAIL:
- return asio::error::no_recovery;
- case EAI_FAMILY:
- return asio::error::address_family_not_supported;
- case EAI_MEMORY:
- return asio::error::no_memory;
- case EAI_NONAME:
-#if defined(EAI_ADDRFAMILY)
- case EAI_ADDRFAMILY:
-#endif
-#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
- case EAI_NODATA:
-#endif
- return asio::error::host_not_found;
- case EAI_SERVICE:
- return asio::error::service_not_found;
- case EAI_SOCKTYPE:
- return asio::error::socket_type_not_supported;
- default: // Possibly the non-portable EAI_SYSTEM.
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
- return asio::error_code(
- WSAGetLastError(), asio::error::get_system_category());
-#else
- return asio::error_code(
- errno, asio::error::get_system_category());
-#endif
- }
-}
-
-inline asio::error_code getaddrinfo(const char* host,
- const char* service, const addrinfo_type* hints, addrinfo_type** result,
- asio::error_code& ec)
-{
- clear_error(ec);
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
- // Building for Windows XP, Windows Server 2003, or later.
- int error = ::getaddrinfo(host, service, hints, result);
- return ec = translate_addrinfo_error(error);
-# else
- // Building for Windows 2000 or earlier.
- typedef int (WSAAPI *gai_t)(const char*,
- const char*, const addrinfo_type*, addrinfo_type**);
- if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
- {
- if (gai_t gai = (gai_t)::GetProcAddress(winsock_module, "getaddrinfo"))
- {
- int error = gai(host, service, hints, result);
- return ec = translate_addrinfo_error(error);
- }
- }
- int error = getaddrinfo_emulation(host, service, hints, result);
- return ec = translate_addrinfo_error(error);
-# endif
-#elif defined(__MACH__) && defined(__APPLE__)
- int error = getaddrinfo_emulation(host, service, hints, result);
- return ec = translate_addrinfo_error(error);
-#else
- int error = ::getaddrinfo(host, service, hints, result);
- return ec = translate_addrinfo_error(error);
-#endif
-}
-
-inline void freeaddrinfo(addrinfo_type* ai)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
- // Building for Windows XP, Windows Server 2003, or later.
- ::freeaddrinfo(ai);
-# else
- // Building for Windows 2000 or earlier.
- typedef int (WSAAPI *fai_t)(addrinfo_type*);
- if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
- {
- if (fai_t fai = (fai_t)::GetProcAddress(winsock_module, "freeaddrinfo"))
- {
- fai(ai);
- return;
- }
- }
- freeaddrinfo_emulation(ai);
-# endif
-#elif defined(__MACH__) && defined(__APPLE__)
- freeaddrinfo_emulation(ai);
-#else
- ::freeaddrinfo(ai);
-#endif
-}
-
-inline asio::error_code getnameinfo(const socket_addr_type* addr,
- std::size_t addrlen, char* host, std::size_t hostlen,
- char* serv, std::size_t servlen, int flags, asio::error_code& ec)
-{
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
- // Building for Windows XP, Windows Server 2003, or later.
- clear_error(ec);
- int error = ::getnameinfo(addr, static_cast<socklen_t>(addrlen),
- host, static_cast<DWORD>(hostlen),
- serv, static_cast<DWORD>(servlen), flags);
- return ec = translate_addrinfo_error(error);
-# else
- // Building for Windows 2000 or earlier.
- typedef int (WSAAPI *gni_t)(const socket_addr_type*,
- int, char*, DWORD, char*, DWORD, int);
- if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
- {
- if (gni_t gni = (gni_t)::GetProcAddress(winsock_module, "getnameinfo"))
- {
- clear_error(ec);
- int error = gni(addr, static_cast<int>(addrlen),
- host, static_cast<DWORD>(hostlen),
- serv, static_cast<DWORD>(servlen), flags);
- return ec = translate_addrinfo_error(error);
- }
- }
- clear_error(ec);
- return getnameinfo_emulation(addr, addrlen,
- host, hostlen, serv, servlen, flags, ec);
-# endif
-#elif defined(__MACH__) && defined(__APPLE__)
- using namespace std; // For memcpy.
- sockaddr_storage_type tmp_addr;
- memcpy(&tmp_addr, addr, addrlen);
- tmp_addr.ss_len = addrlen;
- addr = reinterpret_cast<socket_addr_type*>(&tmp_addr);
- clear_error(ec);
- return getnameinfo_emulation(addr, addrlen,
- host, hostlen, serv, servlen, flags, ec);
-#else
- clear_error(ec);
- int error = ::getnameinfo(addr, addrlen, host, hostlen, serv, servlen, flags);
- return ec = translate_addrinfo_error(error);
-#endif
-}
-
-inline u_long_type network_to_host_long(u_long_type value)
-{
- return ntohl(value);
-}
+ASIO_DECL asio::error_code sync_getnameinfo(
+ const socket_addr_type* addr, std::size_t addrlen,
+ char* host, std::size_t hostlen, char* serv,
+ std::size_t servlen, int sock_type, asio::error_code& ec);
-inline u_long_type host_to_network_long(u_long_type value)
-{
- return htonl(value);
-}
+ASIO_DECL asio::error_code background_getnameinfo(
+ const weak_cancel_token_type& cancel_token,
+ const socket_addr_type* addr, std::size_t addrlen,
+ char* host, std::size_t hostlen, char* serv,
+ std::size_t servlen, int sock_type, asio::error_code& ec);
-inline u_short_type network_to_host_short(u_short_type value)
-{
- return ntohs(value);
-}
+ASIO_DECL u_long_type network_to_host_long(u_long_type value);
-inline u_short_type host_to_network_short(u_short_type value)
-{
- return htons(value);
-}
+ASIO_DECL u_long_type host_to_network_long(u_long_type value);
+
+ASIO_DECL u_short_type network_to_host_short(u_short_type value);
+
+ASIO_DECL u_short_type host_to_network_short(u_short_type value);
} // namespace socket_ops
} // namespace detail
@@ -1909,4 +282,8 @@ inline u_short_type host_to_network_short(u_short_type value)
#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/socket_ops.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
#endif // ASIO_DETAIL_SOCKET_OPS_HPP
diff --git a/ext/asio/asio/detail/socket_option.hpp b/ext/asio/asio/detail/socket_option.hpp
index ac070b7018..c9d789698d 100644
--- a/ext/asio/asio/detail/socket_option.hpp
+++ b/ext/asio/asio/detail/socket_option.hpp
@@ -1,8 +1,8 @@
//
-// socket_option.hpp
-// ~~~~~~~~~~~~~~~~~
+// detail/socket_option.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,15 @@
# 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 <stdexcept>
#include <boost/config.hpp>
#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
#include "asio/detail/socket_types.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
namespace socket_option {
diff --git a/ext/asio/asio/detail/socket_select_interrupter.hpp b/ext/asio/asio/detail/socket_select_interrupter.hpp
index 62e1063e30..b05a4ffa2d 100644
--- a/ext/asio/asio/detail/socket_select_interrupter.hpp
+++ b/ext/asio/asio/detail/socket_select_interrupter.hpp
@@ -1,8 +1,8 @@
//
-// socket_select_interrupter.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/socket_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)
//
// 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/config.hpp"
-#include "asio/detail/push_options.hpp"
-#include <cstdlib>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
+#if defined(BOOST_WINDOWS) \
+ || defined(__CYGWIN__) \
+ || defined(__SYMBIAN32__)
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
-#include "asio/detail/socket_holder.hpp"
-#include "asio/detail/socket_ops.hpp"
#include "asio/detail/socket_types.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
@@ -35,135 +32,16 @@ class socket_select_interrupter
{
public:
// Constructor.
- 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::system_error e(ec, "socket_select_interrupter");
- boost::throw_exception(e);
- }
-
- int opt = 1;
- socket_ops::setsockopt(acceptor.get(),
- 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::system_error e(ec, "socket_select_interrupter");
- boost::throw_exception(e);
- }
-
- if (socket_ops::getsockname(acceptor.get(), (socket_addr_type*)&addr,
- &addr_len, ec) == socket_error_retval)
- {
- asio::system_error e(ec, "socket_select_interrupter");
- boost::throw_exception(e);
- }
-
- // 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::system_error e(ec, "socket_select_interrupter");
- boost::throw_exception(e);
- }
-
- socket_holder client(socket_ops::socket(
- AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));
- if (client.get() == invalid_socket)
- {
- asio::system_error e(ec, "socket_select_interrupter");
- boost::throw_exception(e);
- }
-
- if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr,
- addr_len, ec) == socket_error_retval)
- {
- asio::system_error e(ec, "socket_select_interrupter");
- boost::throw_exception(e);
- }
-
- socket_holder server(socket_ops::accept(acceptor.get(), 0, 0, ec));
- if (server.get() == invalid_socket)
- {
- asio::system_error e(ec, "socket_select_interrupter");
- boost::throw_exception(e);
- }
-
- ioctl_arg_type non_blocking = 1;
- if (socket_ops::ioctl(client.get(), FIONBIO, &non_blocking, ec))
- {
- asio::system_error e(ec, "socket_select_interrupter");
- boost::throw_exception(e);
- }
-
- opt = 1;
- socket_ops::setsockopt(client.get(),
- IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
-
- non_blocking = 1;
- if (socket_ops::ioctl(server.get(), FIONBIO, &non_blocking, ec))
- {
- asio::system_error e(ec, "socket_select_interrupter");
- boost::throw_exception(e);
- }
-
- opt = 1;
- socket_ops::setsockopt(server.get(),
- IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
-
- read_descriptor_ = server.release();
- write_descriptor_ = client.release();
- }
+ ASIO_DECL socket_select_interrupter();
// Destructor.
- ~socket_select_interrupter()
- {
- asio::error_code ec;
- if (read_descriptor_ != invalid_socket)
- socket_ops::close(read_descriptor_, ec);
- if (write_descriptor_ != invalid_socket)
- socket_ops::close(write_descriptor_, ec);
- }
+ ASIO_DECL ~socket_select_interrupter();
// Interrupt the select call.
- void 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);
- }
+ ASIO_DECL void interrupt();
// Reset the select interrupt. Returns true if the call was interrupted.
- bool 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;
- }
+ ASIO_DECL bool reset();
// Get the read descriptor to be passed to select.
socket_type read_descriptor() const
@@ -189,4 +67,12 @@ private:
#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/socket_select_interrupter.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_WINDOWS)
+ // || defined(__CYGWIN__)
+ // || defined(__SYMBIAN32__)
+
#endif // ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP
diff --git a/ext/asio/asio/detail/socket_types.hpp b/ext/asio/asio/detail/socket_types.hpp
index 34b3d3e631..4e29e513ee 100644
--- a/ext/asio/asio/detail/socket_types.hpp
+++ b/ext/asio/asio/detail/socket_types.hpp
@@ -1,8 +1,8 @@
//
-// socket_types.hpp
-// ~~~~~~~~~~~~~~~~
+// detail/socket_types.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,69 +15,19 @@
# 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/push_options.hpp"
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
# if defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)
# error WinSock.h has already been included
# endif // defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)
-# 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__)
# include <stdlib.h> // Needed for __errno
-# 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)
# if !defined(_WSPIAPI_H_)
# define _WSPIAPI_H_
# define ASIO_WSPIAPI_H_DEFINED
# endif // !defined(_WSPIAPI_H_)
# endif // defined(__BORLANDC__)
-# 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)
-# if !defined(ASIO_NO_NOMINMAX)
-# if !defined(NOMINMAX)
-# define NOMINMAX 1
-# endif // !defined(NOMINMAX)
-# endif // !defined(ASIO_NO_NOMINMAX)
-# 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__)
# include <winsock2.h>
# include <ws2tcpip.h>
# include <mswsock.h>
@@ -96,18 +46,25 @@
# include "asio/detail/old_win_sdk_compat.hpp"
#else
# include <sys/ioctl.h>
-# include <sys/poll.h>
+# if !defined(__SYMBIAN32__)
+# include <sys/poll.h>
+# endif
# include <sys/types.h>
-# if defined(__hpux) && !defined(__HP_aCC)
+# include <sys/stat.h>
+# include <fcntl.h>
+# if defined(__hpux)
# include <sys/time.h>
-# else
+# endif
+# if !defined(__hpux) || defined(__SELECT)
# include <sys/select.h>
# endif
# include <sys/socket.h>
# include <sys/uio.h>
# include <sys/un.h>
# include <netinet/in.h>
-# include <netinet/tcp.h>
+# if !defined(__SYMBIAN32__)
+# include <netinet/tcp.h>
+# endif
# include <arpa/inet.h>
# include <netdb.h>
# include <net/if.h>
@@ -117,7 +74,8 @@
# include <sys/sockio.h>
# endif
#endif
-#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
diff --git a/ext/asio/asio/detail/solaris_fenced_block.hpp b/ext/asio/asio/detail/solaris_fenced_block.hpp
index d337f3b62e..411c824515 100644
--- a/ext/asio/asio/detail/solaris_fenced_block.hpp
+++ b/ext/asio/asio/detail/solaris_fenced_block.hpp
@@ -1,8 +1,8 @@
//
-// solaris_fenced_block.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/solaris_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,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 <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/config.hpp"
#if defined(__sun)
-#include "asio/detail/push_options.hpp"
#include <atomic.h>
-#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
@@ -50,8 +46,8 @@ public:
} // namespace detail
} // namespace asio
-#endif // defined(__sun)
-
#include "asio/detail/pop_options.hpp"
+#endif // defined(__sun)
+
#endif // ASIO_DETAIL_SOLARIS_FENCED_BLOCK_HPP
diff --git a/ext/asio/asio/detail/strand_service.hpp b/ext/asio/asio/detail/strand_service.hpp
index ea50f412a1..4885b93ee8 100644
--- a/ext/asio/asio/detail/strand_service.hpp
+++ b/ext/asio/asio/detail/strand_service.hpp
@@ -1,8 +1,8 @@
//
-// strand_service.hpp
-// ~~~~~~~~~~~~~~~~~~
+// detail/strand_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,23 +15,14 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/functional/hash.hpp>
+#include "asio/detail/config.hpp"
#include <boost/scoped_ptr.hpp>
-#include "asio/detail/pop_options.hpp"
-
#include "asio/io_service.hpp"
-#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/mutex.hpp"
#include "asio/detail/op_queue.hpp"
#include "asio/detail/operation.hpp"
-#include "asio/detail/service_base.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
@@ -41,7 +32,10 @@ class strand_service
: public asio::detail::service_base<strand_service>
{
private:
+ // Helper class to re-post the strand on exit.
struct on_do_complete_exit;
+
+ // Helper class to re-post the strand on exit.
struct on_dispatch_exit;
public:
@@ -51,11 +45,7 @@ public:
: public operation
{
public:
- strand_impl()
- : operation(&strand_service::do_complete),
- count_(0)
- {
- }
+ strand_impl();
private:
// Only this service will have access to the internal values.
@@ -76,180 +66,29 @@ public:
typedef strand_impl* implementation_type;
// Construct a new strand service for the specified io_service.
- explicit 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)
- {
- }
+ ASIO_DECL explicit strand_service(asio::io_service& io_service);
// Destroy all user-defined handler objects owned by the service.
- void 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_);
- }
+ ASIO_DECL void shutdown_service();
// Construct a new strand implementation.
- void construct(implementation_type& impl)
- {
- std::size_t index = boost::hash_value(&impl);
- boost::hash_combine(index, salt_++);
- index = index % num_implementations;
-
- asio::detail::mutex::scoped_lock lock(mutex_);
-
- if (!implementations_[index])
- implementations_[index].reset(new strand_impl);
- impl = implementations_[index].get();
- }
+ ASIO_DECL void construct(implementation_type& impl);
// Destroy a strand implementation.
- void destroy(implementation_type& impl)
- {
- impl = 0;
- }
+ void destroy(implementation_type& impl);
// Request the io_service to invoke the given handler.
template <typename Handler>
- void dispatch(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 object to wrap the handler.
- typedef completion_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);
-
- // 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.
- ptr.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(ptr.get());
- impl->mutex_.unlock();
- ptr.release();
-
- // The first handler to be enqueued is responsible for scheduling the
- // strand.
- if (first)
- io_service_.post_immediate_completion(impl);
- }
+ void dispatch(implementation_type& impl, Handler handler);
// Request the io_service to invoke the given handler and return immediately.
template <typename Handler>
- void post(implementation_type& impl, Handler handler)
- {
- // Allocate and construct an object to wrap the handler.
- typedef completion_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);
-
- // Add the handler to the queue.
- impl->mutex_.lock();
- bool first = (++impl->count_ == 1);
- impl->queue_.push(ptr.get());
- impl->mutex_.unlock();
- ptr.release();
-
- // The first handler to be enqueue is responsible for scheduling the strand.
- if (first)
- io_service_.post_immediate_completion(impl);
- }
+ void post(implementation_type& impl, Handler handler);
private:
- static void 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);
- }
- }
-
- // Helper class to re-post the strand on exit.
- struct 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_);
- }
- };
-
- // Helper class to re-post the strand on exit.
- struct 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_);
- }
- };
+ ASIO_DECL static void do_complete(io_service_impl* owner,
+ operation* base, asio::error_code ec,
+ std::size_t bytes_transferred);
// The io_service implementation used to post completions.
io_service_impl& io_service_;
@@ -273,4 +112,9 @@ private:
#include "asio/detail/pop_options.hpp"
+#include "asio/detail/impl/strand_service.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/strand_service.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
#endif // ASIO_DETAIL_STRAND_SERVICE_HPP
diff --git a/ext/asio/asio/detail/task_io_service.hpp b/ext/asio/asio/detail/task_io_service.hpp
index eb77c1d8de..2d69513b46 100644
--- a/ext/asio/asio/detail/task_io_service.hpp
+++ b/ext/asio/asio/detail/task_io_service.hpp
@@ -1,8 +1,8 @@
//
-// task_io_service.hpp
-// ~~~~~~~~~~~~~~~~~~~
+// detail/task_io_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,180 +15,59 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if !defined(ASIO_HAS_IOCP)
+#include <boost/detail/atomic_count.hpp>
#include "asio/error_code.hpp"
#include "asio/io_service.hpp"
-#include "asio/detail/call_stack.hpp"
-#include "asio/detail/completion_handler.hpp"
-#include "asio/detail/event.hpp"
-#include "asio/detail/fenced_block.hpp"
-#include "asio/detail/handler_alloc_helpers.hpp"
-#include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/mutex.hpp"
#include "asio/detail/op_queue.hpp"
-#include "asio/detail/service_base.hpp"
+#include "asio/detail/reactor_fwd.hpp"
#include "asio/detail/task_io_service_fwd.hpp"
#include "asio/detail/task_io_service_operation.hpp"
#include "asio/detail/push_options.hpp"
-#include <boost/detail/atomic_count.hpp>
-#include "asio/detail/pop_options.hpp"
namespace asio {
namespace detail {
-template <typename Task>
class task_io_service
- : public asio::detail::service_base<task_io_service<Task> >
+ : public asio::detail::service_base<task_io_service>
{
public:
- typedef task_io_service_operation<Task> operation;
+ typedef task_io_service_operation operation;
// Constructor.
- task_io_service(asio::io_service& io_service)
- : asio::detail::service_base<task_io_service<Task> >(io_service),
- mutex_(),
- task_(0),
- task_interrupted_(true),
- outstanding_work_(0),
- stopped_(false),
- shutdown_(false),
- first_idle_thread_(0)
- {
- }
+ ASIO_DECL task_io_service(asio::io_service& io_service);
- void init(size_t /*concurrency_hint*/)
- {
- }
+ // How many concurrent threads are likely to run the io_service.
+ ASIO_DECL void init(std::size_t concurrency_hint);
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
- {
- asio::detail::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;
- }
+ ASIO_DECL void shutdown_service();
// Initialise the task, if required.
- void init_task()
- {
- asio::detail::mutex::scoped_lock lock(mutex_);
- if (!shutdown_ && !task_)
- {
- task_ = &use_service<Task>(this->get_io_service());
- op_queue_.push(&task_operation_);
- wake_one_thread_and_unlock(lock);
- }
- }
+ ASIO_DECL void init_task();
// Run the event loop until interrupted or no more work.
- size_t run(asio::error_code& ec)
- {
- ec = asio::error_code();
- if (outstanding_work_ == 0)
- {
- stop();
- return 0;
- }
-
- typename call_stack<task_io_service>::context ctx(this);
-
- idle_thread_info this_idle_thread;
- this_idle_thread.next = 0;
-
- asio::detail::mutex::scoped_lock lock(mutex_);
-
- size_t n = 0;
- for (; do_one(lock, &this_idle_thread); lock.lock())
- if (n != (std::numeric_limits<size_t>::max)())
- ++n;
- return n;
- }
+ ASIO_DECL std::size_t run(asio::error_code& ec);
// Run until interrupted or one operation is performed.
- size_t run_one(asio::error_code& ec)
- {
- ec = asio::error_code();
- if (outstanding_work_ == 0)
- {
- stop();
- return 0;
- }
-
- typename call_stack<task_io_service>::context ctx(this);
-
- idle_thread_info this_idle_thread;
- this_idle_thread.next = 0;
-
- asio::detail::mutex::scoped_lock lock(mutex_);
-
- return do_one(lock, &this_idle_thread);
- }
+ ASIO_DECL std::size_t run_one(asio::error_code& ec);
// Poll for operations without blocking.
- size_t poll(asio::error_code& ec)
- {
- if (outstanding_work_ == 0)
- {
- stop();
- ec = asio::error_code();
- return 0;
- }
-
- typename call_stack<task_io_service>::context ctx(this);
-
- asio::detail::mutex::scoped_lock lock(mutex_);
-
- size_t n = 0;
- for (; do_one(lock, 0); lock.lock())
- if (n != (std::numeric_limits<size_t>::max)())
- ++n;
- return n;
- }
+ ASIO_DECL std::size_t poll(asio::error_code& ec);
// Poll for one operation without blocking.
- size_t poll_one(asio::error_code& ec)
- {
- ec = asio::error_code();
- if (outstanding_work_ == 0)
- {
- stop();
- return 0;
- }
-
- typename call_stack<task_io_service>::context ctx(this);
-
- asio::detail::mutex::scoped_lock lock(mutex_);
-
- return do_one(lock, 0);
- }
+ ASIO_DECL std::size_t poll_one(asio::error_code& ec);
// Interrupt the event processing loop.
- void stop()
- {
- asio::detail::mutex::scoped_lock lock(mutex_);
- stop_all_threads(lock);
- }
+ ASIO_DECL void stop();
// Reset in preparation for a subsequent run invocation.
- void reset()
- {
- asio::detail::mutex::scoped_lock lock(mutex_);
- stopped_ = false;
- }
+ ASIO_DECL void reset();
// Notify that some work has started.
void work_started()
@@ -205,228 +84,60 @@ public:
// Request invocation of the given handler.
template <typename Handler>
- void 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);
- }
+ void dispatch(Handler handler);
// Request invocation of the given handler and return immediately.
template <typename Handler>
- void post(Handler handler)
- {
- // Allocate and construct an operation to wrap the handler.
- typedef completion_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);
-
- post_immediate_completion(ptr.get());
- ptr.release();
- }
+ void post(Handler handler);
// Request invocation of the given operation and return immediately. Assumes
// that work_started() has not yet been called for the operation.
- void post_immediate_completion(operation* op)
- {
- work_started();
- post_deferred_completion(op);
- }
+ ASIO_DECL void post_immediate_completion(operation* op);
// Request invocation of the given operation and return immediately. Assumes
// that work_started() was previously called for the operation.
- void post_deferred_completion(operation* op)
- {
- asio::detail::mutex::scoped_lock lock(mutex_);
- op_queue_.push(op);
- wake_one_thread_and_unlock(lock);
- }
+ ASIO_DECL void post_deferred_completion(operation* op);
// Request invocation of the given operations and return immediately. Assumes
// that work_started() was previously called for each operation.
- void post_deferred_completions(op_queue<operation>& ops)
- {
- if (!ops.empty())
- {
- asio::detail::mutex::scoped_lock lock(mutex_);
- op_queue_.push(ops);
- wake_one_thread_and_unlock(lock);
- }
- }
+ ASIO_DECL void post_deferred_completions(op_queue<operation>& ops);
private:
+ // Structure containing information about an idle thread.
struct idle_thread_info;
- size_t do_one(asio::detail::mutex::scoped_lock& lock,
- 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;
- }
+ // Run at most one operation. Blocks only if this_idle_thread is non-null.
+ ASIO_DECL std::size_t do_one(mutex::scoped_lock& lock,
+ idle_thread_info* this_idle_thread);
// Stop the task and all idle threads.
- void stop_all_threads(
- asio::detail::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();
- }
- }
+ ASIO_DECL void stop_all_threads(mutex::scoped_lock& lock);
// Wakes a single idle thread and unlocks the mutex. Returns true if an idle
// thread was found. If there is no idle thread, returns false and leaves the
// mutex locked.
- bool wake_one_idle_thread_and_unlock(
- asio::detail::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;
- }
+ ASIO_DECL bool wake_one_idle_thread_and_unlock(
+ mutex::scoped_lock& lock);
// Wake a single idle thread, or the task, and always unlock the mutex.
- void wake_one_thread_and_unlock(
- asio::detail::mutex::scoped_lock& lock)
- {
- if (!wake_one_idle_thread_and_unlock(lock))
- {
- if (!task_interrupted_ && task_)
- {
- task_interrupted_ = true;
- task_->interrupt();
- }
- lock.unlock();
- }
- }
+ ASIO_DECL void wake_one_thread_and_unlock(
+ mutex::scoped_lock& lock);
// Helper class to perform task-related operations on block exit.
struct task_cleanup;
friend struct task_cleanup;
- struct 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_;
- asio::detail::mutex::scoped_lock* lock_;
- op_queue<operation>* ops_;
- };
// Helper class to call work_finished() on block exit.
- struct work_finished_on_block_exit
- {
- ~work_finished_on_block_exit()
- {
- task_io_service_->work_finished();
- }
-
- task_io_service* task_io_service_;
- };
+ struct work_finished_on_block_exit;
// Mutex to protect access to internal data.
- asio::detail::mutex mutex_;
+ mutex mutex_;
// The task to be run by this service.
- Task* task_;
+ reactor* task_;
// Operation object to represent the position of the task in the queue.
- struct task_operation : public operation
+ struct task_operation : operation
{
task_operation() : operation(0) {}
} task_operation_;
@@ -446,13 +157,6 @@ private:
// Flag to indicate that the dispatcher has been shut down.
bool shutdown_;
- // Structure containing information about an idle thread.
- struct idle_thread_info
- {
- event wakeup_event;
- idle_thread_info* next;
- };
-
// The threads that are currently idle.
idle_thread_info* first_idle_thread_;
};
@@ -462,4 +166,11 @@ private:
#include "asio/detail/pop_options.hpp"
+#include "asio/detail/impl/task_io_service.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/task_io_service.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // !defined(ASIO_HAS_IOCP)
+
#endif // ASIO_DETAIL_TASK_IO_SERVICE_HPP
diff --git a/ext/asio/asio/detail/task_io_service_fwd.hpp b/ext/asio/asio/detail/task_io_service_fwd.hpp
index 5b18d1d700..b66cb07907 100644
--- a/ext/asio/asio/detail/task_io_service_fwd.hpp
+++ b/ext/asio/asio/detail/task_io_service_fwd.hpp
@@ -1,8 +1,8 @@
//
-// task_io_service_fwd.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~
+// detail/task_io_service_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,17 +15,12 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
namespace asio {
namespace detail {
-template <typename Task>
class task_io_service;
} // namespace detail
} // namespace asio
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP
diff --git a/ext/asio/asio/detail/task_io_service_operation.hpp b/ext/asio/asio/detail/task_io_service_operation.hpp
index 6776f6992f..dd4384a14f 100644
--- a/ext/asio/asio/detail/task_io_service_operation.hpp
+++ b/ext/asio/asio/detail/task_io_service_operation.hpp
@@ -1,8 +1,8 @@
//
-// task_io_service_operation.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/task_io_service_operation.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,21 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
#include "asio/error_code.hpp"
#include "asio/detail/op_queue.hpp"
#include "asio/detail/task_io_service_fwd.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
// Base class for all operations. A function pointer is used instead of virtual
// functions to avoid the associated overhead.
-template <typename Task>
class task_io_service_operation
{
public:
- void complete(task_io_service<Task>& owner)
+ void complete(task_io_service& owner)
{
func_(&owner, this, asio::error_code(), 0);
}
@@ -41,8 +40,9 @@ public:
}
protected:
- typedef void (*func_type)(task_io_service<Task>*,
- task_io_service_operation*, asio::error_code, std::size_t);
+ typedef void (*func_type)(task_io_service*,
+ task_io_service_operation*,
+ asio::error_code, std::size_t);
task_io_service_operation(func_type func)
: next_(0),
diff --git a/ext/asio/asio/detail/thread.hpp b/ext/asio/asio/detail/thread.hpp
index 3c9280bcd3..7c4103b28e 100644
--- a/ext/asio/asio/detail/thread.hpp
+++ b/ext/asio/asio/detail/thread.hpp
@@ -1,8 +1,8 @@
//
-// thread.hpp
-// ~~~~~~~~~~
+// detail/thread.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_thread.hpp"
@@ -53,6 +49,4 @@ typedef posix_thread thread;
} // namespace detail
} // namespace asio
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_DETAIL_THREAD_HPP
diff --git a/ext/asio/asio/detail/throw_error.hpp b/ext/asio/asio/detail/throw_error.hpp
index 51d6e48f4f..d39aa92958 100644
--- a/ext/asio/asio/detail/throw_error.hpp
+++ b/ext/asio/asio/detail/throw_error.hpp
@@ -1,8 +1,8 @@
//
-// throw_error.hpp
-// ~~~~~~~~~~~~~~~
+// detail/throw_error.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,25 +15,30 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include "asio/error_code.hpp"
#include "asio/detail/push_options.hpp"
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error_code.hpp"
-#include "asio/system_error.hpp"
namespace asio {
namespace detail {
+ASIO_DECL void do_throw_error(const asio::error_code& err);
+
+ASIO_DECL void do_throw_error(const asio::error_code& err,
+ const char* location);
+
inline void throw_error(const asio::error_code& err)
{
if (err)
- {
- asio::system_error e(err);
- boost::throw_exception(e);
- }
+ do_throw_error(err);
+}
+
+inline void throw_error(const asio::error_code& err,
+ const char* location)
+{
+ if (err)
+ do_throw_error(err, location);
}
} // namespace detail
@@ -41,4 +46,8 @@ inline void throw_error(const asio::error_code& err)
#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/throw_error.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
#endif // ASIO_DETAIL_THROW_ERROR_HPP
diff --git a/ext/asio/asio/detail/timer_op.hpp b/ext/asio/asio/detail/timer_op.hpp
index bf3c3ae593..62cd292247 100644
--- a/ext/asio/asio/detail/timer_op.hpp
+++ b/ext/asio/asio/detail/timer_op.hpp
@@ -1,8 +1,8 @@
//
-// timer_op.hpp
-// ~~~~~~~~~~~~
+// detail/timer_op.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/detail/operation.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
diff --git a/ext/asio/asio/detail/timer_queue.hpp b/ext/asio/asio/detail/timer_queue.hpp
index 2e4d2d5d97..514c434e53 100644
--- a/ext/asio/asio/detail/timer_queue.hpp
+++ b/ext/asio/asio/detail/timer_queue.hpp
@@ -1,8 +1,8 @@
//
-// timer_queue.hpp
-// ~~~~~~~~~~~~~~~
+// detail/timer_queue.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,21 +15,22 @@
# 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 <memory>
#include <vector>
#include <boost/config.hpp>
#include <boost/limits.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/detail/hash_map.hpp"
#include "asio/detail/op_queue.hpp"
#include "asio/detail/timer_op.hpp"
#include "asio/detail/timer_queue_base.hpp"
+#include "asio/error.hpp"
+#include "asio/time_traits.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 {
@@ -45,6 +46,26 @@ public:
// The duration type.
typedef typename Time_Traits::duration_type duration_type;
+ // Per-timer data.
+ class per_timer_data
+ {
+ public:
+ per_timer_data() : next_(0), prev_(0) {}
+
+ private:
+ friend class timer_queue;
+
+ // The operations waiting on the timer.
+ op_queue<timer_op> op_queue_;
+
+ // The index of the timer in the heap.
+ std::size_t heap_index_;
+
+ // Pointers to adjacent timers in a linked list.
+ per_timer_data* next_;
+ per_timer_data* prev_;
+ };
+
// Constructor.
timer_queue()
: timers_(),
@@ -55,35 +76,45 @@ public:
// Add a new timer to the queue. Returns true if this is the timer that is
// earliest in the queue, in which case the reactor's event demultiplexing
// function call may need to be interrupted and restarted.
- bool enqueue_timer(const time_type& time, timer_op* op, void* token)
+ bool enqueue_timer(const time_type& time, per_timer_data& timer, timer_op* op)
{
- // Ensure that there is space for the timer in the heap. We reserve here so
- // that the push_back below will not throw due to a reallocation failure.
- heap_.reserve(heap_.size() + 1);
-
- // Insert the new timer into the hash.
- typedef typename hash_map<void*, timer>::iterator iterator;
- typedef typename hash_map<void*, timer>::value_type value_type;
- std::pair<iterator, bool> result =
- timers_.insert(value_type(token, timer()));
- result.first->second.op_queue_.push(op);
- if (result.second)
+ // Enqueue the timer object.
+ if (timer.prev_ == 0 && &timer != timers_)
{
- // Put the new timer at the correct position in the heap.
- result.first->second.time_ = time;
- result.first->second.heap_index_ = heap_.size();
- result.first->second.token_ = token;
- heap_.push_back(&result.first->second);
- up_heap(heap_.size() - 1);
+ if (this->is_positive_infinity(time))
+ {
+ // No heap entry is required for timers that never expire.
+ timer.heap_index_ = (std::numeric_limits<std::size_t>::max)();
+ }
+ else
+ {
+ // Put the new timer at the correct position in the heap. This is done
+ // first since push_back() can throw due to allocation failure.
+ timer.heap_index_ = heap_.size();
+ heap_entry entry = { time, &timer };
+ heap_.push_back(entry);
+ up_heap(heap_.size() - 1);
+ }
+
+ // Insert the new timer into the linked list of active timers.
+ timer.next_ = timers_;
+ timer.prev_ = 0;
+ if (timers_)
+ timers_->prev_ = &timer;
+ timers_ = &timer;
}
- return (heap_[0] == &result.first->second);
+ // Enqueue the individual timer operation.
+ timer.op_queue_.push(op);
+
+ // Interrupt reactor only if newly added timer is first to expire.
+ return timer.heap_index_ == 0 && timer.op_queue_.front() == op;
}
// Whether there are no timers in the queue.
virtual bool empty() const
{
- return heap_.empty();
+ return timers_ == 0;
}
// Get the time for the timer that is earliest in the queue.
@@ -93,12 +124,14 @@ public:
return max_duration;
boost::posix_time::time_duration duration = Time_Traits::to_posix_duration(
- Time_Traits::subtract(heap_[0]->time_, Time_Traits::now()));
+ Time_Traits::subtract(heap_[0].time_, Time_Traits::now()));
if (duration > boost::posix_time::milliseconds(max_duration))
duration = boost::posix_time::milliseconds(max_duration);
- else if (duration < boost::posix_time::milliseconds(0))
+ else if (duration <= boost::posix_time::milliseconds(0))
duration = boost::posix_time::milliseconds(0);
+ else if (duration < boost::posix_time::milliseconds(1))
+ duration = boost::posix_time::milliseconds(1);
return duration.total_milliseconds();
}
@@ -110,12 +143,14 @@ public:
return max_duration;
boost::posix_time::time_duration duration = Time_Traits::to_posix_duration(
- Time_Traits::subtract(heap_[0]->time_, Time_Traits::now()));
+ Time_Traits::subtract(heap_[0].time_, Time_Traits::now()));
if (duration > boost::posix_time::microseconds(max_duration))
duration = boost::posix_time::microseconds(max_duration);
- else if (duration < boost::posix_time::microseconds(0))
+ else if (duration <= boost::posix_time::microseconds(0))
duration = boost::posix_time::microseconds(0);
+ else if (duration < boost::posix_time::microseconds(1))
+ duration = boost::posix_time::microseconds(1);
return duration.total_microseconds();
}
@@ -124,77 +159,54 @@ public:
virtual void get_ready_timers(op_queue<operation>& ops)
{
const time_type now = Time_Traits::now();
- while (!heap_.empty() && !Time_Traits::less_than(now, heap_[0]->time_))
+ while (!heap_.empty() && !Time_Traits::less_than(now, heap_[0].time_))
{
- timer* t = heap_[0];
- ops.push(t->op_queue_);
- remove_timer(t);
+ per_timer_data* timer = heap_[0].timer_;
+ ops.push(timer->op_queue_);
+ remove_timer(*timer);
}
}
// Dequeue all timers.
virtual void get_all_timers(op_queue<operation>& ops)
{
- typename hash_map<void*, timer>::iterator i = timers_.begin();
- typename hash_map<void*, timer>::iterator end = timers_.end();
- while (i != end)
+ while (timers_)
{
- ops.push(i->second.op_queue_);
- typename hash_map<void*, timer>::iterator old_i = i++;
- timers_.erase(old_i);
+ per_timer_data* timer = timers_;
+ timers_ = timers_->next_;
+ ops.push(timer->op_queue_);
+ timer->next_ = 0;
+ timer->prev_ = 0;
}
heap_.clear();
- timers_.clear();
}
// Cancel and dequeue the timers with the given token.
- std::size_t cancel_timer(void* timer_token, op_queue<operation>& ops)
+ std::size_t cancel_timer(per_timer_data& timer, op_queue<operation>& ops)
{
std::size_t num_cancelled = 0;
- typedef typename hash_map<void*, timer>::iterator iterator;
- iterator it = timers_.find(timer_token);
- if (it != timers_.end())
+ if (timer.prev_ != 0 || &timer == timers_)
{
- while (timer_op* op = it->second.op_queue_.front())
+ while (timer_op* op = timer.op_queue_.front())
{
op->ec_ = asio::error::operation_aborted;
- it->second.op_queue_.pop();
+ timer.op_queue_.pop();
ops.push(op);
++num_cancelled;
}
- remove_timer(&it->second);
+ remove_timer(timer);
}
return num_cancelled;
}
private:
- // Structure representing a single outstanding timer.
- struct timer
- {
- timer() {}
- timer(const timer&) {}
- void operator=(const timer&) {}
-
- // The time when the timer should fire.
- time_type time_;
-
- // The operations waiting on the timer.
- op_queue<timer_op> op_queue_;
-
- // The index of the timer in the heap.
- size_t heap_index_;
-
- // The token associated with the timer.
- void* token_;
- };
-
// Move the item at the given index up the heap to its correct position.
- void up_heap(size_t index)
+ void up_heap(std::size_t index)
{
- size_t parent = (index - 1) / 2;
+ std::size_t parent = (index - 1) / 2;
while (index > 0
- && Time_Traits::less_than(heap_[index]->time_, heap_[parent]->time_))
+ && Time_Traits::less_than(heap_[index].time_, heap_[parent].time_))
{
swap_heap(index, parent);
index = parent;
@@ -203,16 +215,16 @@ private:
}
// Move the item at the given index down the heap to its correct position.
- void down_heap(size_t index)
+ void down_heap(std::size_t index)
{
- size_t child = index * 2 + 1;
+ std::size_t child = index * 2 + 1;
while (child < heap_.size())
{
- size_t min_child = (child + 1 == heap_.size()
+ std::size_t min_child = (child + 1 == heap_.size()
|| Time_Traits::less_than(
- heap_[child]->time_, heap_[child + 1]->time_))
+ heap_[child].time_, heap_[child + 1].time_))
? child : child + 1;
- if (Time_Traits::less_than(heap_[index]->time_, heap_[min_child]->time_))
+ if (Time_Traits::less_than(heap_[index].time_, heap_[min_child].time_))
break;
swap_heap(index, min_child);
index = min_child;
@@ -221,20 +233,20 @@ private:
}
// Swap two entries in the heap.
- void swap_heap(size_t index1, size_t index2)
+ void swap_heap(std::size_t index1, std::size_t index2)
{
- timer* tmp = heap_[index1];
+ heap_entry tmp = heap_[index1];
heap_[index1] = heap_[index2];
heap_[index2] = tmp;
- heap_[index1]->heap_index_ = index1;
- heap_[index2]->heap_index_ = index2;
+ heap_[index1].timer_->heap_index_ = index1;
+ heap_[index2].timer_->heap_index_ = index2;
}
// Remove a timer from the heap and list of timers.
- void remove_timer(timer* t)
+ void remove_timer(per_timer_data& timer)
{
// Remove the timer from the heap.
- size_t index = t->heap_index_;
+ std::size_t index = timer.heap_index_;
if (!heap_.empty() && index < heap_.size())
{
if (index == heap_.size() - 1)
@@ -245,29 +257,112 @@ private:
{
swap_heap(index, heap_.size() - 1);
heap_.pop_back();
- size_t parent = (index - 1) / 2;
+ std::size_t parent = (index - 1) / 2;
if (index > 0 && Time_Traits::less_than(
- heap_[index]->time_, heap_[parent]->time_))
+ heap_[index].time_, heap_[parent].time_))
up_heap(index);
else
down_heap(index);
}
}
- // Remove the timer from the hash.
- typedef typename hash_map<void*, timer>::iterator iterator;
- iterator it = timers_.find(t->token_);
- if (it != timers_.end())
- timers_.erase(it);
+ // Remove the timer from the linked list of active timers.
+ if (timers_ == &timer)
+ timers_ = timer.next_;
+ if (timer.prev_)
+ timer.prev_->next_ = timer.next_;
+ if (timer.next_)
+ timer.next_->prev_= timer.prev_;
+ timer.next_ = 0;
+ timer.prev_ = 0;
+ }
+
+ // Determine if the specified absolute time is positive infinity.
+ template <typename Time_Type>
+ static bool is_positive_infinity(const Time_Type&)
+ {
+ return false;
+ }
+
+ // Determine if the specified absolute time is positive infinity.
+ static bool is_positive_infinity(const boost::posix_time::ptime& time)
+ {
+ return time == boost::posix_time::pos_infin;
}
- // A hash of timer token to linked lists of timers.
- hash_map<void*, timer> timers_;
+ // The head of a linked list of all active timers.
+ per_timer_data* timers_;
+
+ struct heap_entry
+ {
+ // The time when the timer should fire.
+ time_type time_;
+
+ // The associated timer with enqueued operations.
+ per_timer_data* timer_;
+ };
// The heap of timers, with the earliest timer at the front.
- std::vector<timer*> heap_;
+ std::vector<heap_entry> heap_;
};
+#if !defined(ASIO_HEADER_ONLY)
+
+struct forwarding_posix_time_traits : time_traits<boost::posix_time::ptime> {};
+
+// Template specialisation for the commonly used instantation.
+template <>
+class timer_queue<time_traits<boost::posix_time::ptime> >
+ : public timer_queue_base
+{
+public:
+ // The time type.
+ typedef boost::posix_time::ptime time_type;
+
+ // The duration type.
+ typedef boost::posix_time::time_duration duration_type;
+
+ // Per-timer data.
+ typedef timer_queue<forwarding_posix_time_traits>::per_timer_data
+ per_timer_data;
+
+ // Constructor.
+ ASIO_DECL timer_queue();
+
+ // Destructor.
+ ASIO_DECL virtual ~timer_queue();
+
+ // Add a new timer to the queue. Returns true if this is the timer that is
+ // earliest in the queue, in which case the reactor's event demultiplexing
+ // function call may need to be interrupted and restarted.
+ ASIO_DECL bool enqueue_timer(const time_type& time,
+ per_timer_data& timer, timer_op* op);
+
+ // Whether there are no timers in the queue.
+ ASIO_DECL virtual bool empty() const;
+
+ // Get the time for the timer that is earliest in the queue.
+ ASIO_DECL virtual long wait_duration_msec(long max_duration) const;
+
+ // Get the time for the timer that is earliest in the queue.
+ ASIO_DECL virtual long wait_duration_usec(long max_duration) const;
+
+ // Dequeue all timers not later than the current time.
+ ASIO_DECL virtual void get_ready_timers(op_queue<operation>& ops);
+
+ // Dequeue all timers.
+ ASIO_DECL virtual void get_all_timers(op_queue<operation>& ops);
+
+ // Cancel and dequeue the timers with the given token.
+ ASIO_DECL std::size_t cancel_timer(
+ per_timer_data& timer, op_queue<operation>& ops);
+
+private:
+ timer_queue<forwarding_posix_time_traits> impl_;
+};
+
+#endif // !defined(ASIO_HEADER_ONLY)
+
} // namespace detail
} // namespace asio
diff --git a/ext/asio/asio/detail/timer_queue_base.hpp b/ext/asio/asio/detail/timer_queue_base.hpp
index f978667535..0e8d4c7868 100644
--- a/ext/asio/asio/detail/timer_queue_base.hpp
+++ b/ext/asio/asio/detail/timer_queue_base.hpp
@@ -1,8 +1,8 @@
//
-// timer_queue_base.hpp
-// ~~~~~~~~~~~~~~~~~~~~
+// detail/timer_queue_base.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,13 @@
# 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/op_queue.hpp"
#include "asio/detail/operation.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
diff --git a/ext/asio/asio/detail/timer_queue_fwd.hpp b/ext/asio/asio/detail/timer_queue_fwd.hpp
index 53172448bc..0cca96703c 100644
--- a/ext/asio/asio/detail/timer_queue_fwd.hpp
+++ b/ext/asio/asio/detail/timer_queue_fwd.hpp
@@ -1,8 +1,8 @@
//
-// timer_queue_fwd.hpp
-// ~~~~~~~~~~~~~~~~~~~
+// detail/timer_queue_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 {
namespace detail {
@@ -26,6 +24,4 @@ class timer_queue;
} // namespace detail
} // namespace asio
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_DETAIL_TIMER_QUEUE_FWD_HPP
diff --git a/ext/asio/asio/detail/timer_queue_set.hpp b/ext/asio/asio/detail/timer_queue_set.hpp
index 6860867074..9e8d428414 100644
--- a/ext/asio/asio/detail/timer_queue_set.hpp
+++ b/ext/asio/asio/detail/timer_queue_set.hpp
@@ -1,8 +1,8 @@
//
-// timer_queue_set.hpp
-// ~~~~~~~~~~~~~~~~~~~
+// detail/timer_queue_set.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/detail/timer_queue_base.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
@@ -26,82 +27,28 @@ class timer_queue_set
{
public:
// Constructor.
- timer_queue_set()
- : first_(0)
- {
- }
+ ASIO_DECL timer_queue_set();
// Add a timer queue to the set.
- void insert(timer_queue_base* q)
- {
- q->next_ = first_;
- first_ = q;
- }
+ ASIO_DECL void insert(timer_queue_base* q);
// Remove a timer queue from the set.
- void 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;
- }
- }
- }
- }
+ ASIO_DECL void erase(timer_queue_base* q);
// Determine whether all queues are empty.
- bool all_empty() const
- {
- for (timer_queue_base* p = first_; p; p = p->next_)
- if (!p->empty())
- return false;
- return true;
- }
+ ASIO_DECL bool all_empty() const;
// Get the wait duration in milliseconds.
- long 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;
- }
+ ASIO_DECL long wait_duration_msec(long max_duration) const;
// Get the wait duration in microseconds.
- long 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;
- }
+ ASIO_DECL long wait_duration_usec(long max_duration) const;
// Dequeue all ready timers.
- void get_ready_timers(op_queue<operation>& ops)
- {
- for (timer_queue_base* p = first_; p; p = p->next_)
- p->get_ready_timers(ops);
- }
+ ASIO_DECL void get_ready_timers(op_queue<operation>& ops);
// Dequeue all timers.
- void get_all_timers(op_queue<operation>& ops)
- {
- for (timer_queue_base* p = first_; p; p = p->next_)
- p->get_all_timers(ops);
- }
+ ASIO_DECL void get_all_timers(op_queue<operation>& ops);
private:
timer_queue_base* first_;
@@ -112,4 +59,8 @@ private:
#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/timer_queue_set.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
#endif // ASIO_DETAIL_TIMER_QUEUE_SET_HPP
diff --git a/ext/asio/asio/detail/timer_scheduler.hpp b/ext/asio/asio/detail/timer_scheduler.hpp
index 6822d3f793..1222e630e1 100644
--- a/ext/asio/asio/detail/timer_scheduler.hpp
+++ b/ext/asio/asio/detail/timer_scheduler.hpp
@@ -1,8 +1,8 @@
//
-// timer_scheduler.hpp
-// ~~~~~~~~~~~~~~~~~~~
+// detail/timer_scheduler.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,7 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
#include "asio/detail/timer_scheduler_fwd.hpp"
#if defined(ASIO_HAS_IOCP)
@@ -31,6 +30,4 @@
# include "asio/detail/select_reactor.hpp"
#endif
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_DETAIL_TIMER_SCHEDULER_HPP
diff --git a/ext/asio/asio/detail/timer_scheduler_fwd.hpp b/ext/asio/asio/detail/timer_scheduler_fwd.hpp
index d766a87fb2..5fced5005f 100644
--- a/ext/asio/asio/detail/timer_scheduler_fwd.hpp
+++ b/ext/asio/asio/detail/timer_scheduler_fwd.hpp
@@ -1,8 +1,8 @@
//
-// timer_scheduler_fwd.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~
+// detail/timer_scheduler_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,19 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
-#include "asio/detail/dev_poll_reactor_fwd.hpp"
-#include "asio/detail/epoll_reactor_fwd.hpp"
-#include "asio/detail/kqueue_reactor_fwd.hpp"
-#include "asio/detail/select_reactor_fwd.hpp"
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#if defined(ASIO_HAS_IOCP)
+# include "asio/detail/win_iocp_io_service_fwd.hpp"
+#elif defined(ASIO_HAS_EPOLL)
+# include "asio/detail/epoll_reactor_fwd.hpp"
+#elif defined(ASIO_HAS_KQUEUE)
+# include "asio/detail/kqueue_reactor_fwd.hpp"
+#elif defined(ASIO_HAS_DEV_POLL)
+# include "asio/detail/dev_poll_reactor_fwd.hpp"
+#else
+# include "asio/detail/select_reactor_fwd.hpp"
+#endif
namespace asio {
namespace detail {
@@ -35,12 +41,10 @@ typedef kqueue_reactor timer_scheduler;
#elif defined(ASIO_HAS_DEV_POLL)
typedef dev_poll_reactor timer_scheduler;
#else
-typedef select_reactor<false> timer_scheduler;
+typedef select_reactor timer_scheduler;
#endif
} // namespace detail
} // namespace asio
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_DETAIL_TIMER_SCHEDULER_FWD_HPP
diff --git a/ext/asio/asio/detail/tss_ptr.hpp b/ext/asio/asio/detail/tss_ptr.hpp
index ac67d9f0ce..0218f5f779 100644
--- a/ext/asio/asio/detail/tss_ptr.hpp
+++ b/ext/asio/asio/detail/tss_ptr.hpp
@@ -1,8 +1,8 @@
//
-// tss_ptr.hpp
-// ~~~~~~~~~~~
+// detail/tss_ptr.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_tss_ptr.hpp"
@@ -31,6 +27,8 @@
# error Only Windows and POSIX are supported!
#endif
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
diff --git a/ext/asio/asio/detail/wait_handler.hpp b/ext/asio/asio/detail/wait_handler.hpp
new file mode 100644
index 0000000000..0df16cb6a9
--- /dev/null
+++ b/ext/asio/asio/detail/wait_handler.hpp
@@ -0,0 +1,76 @@
+//
+// detail/wait_handler.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_WAIT_HANDLER_HPP
+#define ASIO_DETAIL_WAIT_HANDLER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#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/timer_op.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Handler>
+class wait_handler : public timer_op
+{
+public:
+ ASIO_DEFINE_HANDLER_PTR(wait_handler);
+
+ wait_handler(Handler h)
+ : timer_op(&wait_handler::do_complete),
+ handler_(h)
+ {
+ }
+
+ 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));
+ 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.
+ detail::binder1<Handler, asio::error_code>
+ handler(h->handler_, h->ec_);
+ 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 // ASIO_DETAIL_WAIT_HANDLER_HPP
diff --git a/ext/asio/asio/detail/weak_ptr.hpp b/ext/asio/asio/detail/weak_ptr.hpp
new file mode 100644
index 0000000000..35dca19a41
--- /dev/null
+++ b/ext/asio/asio/detail/weak_ptr.hpp
@@ -0,0 +1,39 @@
+//
+// detail/weak_ptr.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_WEAK_PTR_HPP
+#define ASIO_DETAIL_WEAK_PTR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <boost/version.hpp>
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1600)
+# include <memory>
+#else
+# include <boost/weak_ptr.hpp>
+#endif
+
+namespace asio {
+namespace detail {
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1600)
+using std::weak_ptr;
+#else
+using boost::weak_ptr;
+#endif
+
+} // namespace detail
+} // namespace asio
+
+#endif // ASIO_DETAIL_WEAK_PTR_HPP
diff --git a/ext/asio/asio/detail/win_event.hpp b/ext/asio/asio/detail/win_event.hpp
index cabb2c389c..71ad7e0b5a 100644
--- a/ext/asio/asio/detail/win_event.hpp
+++ b/ext/asio/asio/detail/win_event.hpp
@@ -1,8 +1,8 @@
//
-// win_event.hpp
-// ~~~~~~~~~~~~~
+// detail/win_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,23 +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_WINDOWS)
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
+#include <boost/assert.hpp>
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/push_options.hpp"
-#include <boost/assert.hpp>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
namespace asio {
namespace detail {
@@ -41,19 +33,7 @@ class win_event
{
public:
// Constructor.
- win_event()
- : event_(::CreateEvent(0, true, false, 0))
- {
- if (!event_)
- {
- DWORD last_error = ::GetLastError();
- asio::system_error e(
- asio::error_code(last_error,
- asio::error::get_system_category()),
- "event");
- boost::throw_exception(e);
- }
- }
+ ASIO_DECL win_event();
// Destructor.
~win_event()
@@ -105,8 +85,12 @@ private:
} // namespace detail
} // namespace asio
-#endif // defined(BOOST_WINDOWS)
-
#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/win_event.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_WINDOWS)
+
#endif // ASIO_DETAIL_WIN_EVENT_HPP
diff --git a/ext/asio/asio/detail/win_fd_set_adapter.hpp b/ext/asio/asio/detail/win_fd_set_adapter.hpp
index 012a10ff76..0cb9d8c9d8 100644
--- a/ext/asio/asio/detail/win_fd_set_adapter.hpp
+++ b/ext/asio/asio/detail/win_fd_set_adapter.hpp
@@ -1,8 +1,8 @@
//
-// win_fd_set_adapter.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~
+// detail/win_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,11 +15,13 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
#include "asio/detail/socket_types.hpp"
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
@@ -81,8 +83,8 @@ private:
} // namespace detail
} // namespace asio
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-
#include "asio/detail/pop_options.hpp"
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
#endif // ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP
diff --git a/ext/asio/asio/detail/win_fenced_block.hpp b/ext/asio/asio/detail/win_fenced_block.hpp
index 6338488f91..011f44b23a 100644
--- a/ext/asio/asio/detail/win_fenced_block.hpp
+++ b/ext/asio/asio/detail/win_fenced_block.hpp
@@ -1,8 +1,8 @@
//
-// win_fenced_block.hpp
-// ~~~~~~~~~~~~~~~~~~~~
+// detail/win_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,16 +15,14 @@
# 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_WINDOWS) && !defined(UNDER_CE)
#include "asio/detail/socket_types.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
@@ -35,7 +33,10 @@ public:
// Constructor.
win_fenced_block()
{
-#if defined(BOOST_MSVC) && (BOOST_MSVC < 1400)
+#if defined(__BORLANDC__)
+ LONG barrier = 0;
+ ::InterlockedExchange(&barrier, 1);
+#elif defined(BOOST_MSVC) && ((BOOST_MSVC < 1400) || !defined(MemoryBarrier))
# if defined(_M_IX86)
# pragma warning(push)
# pragma warning(disable:4793)
@@ -43,15 +44,18 @@ public:
__asm { xchg barrier, eax }
# pragma warning(pop)
# endif // defined(_M_IX86)
-#else // defined(BOOST_MSVC) && (BOOST_MSVC < 1400)
+#else
MemoryBarrier();
-#endif // defined(BOOST_MSVC) && (BOOST_MSVC < 1400)
+#endif
}
// Destructor.
~win_fenced_block()
{
-#if defined(BOOST_MSVC) && (BOOST_MSVC < 1400)
+#if defined(__BORLANDC__)
+ LONG barrier = 0;
+ ::InterlockedExchange(&barrier, 1);
+#elif defined(BOOST_MSVC) && ((BOOST_MSVC < 1400) || !defined(MemoryBarrier))
# if defined(_M_IX86)
# pragma warning(push)
# pragma warning(disable:4793)
@@ -59,17 +63,17 @@ public:
__asm { xchg barrier, eax }
# pragma warning(pop)
# endif // defined(_M_IX86)
-#else // defined(BOOST_MSVC) && (BOOST_MSVC < 1400)
+#else
MemoryBarrier();
-#endif // defined(BOOST_MSVC) && (BOOST_MSVC < 1400)
+#endif
}
};
} // namespace detail
} // namespace asio
-#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
-
#include "asio/detail/pop_options.hpp"
+#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
+
#endif // ASIO_DETAIL_WIN_FENCED_BLOCK_HPP
diff --git a/ext/asio/asio/detail/win_iocp_handle_read_op.hpp b/ext/asio/asio/detail/win_iocp_handle_read_op.hpp
new file mode 100644
index 0000000000..fb358bed7b
--- /dev/null
+++ b/ext/asio/asio/detail/win_iocp_handle_read_op.hpp
@@ -0,0 +1,101 @@
+//
+// detail/win_iocp_handle_read_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// 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_WIN_IOCP_HANDLE_READ_OP_HPP
+#define ASIO_DETAIL_WIN_IOCP_HANDLE_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(ASIO_HAS_IOCP)
+
+#include "asio/error.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.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 {
+
+template <typename MutableBufferSequence, typename Handler>
+class win_iocp_handle_read_op : public operation
+{
+public:
+ ASIO_DEFINE_HANDLER_PTR(win_iocp_handle_read_op);
+
+ win_iocp_handle_read_op(const MutableBufferSequence& buffers, Handler handler)
+ : operation(&win_iocp_handle_read_op::do_complete),
+ buffers_(buffers),
+ 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 operation object.
+ win_iocp_handle_read_op* o(static_cast<win_iocp_handle_read_op*>(base));
+ ptr p = { boost::addressof(o->handler_), o, o };
+
+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+ if (owner)
+ {
+ // Check whether buffers are still valid.
+ buffer_sequence_adapter<asio::mutable_buffer,
+ MutableBufferSequence>::validate(o->buffers_);
+ }
+#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+
+ // Map non-portable errors to their portable counterparts.
+ if (ec.value() == ERROR_HANDLE_EOF)
+ ec = asio::error::eof;
+
+ // 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_, ec, 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:
+ MutableBufferSequence buffers_;
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_WIN_IOCP_HANDLE_READ_OP_HPP
diff --git a/ext/asio/asio/detail/win_iocp_handle_service.hpp b/ext/asio/asio/detail/win_iocp_handle_service.hpp
index bfc159ce72..34f725f163 100644
--- a/ext/asio/asio/detail/win_iocp_handle_service.hpp
+++ b/ext/asio/asio/detail/win_iocp_handle_service.hpp
@@ -1,8 +1,8 @@
//
-// win_iocp_handle_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/win_iocp_handle_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)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -16,26 +16,23 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_IOCP)
-#include "asio/detail/push_options.hpp"
#include <boost/cstdint.hpp>
-#include "asio/detail/pop_options.hpp"
-
#include "asio/error.hpp"
#include "asio/io_service.hpp"
-#include "asio/detail/bind_handler.hpp"
#include "asio/detail/buffer_sequence_adapter.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
-#include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/mutex.hpp"
#include "asio/detail/operation.hpp"
+#include "asio/detail/win_iocp_handle_read_op.hpp"
+#include "asio/detail/win_iocp_handle_write_op.hpp"
#include "asio/detail/win_iocp_io_service.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
@@ -76,75 +73,20 @@ public:
implementation_type* prev_;
};
- win_iocp_handle_service(asio::io_service& io_service)
- : iocp_service_(asio::use_service<win_iocp_io_service>(io_service)),
- mutex_(),
- impl_list_(0)
- {
- }
+ ASIO_DECL win_iocp_handle_service(asio::io_service& io_service);
// Destroy all user-defined handler objects owned by the service.
- void 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_;
- }
- }
+ ASIO_DECL void shutdown_service();
// Construct a new handle implementation.
- void construct(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;
- }
+ ASIO_DECL void construct(implementation_type& impl);
// Destroy a handle implementation.
- void destroy(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_DECL void destroy(implementation_type& impl);
// Assign a native handle to a handle implementation.
- asio::error_code assign(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_DECL asio::error_code assign(implementation_type& impl,
+ const native_type& native_handle, asio::error_code& ec);
// Determine whether the handle is open.
bool is_open(const implementation_type& impl) const
@@ -153,26 +95,8 @@ public:
}
// Destroy a handle implementation.
- asio::error_code close(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_DECL asio::error_code close(implementation_type& impl,
+ asio::error_code& ec);
// Get the native handle representation.
native_type native(const implementation_type& impl) const
@@ -181,106 +105,8 @@ public:
}
// Cancel all operations associated with the handle.
- asio::error_code cancel(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;
- }
-
- class 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);
- }
- }
- };
+ ASIO_DECL asio::error_code cancel(implementation_type& impl,
+ asio::error_code& ec);
// Write the given data. Returns the number of bytes written.
template <typename ConstBufferSequence>
@@ -296,109 +122,13 @@ public:
size_t write_some_at(implementation_type& impl, boost::uint64_t offset,
const ConstBufferSequence& buffers, asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
asio::const_buffer buffer =
buffer_sequence_adapter<asio::const_buffer,
ConstBufferSequence>::first(buffers);
- // 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;
+ return do_write(impl, offset, buffer, ec);
}
- template <typename ConstBufferSequence, typename Handler>
- class write_op : public operation
- {
- public:
- write_op(const ConstBufferSequence& buffers, Handler handler)
- : operation(&write_op::do_complete),
- buffers_(buffers),
- 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 operation object.
- write_op* o(static_cast<write_op*>(base));
- typedef handler_alloc_traits<Handler, write_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- // Make the upcall if required.
- if (owner)
- {
-#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
- // Check whether buffers are still valid.
- buffer_sequence_adapter<asio::const_buffer,
- ConstBufferSequence>::validate(o->buffers_);
-#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-
- // 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_, ec, bytes_transferred);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
- }
-
- private:
- ConstBufferSequence buffers_;
- Handler handler_;
- };
-
// Start an asynchronous write. The data being written must be valid for the
// lifetime of the asynchronous operation.
template <typename ConstBufferSequence, typename Handler>
@@ -415,15 +145,16 @@ public:
const ConstBufferSequence& buffers, Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef write_op<ConstBufferSequence, 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, buffers, handler);
+ typedef win_iocp_handle_write_op<ConstBufferSequence, Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(buffers, handler);
start_write_op(impl, offset,
buffer_sequence_adapter<asio::const_buffer,
- ConstBufferSequence>::first(buffers), ptr.get());
- ptr.release();
+ ConstBufferSequence>::first(buffers), p.p);
+ p.v = p.p = 0;
}
// Read some data. Returns the number of bytes received.
@@ -439,129 +170,13 @@ public:
size_t read_some_at(implementation_type& impl, boost::uint64_t offset,
const MutableBufferSequence& buffers, asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
asio::mutable_buffer buffer =
buffer_sequence_adapter<asio::mutable_buffer,
MutableBufferSequence>::first(buffers);
- // 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;
+ return do_read(impl, offset, buffer, ec);
}
- template <typename MutableBufferSequence, typename Handler>
- class read_op : public operation
- {
- public:
- read_op(const MutableBufferSequence& buffers, Handler handler)
- : operation(&read_op::do_complete),
- buffers_(buffers),
- 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 operation object.
- read_op* o(static_cast<read_op*>(base));
- typedef handler_alloc_traits<Handler, read_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- // Make the upcall if required.
- if (owner)
- {
-#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
- // Check whether buffers are still valid.
- buffer_sequence_adapter<asio::mutable_buffer,
- MutableBufferSequence>::validate(o->buffers_);
-#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-
- // Map non-portable errors to their portable counterparts.
- if (ec.value() == ERROR_HANDLE_EOF)
- {
- ec = asio::error::eof;
- }
-
- // 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_, ec, bytes_transferred);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
- }
-
- private:
- MutableBufferSequence buffers_;
- Handler handler_;
- };
-
// Start an asynchronous read. The buffer for the data being received must be
// valid for the lifetime of the asynchronous operation.
template <typename MutableBufferSequence, typename Handler>
@@ -579,15 +194,16 @@ public:
const MutableBufferSequence& buffers, Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef read_op<MutableBufferSequence, 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, buffers, handler);
+ typedef win_iocp_handle_read_op<MutableBufferSequence, Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(buffers, handler);
start_read_op(impl, offset,
buffer_sequence_adapter<asio::mutable_buffer,
- MutableBufferSequence>::first(buffers), ptr.get());
- ptr.release();
+ MutableBufferSequence>::first(buffers), p.p);
+ p.v = p.p = 0;
}
private:
@@ -613,113 +229,42 @@ private:
void async_read_some_at(implementation_type& impl, boost::uint64_t offset,
const null_buffers& buffers, Handler handler);
+ // Helper class for waiting for synchronous operations to complete.
+ class overlapped_wrapper;
+
+ // Helper function to perform a synchronous write operation.
+ ASIO_DECL size_t do_write(implementation_type& impl,
+ boost::uint64_t offset, const asio::const_buffer& buffer,
+ asio::error_code& ec);
+
// Helper function to start a write operation.
- void start_write_op(implementation_type& impl, boost::uint64_t offset,
- const asio::const_buffer& buffer, operation* op)
- {
- update_cancellation_thread_id(impl);
- iocp_service_.work_started();
+ ASIO_DECL void start_write_op(implementation_type& impl,
+ boost::uint64_t offset, const asio::const_buffer& buffer,
+ operation* op);
- 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);
- }
- }
- }
+ // Helper function to perform a synchronous write operation.
+ ASIO_DECL size_t do_read(implementation_type& impl,
+ boost::uint64_t offset, const asio::mutable_buffer& buffer,
+ asio::error_code& ec);
// Helper function to start a read operation.
- void start_read_op(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);
- }
- }
- }
+ ASIO_DECL void start_read_op(implementation_type& impl,
+ boost::uint64_t offset, const asio::mutable_buffer& buffer,
+ operation* op);
// Update the ID of the thread from which cancellation is safe.
- void update_cancellation_thread_id(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)
- }
+ ASIO_DECL void update_cancellation_thread_id(implementation_type& impl);
// Helper function to close a handle when the associated object is being
// destroyed.
- void close_for_destruction(implementation_type& impl)
- {
- if (is_open(impl))
- {
- ::CloseHandle(impl.handle_);
- impl.handle_ = INVALID_HANDLE_VALUE;
- impl.safe_cancellation_thread_id_ = 0;
- }
- }
+ ASIO_DECL void close_for_destruction(implementation_type& impl);
// The IOCP service used for running asynchronous operations and dispatching
// handlers.
win_iocp_io_service& iocp_service_;
// Mutex to protect access to the linked list of implementations.
- asio::detail::mutex mutex_;
+ mutex mutex_;
// The head of a linked list of all implementations.
implementation_type* impl_list_;
@@ -728,8 +273,12 @@ private:
} // namespace detail
} // namespace asio
-#endif // defined(ASIO_HAS_IOCP)
-
#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/win_iocp_handle_service.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_IOCP)
+
#endif // ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP
diff --git a/ext/asio/asio/detail/win_iocp_handle_write_op.hpp b/ext/asio/asio/detail/win_iocp_handle_write_op.hpp
new file mode 100644
index 0000000000..ddfe8fc2a8
--- /dev/null
+++ b/ext/asio/asio/detail/win_iocp_handle_write_op.hpp
@@ -0,0 +1,97 @@
+//
+// detail/win_iocp_handle_write_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// 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_WIN_IOCP_HANDLE_WRITE_OP_HPP
+#define ASIO_DETAIL_WIN_IOCP_HANDLE_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(ASIO_HAS_IOCP)
+
+#include "asio/error.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.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 {
+
+template <typename ConstBufferSequence, typename Handler>
+class win_iocp_handle_write_op : public operation
+{
+public:
+ ASIO_DEFINE_HANDLER_PTR(win_iocp_handle_write_op);
+
+ win_iocp_handle_write_op(const ConstBufferSequence& buffers, Handler handler)
+ : operation(&win_iocp_handle_write_op::do_complete),
+ buffers_(buffers),
+ 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 operation object.
+ win_iocp_handle_write_op* o(static_cast<win_iocp_handle_write_op*>(base));
+ ptr p = { boost::addressof(o->handler_), o, o };
+
+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+ if (owner)
+ {
+ // Check whether buffers are still valid.
+ buffer_sequence_adapter<asio::const_buffer,
+ ConstBufferSequence>::validate(o->buffers_);
+ }
+#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+
+ // 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_, ec, 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:
+ ConstBufferSequence buffers_;
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_WIN_IOCP_HANDLE_WRITE_OP_HPP
diff --git a/ext/asio/asio/detail/win_iocp_io_service.hpp b/ext/asio/asio/detail/win_iocp_io_service.hpp
index fd899c1146..c8974b60cd 100644
--- a/ext/asio/asio/detail/win_iocp_io_service.hpp
+++ b/ext/asio/asio/detail/win_iocp_io_service.hpp
@@ -1,8 +1,8 @@
//
-// win_iocp_io_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~
+// detail/win_iocp_io_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,33 +15,24 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_IOCP)
-#include "asio/detail/push_options.hpp"
-#include <boost/limits.hpp>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include <boost/scoped_ptr.hpp>
#include "asio/io_service.hpp"
-#include "asio/system_error.hpp"
-#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/mutex.hpp"
#include "asio/detail/op_queue.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/detail/win_iocp_io_service_fwd.hpp"
#include "asio/detail/win_iocp_operation.hpp"
+#include "asio/detail/thread.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
@@ -52,69 +43,13 @@ class win_iocp_io_service
: public asio::detail::service_base<win_iocp_io_service>
{
public:
- typedef win_iocp_operation operation;
-
// Constructor.
- 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),
- timer_thread_(0),
- timer_interrupt_issued_(false)
- {
- }
+ ASIO_DECL win_iocp_io_service(asio::io_service& io_service);
- void 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::system_error e(
- asio::error_code(last_error,
- asio::error::get_system_category()),
- "iocp");
- boost::throw_exception(e);
- }
- }
+ ASIO_DECL void init(size_t concurrency_hint);
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
- {
- ::InterlockedExchange(&shutdown_, 1);
-
- while (::InterlockedExchangeAdd(&outstanding_work_, 0) > 0)
- {
- op_queue<operation> ops;
- timer_queues_.get_all_timers(ops);
- ops.push(completed_ops_);
- if (!ops.empty())
- {
- while (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, max_timeout);
- if (overlapped)
- {
- ::InterlockedDecrement(&outstanding_work_);
- static_cast<operation*>(overlapped)->destroy();
- }
- }
- }
- }
+ ASIO_DECL void shutdown_service();
// Initialise the task. Nothing to do here.
void init_task()
@@ -122,106 +57,23 @@ public:
}
// Register a handle with the IO completion port.
- asio::error_code 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;
- }
+ ASIO_DECL asio::error_code register_handle(
+ HANDLE handle, asio::error_code& ec);
// Run the event loop until stopped or no more work.
- size_t 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;
- }
+ ASIO_DECL size_t run(asio::error_code& ec);
// Run until stopped or one operation is performed.
- size_t 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);
- }
+ ASIO_DECL size_t run_one(asio::error_code& ec);
// Poll for operations without blocking.
- size_t 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;
- }
+ ASIO_DECL size_t poll(asio::error_code& ec);
// Poll for one operation without blocking.
- size_t 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);
- }
+ ASIO_DECL size_t poll_one(asio::error_code& ec);
// Stop the event processing loop.
- void stop()
- {
- if (::InterlockedExchange(&stopped_, 1) == 0)
- {
- if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
- {
- DWORD last_error = ::GetLastError();
- asio::system_error e(
- asio::error_code(last_error,
- asio::error::get_system_category()),
- "pqcs");
- boost::throw_exception(e);
- }
- }
- }
+ ASIO_DECL void stop();
// Reset in preparation for a subsequent run invocation.
void reset()
@@ -244,34 +96,15 @@ public:
// Request invocation of the given handler.
template <typename Handler>
- void 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);
- }
+ void dispatch(Handler handler);
// Request invocation of the given handler and return immediately.
template <typename Handler>
- void post(Handler handler)
- {
- // Allocate and construct an operation to wrap the handler.
- typedef completion_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);
-
- post_immediate_completion(ptr.get());
- ptr.release();
- }
+ void post(Handler handler);
// Request invocation of the given operation and return immediately. Assumes
// that work_started() has not yet been called for the operation.
- void post_immediate_completion(operation* op)
+ void post_immediate_completion(win_iocp_operation* op)
{
work_started();
post_deferred_completion(op);
@@ -279,170 +112,50 @@ public:
// Request invocation of the given operation and return immediately. Assumes
// that work_started() was previously called for the operation.
- void post_deferred_completion(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.
- asio::detail::mutex::scoped_lock lock(timer_mutex_);
- completed_ops_.push(op);
- }
- }
+ ASIO_DECL void post_deferred_completion(win_iocp_operation* op);
// Request invocation of the given operation and return immediately. Assumes
// that work_started() was previously called for the operations.
- void post_deferred_completions(op_queue<operation>& ops)
- {
- while (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.
- asio::detail::mutex::scoped_lock lock(timer_mutex_);
- completed_ops_.push(op);
- completed_ops_.push(ops);
- }
- }
- }
+ ASIO_DECL void post_deferred_completions(
+ op_queue<win_iocp_operation>& ops);
// Called after starting an overlapped I/O operation that did not complete
// immediately. The caller must have already called work_started() prior to
// starting the operation.
- void on_pending(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.
- asio::detail::mutex::scoped_lock lock(timer_mutex_);
- completed_ops_.push(op);
- }
- }
- }
+ ASIO_DECL void on_pending(win_iocp_operation* op);
// Called after starting an overlapped I/O operation that completed
// immediately. The caller must have already called work_started() prior to
// starting the operation.
- void on_completion(operation* op,
- DWORD last_error = 0, DWORD bytes_transferred = 0)
- {
- // 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.
- asio::detail::mutex::scoped_lock lock(timer_mutex_);
- completed_ops_.push(op);
- }
- }
+ ASIO_DECL void on_completion(win_iocp_operation* op,
+ DWORD last_error = 0, DWORD bytes_transferred = 0);
// Called after starting an overlapped I/O operation that completed
// immediately. The caller must have already called work_started() prior to
// starting the operation.
- void on_completion(operation* op,
- const asio::error_code& ec, DWORD bytes_transferred = 0)
- {
- // 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.
- asio::detail::mutex::scoped_lock lock(timer_mutex_);
- completed_ops_.push(op);
- }
- }
+ ASIO_DECL void on_completion(win_iocp_operation* op,
+ const asio::error_code& ec, DWORD bytes_transferred = 0);
// Add a new timer queue to the service.
template <typename Time_Traits>
- void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
- {
- asio::detail::mutex::scoped_lock lock(timer_mutex_);
- timer_queues_.insert(&timer_queue);
- }
+ void add_timer_queue(timer_queue<Time_Traits>& timer_queue);
// Remove a timer queue from the service.
template <typename Time_Traits>
- void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
- {
- asio::detail::mutex::scoped_lock lock(timer_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)
- {
- // If the service has been shut down we silently discard the timer.
- if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
- return;
-
- asio::detail::mutex::scoped_lock lock(timer_mutex_);
- bool interrupt = timer_queue.enqueue_timer(time, op, token);
- work_started();
- if (interrupt && !timer_interrupt_issued_)
- {
- timer_interrupt_issued_ = true;
- lock.unlock();
- ::PostQueuedCompletionStatus(iocp_.handle,
- 0, steal_timer_dispatching, 0);
- }
- }
+ 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 associated with the given token. Returns the number of
// handlers that have been posted or dispatched.
template <typename Time_Traits>
- std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
- {
- // If the service has been shut down we silently ignore the cancellation.
- if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
- return 0;
-
- asio::detail::mutex::scoped_lock lock(timer_mutex_);
- op_queue<operation> ops;
- std::size_t n = timer_queue.cancel_timer(token, ops);
- post_deferred_completions(ops);
- if (n > 0 && !timer_interrupt_issued_)
- {
- timer_interrupt_issued_ = true;
- lock.unlock();
- ::PostQueuedCompletionStatus(iocp_.handle,
- 0, steal_timer_dispatching, 0);
- }
- return n;
- }
+ std::size_t cancel_timer(timer_queue<Time_Traits>& queue,
+ typename timer_queue<Time_Traits>::per_timer_data& timer);
private:
#if defined(WINVER) && (WINVER < 0x0500)
@@ -456,181 +169,30 @@ private:
// Dequeues at most one operation from the I/O completion port, and then
// executes it. Returns the number of operations that were dequeued (i.e.
// either 0 or 1).
- size_t do_one(bool block, asio::error_code& ec)
- {
- long this_thread_id = static_cast<long>(::GetCurrentThreadId());
-
- for (;;)
- {
- // Try to acquire responsibility for dispatching timers.
- bool dispatching_timers = (::InterlockedCompareExchange(
- &timer_thread_, this_thread_id, 0) == 0);
-
- // Calculate timeout for GetQueuedCompletionStatus call.
- DWORD timeout = max_timeout;
- if (dispatching_timers)
- {
- asio::detail::mutex::scoped_lock lock(timer_mutex_);
- timer_interrupt_issued_ = false;
- timeout = get_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 ? timeout : 0);
- DWORD last_error = ::GetLastError();
-
- // Dispatch any pending timers.
- if (dispatching_timers)
- {
- asio::detail::mutex::scoped_lock lock(timer_mutex_);
- op_queue<operation> ops;
- ops.push(completed_ops_);
- timer_queues_.get_ready_timers(ops);
- post_deferred_completions(ops);
- }
-
- if (!ok && overlapped == 0)
- {
- if (block && last_error == WAIT_TIMEOUT)
- {
- // Relinquish responsibility for dispatching timers.
- if (dispatching_timers)
- {
- ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id);
- }
-
- continue;
- }
-
- // Transfer responsibility for dispatching timers to another thread.
- if (dispatching_timers && ::InterlockedCompareExchange(
- &timer_thread_, 0, this_thread_id) == this_thread_id)
- {
- ::PostQueuedCompletionStatus(iocp_.handle,
- 0, transfer_timer_dispatching, 0);
- }
-
- ec = asio::error_code();
- return 0;
- }
- else if (overlapped)
- {
- operation* op = static_cast<operation*>(overlapped);
- asio::error_code result_ec(last_error,
- asio::error::get_system_category());
-
- // Transfer responsibility for dispatching timers to another thread.
- if (dispatching_timers && ::InterlockedCompareExchange(
- &timer_thread_, 0, this_thread_id) == this_thread_id)
- {
- ::PostQueuedCompletionStatus(iocp_.handle,
- 0, transfer_timer_dispatching, 0);
- }
-
- // 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 (completion_key == transfer_timer_dispatching)
- {
- // Woken up to try to acquire responsibility for dispatching timers.
- ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id);
- }
- else if (completion_key == steal_timer_dispatching)
- {
- // Woken up to steal responsibility for dispatching timers.
- ::InterlockedExchange(&timer_thread_, 0);
- }
- else
- {
- // Relinquish responsibility for dispatching timers. If the io_service
- // is not being stopped then the thread will get an opportunity to
- // reacquire timer responsibility on the next loop iteration.
- if (dispatching_timers)
- {
- ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id);
- }
-
- // 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;
- }
- }
- }
- }
+ ASIO_DECL size_t do_one(bool block, asio::error_code& ec);
- // Get the timeout value for the GetQueuedCompletionStatus call. The timeout
- // value is returned as a number of milliseconds. We will wait no longer than
- // 1000 milliseconds.
- DWORD get_timeout()
- {
- return timer_queues_.wait_duration_msec(max_timeout);
- }
+ // 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();
// Helper class to call work_finished() on block exit.
- struct work_finished_on_block_exit
- {
- ~work_finished_on_block_exit()
- {
- io_service_->work_finished();
- }
+ struct work_finished_on_block_exit;
- win_iocp_io_service* io_service_;
+ // Helper class for managing a HANDLE.
+ struct auto_handle
+ {
+ HANDLE handle;
+ auto_handle() : handle(0) {}
+ ~auto_handle() { if (handle) ::CloseHandle(handle); }
};
// The IO completion port used for queueing operations.
- struct iocp_holder
- {
- HANDLE handle;
- iocp_holder() : handle(0) {}
- ~iocp_holder() { if (handle) ::CloseHandle(handle); }
- } iocp_;
+ auto_handle iocp_;
// The count of unfinished work.
long outstanding_work_;
@@ -643,44 +205,61 @@ private:
enum
{
- // Maximum GetQueuedCompletionStatus timeout, in milliseconds.
- max_timeout = 500,
+ // Timeout to use with GetQueuedCompletionStatus. Some versions of windows
+ // have a "bug" where a call to GetQueuedCompletionStatus can appear stuck
+ // even though there are events waiting on the queue. Using a timeout helps
+ // to work around the issue.
+ gqcs_timeout = 500,
+
+ // Maximum waitable timer timeout, in milliseconds.
+ max_timeout_msec = 5 * 60 * 1000,
- // Completion key value to indicate that responsibility for dispatching
- // timers is being cooperatively transferred from one thread to another.
- transfer_timer_dispatching = 1,
+ // Maximum waitable timer timeout, in microseconds.
+ max_timeout_usec = max_timeout_msec * 1000,
- // Completion key value to indicate that responsibility for dispatching
- // timers should be stolen from another thread.
- steal_timer_dispatching = 2,
+ // Completion key value used to wake up a thread to dispatch timers or
+ // completed operations.
+ wake_for_dispatch = 1,
// Completion key value to indicate that an operation has posted with the
// original last_error and bytes_transferred values stored in the fields of
// the OVERLAPPED structure.
- overlapped_contains_result = 3
+ overlapped_contains_result = 2
};
- // The thread that's currently in charge of dispatching timers.
- long timer_thread_;
+ // Function object for processing timeouts in a background thread.
+ struct timer_thread_function;
+ friend struct timer_thread_function;
+
+ // Background thread used for processing timeouts.
+ boost::scoped_ptr<thread> timer_thread_;
+
+ // A waitable timer object used for waiting for timeouts.
+ auto_handle waitable_timer_;
- // Mutex for protecting access to the timer queues.
- mutex timer_mutex_;
+ // Non-zero if timers or completed operations need to be dispatched.
+ long dispatch_required_;
- // Whether a thread has been interrupted to process a new timeout.
- bool timer_interrupt_issued_;
+ // Mutex for protecting access to the timer queues and completed operations.
+ mutex dispatch_mutex_;
// The timer queues.
timer_queue_set timer_queues_;
// The operations that are ready to dispatch.
- op_queue<operation> completed_ops_;
+ op_queue<win_iocp_operation> completed_ops_;
};
} // namespace detail
} // namespace asio
-#endif // defined(ASIO_HAS_IOCP)
-
#include "asio/detail/pop_options.hpp"
+#include "asio/detail/impl/win_iocp_io_service.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/win_iocp_io_service.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_IOCP)
+
#endif // ASIO_DETAIL_WIN_IOCP_IO_SERVICE_HPP
diff --git a/ext/asio/asio/detail/win_iocp_io_service_fwd.hpp b/ext/asio/asio/detail/win_iocp_io_service_fwd.hpp
index 29d2a05481..9f03743d2b 100644
--- a/ext/asio/asio/detail/win_iocp_io_service_fwd.hpp
+++ b/ext/asio/asio/detail/win_iocp_io_service_fwd.hpp
@@ -1,8 +1,8 @@
//
-// win_iocp_io_service_fwd.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/win_iocp_io_service_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,22 +15,9 @@
# 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"
-
-#include "asio/detail/socket_types.hpp"
-
-// This service is only supported on Win32 (NT4 and later).
-#if !defined(ASIO_DISABLE_IOCP)
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
-#if !defined(UNDER_CE)
-
-// Define this to indicate that IOCP is supported on the target platform.
-#define ASIO_HAS_IOCP 1
+#if defined(ASIO_HAS_IOCP)
namespace asio {
namespace detail {
@@ -41,11 +28,6 @@ class win_iocp_overlapped_ptr;
} // namespace detail
} // namespace asio
-#endif // !defined(UNDER_CE)
-#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-#endif // !defined(ASIO_DISABLE_IOCP)
-
-#include "asio/detail/pop_options.hpp"
+#endif // defined(ASIO_HAS_IOCP)
#endif // ASIO_DETAIL_WIN_IOCP_IO_SERVICE_FWD_HPP
diff --git a/ext/asio/asio/detail/win_iocp_null_buffers_op.hpp b/ext/asio/asio/detail/win_iocp_null_buffers_op.hpp
new file mode 100644
index 0000000000..e39fff7c75
--- /dev/null
+++ b/ext/asio/asio/detail/win_iocp_null_buffers_op.hpp
@@ -0,0 +1,112 @@
+//
+// detail/win_iocp_null_buffers_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_WIN_IOCP_NULL_BUFFERS_OP_HPP
+#define ASIO_DETAIL_WIN_IOCP_NULL_BUFFERS_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(ASIO_HAS_IOCP)
+
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Handler>
+class win_iocp_null_buffers_op : public reactor_op
+{
+public:
+ ASIO_DEFINE_HANDLER_PTR(win_iocp_null_buffers_op);
+
+ win_iocp_null_buffers_op(socket_ops::weak_cancel_token_type cancel_token,
+ Handler handler)
+ : reactor_op(&win_iocp_null_buffers_op::do_perform,
+ &win_iocp_null_buffers_op::do_complete),
+ cancel_token_(cancel_token),
+ handler_(handler)
+ {
+ }
+
+ static bool do_perform(reactor_op*)
+ {
+ return true;
+ }
+
+ static void do_complete(io_service_impl* owner, operation* base,
+ asio::error_code ec, std::size_t bytes_transferred)
+ {
+ // Take ownership of the operation object.
+ win_iocp_null_buffers_op* o(static_cast<win_iocp_null_buffers_op*>(base));
+ ptr p = { boost::addressof(o->handler_), o, o };
+
+ // The reactor may have stored a result in the operation object.
+ if (o->ec_)
+ ec = o->ec_;
+
+ // Map non-portable errors to their portable counterparts.
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ {
+ if (o->cancel_token_.expired())
+ ec = asio::error::operation_aborted;
+ else
+ ec = asio::error::connection_reset;
+ }
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = asio::error::connection_refused;
+ }
+
+ // 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_, ec, 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:
+ socket_ops::weak_cancel_token_type cancel_token_;
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_WIN_IOCP_NULL_BUFFERS_OP_HPP
diff --git a/ext/asio/asio/detail/win_iocp_operation.hpp b/ext/asio/asio/detail/win_iocp_operation.hpp
index ac8106255a..649edd1a88 100644
--- a/ext/asio/asio/detail/win_iocp_operation.hpp
+++ b/ext/asio/asio/detail/win_iocp_operation.hpp
@@ -1,8 +1,8 @@
//
-// win_iocp_operation.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~
+// detail/win_iocp_operation.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/win_iocp_io_service_fwd.hpp"
+#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_IOCP)
-#include "asio/error_code.hpp"
#include "asio/detail/op_queue.hpp"
+#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#include "asio/error_code.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
@@ -82,8 +83,8 @@ private:
} // namespace detail
} // namespace asio
-#endif // defined(ASIO_HAS_IOCP)
-
#include "asio/detail/pop_options.hpp"
+#endif // defined(ASIO_HAS_IOCP)
+
#endif // ASIO_DETAIL_WIN_IOCP_OPERATION_HPP
diff --git a/ext/asio/asio/detail/win_iocp_overlapped_op.hpp b/ext/asio/asio/detail/win_iocp_overlapped_op.hpp
new file mode 100644
index 0000000000..f2b7ddf624
--- /dev/null
+++ b/ext/asio/asio/detail/win_iocp_overlapped_op.hpp
@@ -0,0 +1,84 @@
+//
+// detail/win_iocp_overlapped_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_WIN_IOCP_OVERLAPPED_OP_HPP
+#define ASIO_DETAIL_WIN_IOCP_OVERLAPPED_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(ASIO_HAS_IOCP)
+
+#include "asio/error.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_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/operation.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Handler>
+class win_iocp_overlapped_op : public operation
+{
+public:
+ ASIO_DEFINE_HANDLER_PTR(win_iocp_overlapped_op);
+
+ win_iocp_overlapped_op(Handler handler)
+ : operation(&win_iocp_overlapped_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 operation object.
+ win_iocp_overlapped_op* o(static_cast<win_iocp_overlapped_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_, ec, 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(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_WIN_IOCP_OVERLAPPED_OP_HPP
diff --git a/ext/asio/asio/detail/win_iocp_overlapped_ptr.hpp b/ext/asio/asio/detail/win_iocp_overlapped_ptr.hpp
index 47a3f70cf1..919affe414 100644
--- a/ext/asio/asio/detail/win_iocp_overlapped_ptr.hpp
+++ b/ext/asio/asio/detail/win_iocp_overlapped_ptr.hpp
@@ -1,8 +1,8 @@
//
-// win_iocp_overlapped_ptr.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/win_iocp_overlapped_ptr.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,18 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_IOCP)
-#include "asio/detail/fenced_block.hpp"
+#include <boost/utility/addressof.hpp>
+#include "asio/io_service.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/noncopyable.hpp"
+#include "asio/detail/win_iocp_overlapped_op.hpp"
#include "asio/detail/win_iocp_io_service.hpp"
-#include "asio/detail/win_iocp_operation.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
@@ -74,13 +76,15 @@ public:
template <typename Handler>
void reset(asio::io_service& io_service, Handler handler)
{
- typedef overlapped_op<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 win_iocp_overlapped_op<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);
io_service.impl_.work_started();
reset();
- ptr_ = ptr.release();
+ ptr_ = p.p;
+ p.v = p.p = 0;
iocp_service_ = &io_service.impl_;
}
@@ -122,44 +126,6 @@ public:
}
private:
- template <typename Handler>
- struct overlapped_op : public win_iocp_operation
- {
- overlapped_op(Handler handler)
- : win_iocp_operation(&overlapped_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 operation object.
- overlapped_op* o(static_cast<overlapped_op*>(base));
- typedef handler_alloc_traits<Handler, overlapped_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- // 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::binder2<Handler, asio::error_code, std::size_t>
- handler(o->handler_, ec, bytes_transferred);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
- }
-
- private:
- Handler handler_;
- };
-
win_iocp_operation* ptr_;
win_iocp_io_service* iocp_service_;
};
@@ -167,8 +133,8 @@ private:
} // namespace detail
} // namespace asio
-#endif // defined(ASIO_HAS_IOCP)
-
#include "asio/detail/pop_options.hpp"
+#endif // defined(ASIO_HAS_IOCP)
+
#endif // ASIO_DETAIL_WIN_IOCP_OVERLAPPED_PTR_HPP
diff --git a/ext/asio/asio/detail/win_iocp_serial_port_service.hpp b/ext/asio/asio/detail/win_iocp_serial_port_service.hpp
index ed5f75e91c..bf3a692d55 100644
--- a/ext/asio/asio/detail/win_iocp_serial_port_service.hpp
+++ b/ext/asio/asio/detail/win_iocp_serial_port_service.hpp
@@ -1,8 +1,8 @@
//
-// win_iocp_serial_port_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/win_iocp_serial_port_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)
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -16,21 +16,17 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <cstring>
-#include <string>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#include "asio/detail/config.hpp"
-#if defined(ASIO_HAS_IOCP)
+#if defined(ASIO_HAS_IOCP) && defined(ASIO_HAS_SERIAL_PORT)
+#include <string>
#include "asio/error.hpp"
#include "asio/io_service.hpp"
#include "asio/detail/win_iocp_handle_service.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
@@ -38,133 +34,56 @@ namespace detail {
class win_iocp_serial_port_service
{
public:
- // The native type of a stream handle.
+ // The native type of a serial port.
typedef win_iocp_handle_service::native_type native_type;
- // The implementation type of the stream handle.
+ // The implementation type of the serial port.
typedef win_iocp_handle_service::implementation_type implementation_type;
- win_iocp_serial_port_service(asio::io_service& io_service)
- : handle_service_(io_service)
- {
- }
+ // Constructor.
+ ASIO_DECL win_iocp_serial_port_service(
+ asio::io_service& io_service);
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
- {
- }
+ ASIO_DECL void shutdown_service();
- // Construct a new handle implementation.
+ // Construct a new serial port implementation.
void construct(implementation_type& impl)
{
handle_service_.construct(impl);
}
- // Destroy a handle implementation.
+ // Destroy a serial port implementation.
void destroy(implementation_type& impl)
{
handle_service_.destroy(impl);
}
// Open the serial port using the specified device name.
- asio::error_code open(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 memcpy.
- ::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_DECL asio::error_code open(implementation_type& impl,
+ const std::string& device, asio::error_code& ec);
- // Assign a native handle to a handle implementation.
+ // Assign a native handle to a serial port implementation.
asio::error_code assign(implementation_type& impl,
const native_type& native_handle, asio::error_code& ec)
{
return handle_service_.assign(impl, native_handle, ec);
}
- // Determine whether the handle is open.
+ // Determine whether the serial port is open.
bool is_open(const implementation_type& impl) const
{
return handle_service_.is_open(impl);
}
- // Destroy a handle implementation.
+ // Destroy a serial port implementation.
asio::error_code close(implementation_type& impl,
asio::error_code& ec)
{
return handle_service_.close(impl, ec);
}
- // Get the native handle representation.
+ // Get the native serial port representation.
native_type native(implementation_type& impl)
{
return handle_service_.native(impl);
@@ -182,32 +101,9 @@ public:
asio::error_code set_option(implementation_type& impl,
const SettableSerialPortOption& 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 (option.store(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;
+ return do_set_option(impl,
+ &win_iocp_serial_port_service::store_option<SettableSerialPortOption>,
+ &option, ec);
}
// Get an option from the serial port.
@@ -215,20 +111,9 @@ public:
asio::error_code get_option(const implementation_type& impl,
GettableSerialPortOption& option, asio::error_code& ec) const
{
- 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;
- }
-
- return option.load(dcb, ec);
+ return do_get_option(impl,
+ &win_iocp_serial_port_service::load_option<GettableSerialPortOption>,
+ &option, ec);
}
// Send a break sequence to the serial port.
@@ -274,6 +159,41 @@ public:
}
private:
+ // Function pointer type for storing a serial port option.
+ typedef asio::error_code (*store_function_type)(
+ const void*, ::DCB&, asio::error_code&);
+
+ // Helper function template to store a serial port option.
+ template <typename SettableSerialPortOption>
+ static asio::error_code store_option(const void* option,
+ ::DCB& storage, asio::error_code& ec)
+ {
+ return static_cast<const SettableSerialPortOption*>(option)->store(
+ storage, ec);
+ }
+
+ // Helper function to set a serial port option.
+ ASIO_DECL asio::error_code do_set_option(
+ implementation_type& impl, store_function_type store,
+ const void* option, asio::error_code& ec);
+
+ // Function pointer type for loading a serial port option.
+ typedef asio::error_code (*load_function_type)(
+ void*, const ::DCB&, asio::error_code&);
+
+ // Helper function template to load a serial port option.
+ template <typename GettableSerialPortOption>
+ static asio::error_code load_option(void* option,
+ const ::DCB& storage, asio::error_code& ec)
+ {
+ return static_cast<GettableSerialPortOption*>(option)->load(storage, ec);
+ }
+
+ // Helper function to get a serial port option.
+ ASIO_DECL asio::error_code do_get_option(
+ const implementation_type& impl, load_function_type load,
+ void* option, asio::error_code& ec) const;
+
// The implementation used for initiating asynchronous operations.
win_iocp_handle_service handle_service_;
};
@@ -281,8 +201,12 @@ private:
} // namespace detail
} // namespace asio
-#endif // defined(ASIO_HAS_IOCP)
-
#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/win_iocp_serial_port_service.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_IOCP) && defined(ASIO_HAS_SERIAL_PORT)
+
#endif // ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP
diff --git a/ext/asio/asio/detail/win_iocp_socket_accept_op.hpp b/ext/asio/asio/detail/win_iocp_socket_accept_op.hpp
new file mode 100644
index 0000000000..a71c7c0de5
--- /dev/null
+++ b/ext/asio/asio/detail/win_iocp_socket_accept_op.hpp
@@ -0,0 +1,158 @@
+//
+// detail/win_iocp_socket_accept_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_WIN_IOCP_SOCKET_ACCEPT_OP_HPP
+#define ASIO_DETAIL_WIN_IOCP_SOCKET_ACCEPT_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(ASIO_HAS_IOCP)
+
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.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/socket_ops.hpp"
+#include "asio/detail/win_iocp_socket_service_base.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename Socket, typename Protocol, typename Handler>
+class win_iocp_socket_accept_op : public operation
+{
+public:
+ ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_accept_op);
+
+ win_iocp_socket_accept_op(win_iocp_socket_service_base& socket_service,
+ socket_type socket, Socket& peer, const Protocol& protocol,
+ typename Protocol::endpoint* peer_endpoint,
+ bool enable_connection_aborted, Handler handler)
+ : operation(&win_iocp_socket_accept_op::do_complete),
+ socket_service_(socket_service),
+ socket_(socket),
+ peer_(peer),
+ protocol_(protocol),
+ peer_endpoint_(peer_endpoint),
+ enable_connection_aborted_(enable_connection_aborted),
+ handler_(handler)
+ {
+ }
+
+ socket_holder& new_socket()
+ {
+ return new_socket_;
+ }
+
+ void* output_buffer()
+ {
+ return output_buffer_;
+ }
+
+ DWORD address_length()
+ {
+ return sizeof(sockaddr_storage_type) + 16;
+ }
+
+ static void do_complete(io_service_impl* owner, operation* base,
+ asio::error_code ec, std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the operation object.
+ win_iocp_socket_accept_op* o(static_cast<win_iocp_socket_accept_op*>(base));
+ ptr p = { boost::addressof(o->handler_), o, o };
+
+ if (owner)
+ {
+ typename Protocol::endpoint peer_endpoint;
+ std::size_t addr_len = peer_endpoint.capacity();
+ socket_ops::complete_iocp_accept(o->socket_,
+ o->output_buffer(), o->address_length(),
+ peer_endpoint.data(), &addr_len,
+ o->new_socket_.get(), ec);
+
+ // Restart the accept operation if we got the connection_aborted error
+ // and the enable_connection_aborted socket option is not set.
+ if (ec == asio::error::connection_aborted
+ && !o->enable_connection_aborted_)
+ {
+ o->reset();
+ o->socket_service_.restart_accept_op(o->socket_,
+ o->new_socket_, o->protocol_.family(),
+ o->protocol_.type(), o->protocol_.protocol(),
+ o->output_buffer(), o->address_length(), o);
+ p.v = p.p = 0;
+ return;
+ }
+
+ // If the socket was successfully accepted, transfer ownership of the
+ // socket to the peer object.
+ if (!ec)
+ {
+ o->peer_.assign(o->protocol_,
+ typename Socket::native_type(
+ o->new_socket_.get(), peer_endpoint), ec);
+ if (!ec)
+ o->new_socket_.release();
+ }
+
+ // Pass endpoint back to caller.
+ if (o->peer_endpoint_)
+ *o->peer_endpoint_ = peer_endpoint;
+ }
+
+ // 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(o->handler_, ec);
+ 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:
+ win_iocp_socket_service_base& socket_service_;
+ socket_type socket_;
+ socket_holder new_socket_;
+ Socket& peer_;
+ Protocol protocol_;
+ typename Protocol::endpoint* peer_endpoint_;
+ unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];
+ bool enable_connection_aborted_;
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_ACCEPT_OP_HPP
diff --git a/ext/asio/asio/detail/win_iocp_socket_recv_op.hpp b/ext/asio/asio/detail/win_iocp_socket_recv_op.hpp
new file mode 100644
index 0000000000..3ab4fcb4d5
--- /dev/null
+++ b/ext/asio/asio/detail/win_iocp_socket_recv_op.hpp
@@ -0,0 +1,108 @@
+//
+// detail/win_iocp_socket_recv_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_WIN_IOCP_SOCKET_RECV_OP_HPP
+#define ASIO_DETAIL_WIN_IOCP_SOCKET_RECV_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(ASIO_HAS_IOCP)
+
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.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/socket_ops.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence, typename Handler>
+class win_iocp_socket_recv_op : public operation
+{
+public:
+ ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_recv_op);
+
+ win_iocp_socket_recv_op(socket_ops::state_type state,
+ socket_ops::weak_cancel_token_type cancel_token,
+ const MutableBufferSequence& buffers, Handler handler)
+ : operation(&win_iocp_socket_recv_op::do_complete),
+ state_(state),
+ cancel_token_(cancel_token),
+ buffers_(buffers),
+ 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 operation object.
+ win_iocp_socket_recv_op* o(static_cast<win_iocp_socket_recv_op*>(base));
+ ptr p = { boost::addressof(o->handler_), o, o };
+
+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+ // Check whether buffers are still valid.
+ if (owner)
+ {
+ buffer_sequence_adapter<asio::mutable_buffer,
+ MutableBufferSequence>::validate(o->buffers_);
+ }
+#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+
+ socket_ops::complete_iocp_recv(o->state_, o->cancel_token_,
+ buffer_sequence_adapter<asio::mutable_buffer,
+ MutableBufferSequence>::all_empty(o->buffers_),
+ ec, bytes_transferred);
+
+ // 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_, ec, 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:
+ socket_ops::state_type state_;
+ socket_ops::weak_cancel_token_type cancel_token_;
+ MutableBufferSequence buffers_;
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_RECV_OP_HPP
diff --git a/ext/asio/asio/detail/win_iocp_socket_recvfrom_op.hpp b/ext/asio/asio/detail/win_iocp_socket_recvfrom_op.hpp
new file mode 100644
index 0000000000..d1e2ecec58
--- /dev/null
+++ b/ext/asio/asio/detail/win_iocp_socket_recvfrom_op.hpp
@@ -0,0 +1,116 @@
+//
+// detail/win_iocp_socket_recvfrom_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_WIN_IOCP_SOCKET_RECVFROM_OP_HPP
+#define ASIO_DETAIL_WIN_IOCP_SOCKET_RECVFROM_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(ASIO_HAS_IOCP)
+
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.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/socket_ops.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename MutableBufferSequence, typename Endpoint, typename Handler>
+class win_iocp_socket_recvfrom_op : public operation
+{
+public:
+ ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_recvfrom_op);
+
+ win_iocp_socket_recvfrom_op(Endpoint& endpoint,
+ socket_ops::weak_cancel_token_type cancel_token,
+ const MutableBufferSequence& buffers, Handler handler)
+ : operation(&win_iocp_socket_recvfrom_op::do_complete),
+ endpoint_(endpoint),
+ endpoint_size_(static_cast<int>(endpoint.capacity())),
+ cancel_token_(cancel_token),
+ buffers_(buffers),
+ handler_(handler)
+ {
+ }
+
+ int& endpoint_size()
+ {
+ return endpoint_size_;
+ }
+
+ static void do_complete(io_service_impl* owner, operation* base,
+ asio::error_code ec, std::size_t bytes_transferred)
+ {
+ // Take ownership of the operation object.
+ win_iocp_socket_recvfrom_op* o(
+ static_cast<win_iocp_socket_recvfrom_op*>(base));
+ ptr p = { boost::addressof(o->handler_), o, o };
+
+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+ // Check whether buffers are still valid.
+ if (owner)
+ {
+ buffer_sequence_adapter<asio::mutable_buffer,
+ MutableBufferSequence>::validate(o->buffers_);
+ }
+#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+
+ socket_ops::complete_iocp_recvfrom(o->cancel_token_, ec);
+
+ // Record the size of the endpoint returned by the operation.
+ o->endpoint_.resize(o->endpoint_size_);
+
+ // 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_, ec, 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:
+ Endpoint& endpoint_;
+ int endpoint_size_;
+ socket_ops::weak_cancel_token_type cancel_token_;
+ MutableBufferSequence buffers_;
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_RECVFROM_OP_HPP
diff --git a/ext/asio/asio/detail/win_iocp_socket_send_op.hpp b/ext/asio/asio/detail/win_iocp_socket_send_op.hpp
new file mode 100644
index 0000000000..56f3f2d304
--- /dev/null
+++ b/ext/asio/asio/detail/win_iocp_socket_send_op.hpp
@@ -0,0 +1,102 @@
+//
+// detail/win_iocp_socket_send_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_WIN_IOCP_SOCKET_SEND_OP_HPP
+#define ASIO_DETAIL_WIN_IOCP_SOCKET_SEND_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(ASIO_HAS_IOCP)
+
+#include <boost/utility/addressof.hpp>
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.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/socket_ops.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+template <typename ConstBufferSequence, typename Handler>
+class win_iocp_socket_send_op : public operation
+{
+public:
+ ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_send_op);
+
+ win_iocp_socket_send_op(socket_ops::weak_cancel_token_type cancel_token,
+ const ConstBufferSequence& buffers, Handler handler)
+ : operation(&win_iocp_socket_send_op::do_complete),
+ cancel_token_(cancel_token),
+ buffers_(buffers),
+ 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 operation object.
+ win_iocp_socket_send_op* o(static_cast<win_iocp_socket_send_op*>(base));
+ ptr p = { boost::addressof(o->handler_), o, o };
+
+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+ // Check whether buffers are still valid.
+ if (owner)
+ {
+ buffer_sequence_adapter<asio::const_buffer,
+ ConstBufferSequence>::validate(o->buffers_);
+ }
+#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
+
+ socket_ops::complete_iocp_send(o->cancel_token_, ec);
+
+ // 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_, ec, 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:
+ socket_ops::weak_cancel_token_type cancel_token_;
+ ConstBufferSequence buffers_;
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_SEND_OP_HPP
diff --git a/ext/asio/asio/detail/win_iocp_socket_service.hpp b/ext/asio/asio/detail/win_iocp_socket_service.hpp
index cb1d2037de..b476f8bb2b 100644
--- a/ext/asio/asio/detail/win_iocp_socket_service.hpp
+++ b/ext/asio/asio/detail/win_iocp_socket_service.hpp
@@ -1,8 +1,8 @@
//
-// win_iocp_socket_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/win_iocp_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,19 +15,12 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
+#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_IOCP)
-#include "asio/detail/push_options.hpp"
#include <cstring>
-#include <boost/shared_ptr.hpp>
-#include <boost/type_traits/is_same.hpp>
-#include <boost/weak_ptr.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include <boost/utility/addressof.hpp>
#include "asio/error.hpp"
#include "asio/io_service.hpp"
#include "asio/socket_base.hpp"
@@ -37,20 +30,27 @@
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/mutex.hpp"
-#include "asio/detail/null_buffers_op.hpp"
#include "asio/detail/operation.hpp"
+#include "asio/detail/reactive_socket_connect_op.hpp"
#include "asio/detail/reactor.hpp"
#include "asio/detail/reactor_op.hpp"
#include "asio/detail/socket_holder.hpp"
#include "asio/detail/socket_ops.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/win_iocp_io_service.hpp"
+#include "asio/detail/win_iocp_null_buffers_op.hpp"
+#include "asio/detail/win_iocp_socket_accept_op.hpp"
+#include "asio/detail/win_iocp_socket_recvfrom_op.hpp"
+#include "asio/detail/win_iocp_socket_send_op.hpp"
+#include "asio/detail/win_iocp_socket_service_base.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
template <typename Protocol>
-class win_iocp_socket_service
+class win_iocp_socket_service : public win_iocp_socket_service_base
{
public:
// The protocol type.
@@ -59,10 +59,6 @@ public:
// The endpoint type.
typedef typename Protocol::endpoint endpoint_type;
- struct noop_deleter { void operator()(void*) {} };
- typedef boost::shared_ptr<void> shared_cancel_token_type;
- typedef boost::weak_ptr<void> weak_cancel_token_type;
-
// The native type of a socket.
class native_type
{
@@ -92,11 +88,6 @@ public:
return socket_;
}
- HANDLE as_handle() const
- {
- return reinterpret_cast<HANDLE>(socket_);
- }
-
bool have_remote_endpoint() const
{
return have_remote_endpoint_;
@@ -114,148 +105,44 @@ public:
};
// The implementation type of the socket.
- class implementation_type
+ struct implementation_type :
+ win_iocp_socket_service_base::base_implementation_type
{
- public:
// Default constructor.
implementation_type()
- : socket_(invalid_socket),
- flags_(0),
- cancel_token_(),
- protocol_(endpoint_type().protocol()),
- next_(0),
- prev_(0)
+ : protocol_(endpoint_type().protocol()),
+ have_remote_endpoint_(false),
+ remote_endpoint_()
{
}
- private:
- // Only this service will have access to the internal values.
- friend class win_iocp_socket_service;
-
- // The native socket representation.
- native_type socket_;
-
- enum
- {
- enable_connection_aborted = 1, // User wants connection_aborted errors.
- close_might_block = 2, // User set linger option for blocking close.
- user_set_non_blocking = 4 // The user wants a non-blocking socket.
- };
-
- // Flags indicating the current state of the socket.
- unsigned char flags_;
-
- // We use a shared pointer as a cancellation token here to work around the
- // broken Windows support for cancellation. MSDN says that when you call
- // closesocket any outstanding WSARecv or WSASend operations will complete
- // with the error ERROR_OPERATION_ABORTED. In practice they complete with
- // ERROR_NETNAME_DELETED, which means you can't tell the difference between
- // a local cancellation and the socket being hard-closed by the peer.
- shared_cancel_token_type cancel_token_;
-
// The protocol associated with the socket.
protocol_type protocol_;
- // Per-descriptor data used by the reactor.
- reactor::per_descriptor_data reactor_data_;
-
-#if defined(ASIO_ENABLE_CANCELIO)
- // The ID of the thread from which it is safe to cancel asynchronous
- // operations. 0 means no asynchronous operations have been started yet.
- // ~0 means asynchronous operations have been started from more than one
- // thread, and cancellation is not supported for the socket.
- DWORD safe_cancellation_thread_id_;
-#endif // defined(ASIO_ENABLE_CANCELIO)
+ // Whether we have a cached remote endpoint.
+ bool have_remote_endpoint_;
- // Pointers to adjacent socket implementations in linked list.
- implementation_type* next_;
- implementation_type* prev_;
+ // A cached remote endpoint.
+ endpoint_type remote_endpoint_;
};
// Constructor.
win_iocp_socket_service(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)
- {
- }
-
- // Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ : win_iocp_socket_service_base(io_service)
{
- // Close all implementations, causing all operations to complete.
- asio::detail::mutex::scoped_lock lock(mutex_);
- implementation_type* impl = impl_list_;
- while (impl)
- {
- asio::error_code ignored_ec;
- close_for_destruction(*impl);
- impl = impl->next_;
- }
- }
-
- // Construct a new socket implementation.
- void construct(implementation_type& impl)
- {
- impl.socket_ = invalid_socket;
- impl.flags_ = 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;
- }
-
- // Destroy a socket implementation.
- void destroy(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;
}
// Open a new socket implementation.
asio::error_code open(implementation_type& impl,
const protocol_type& protocol, asio::error_code& ec)
{
- if (is_open(impl))
+ if (!do_open(impl, protocol.family(),
+ protocol.type(), protocol.protocol(), ec))
{
- ec = asio::error::already_open;
- return ec;
+ impl.protocol_ = protocol;
+ impl.have_remote_endpoint_ = false;
+ impl.remote_endpoint_ = endpoint_type();
}
-
- socket_holder sock(socket_ops::socket(protocol.family(), protocol.type(),
- protocol.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();
- impl.flags_ = 0;
- impl.cancel_token_.reset(static_cast<void*>(0), noop_deleter());
- impl.protocol_ = protocol;
- ec = asio::error_code();
return ec;
}
@@ -264,247 +151,40 @@ public:
const protocol_type& protocol, const native_type& native_socket,
asio::error_code& ec)
{
- if (is_open(impl))
- {
- ec = asio::error::already_open;
- return ec;
- }
-
- if (iocp_service_.register_handle(native_socket.as_handle(), ec))
- return ec;
-
- impl.socket_ = native_socket;
- impl.flags_ = 0;
- impl.cancel_token_.reset(static_cast<void*>(0), noop_deleter());
- impl.protocol_ = protocol;
- ec = asio::error_code();
- return ec;
- }
-
- // Determine whether the socket is open.
- bool is_open(const implementation_type& impl) const
- {
- return impl.socket_ != invalid_socket;
- }
-
- // Destroy a socket implementation.
- asio::error_code close(implementation_type& impl,
- asio::error_code& ec)
- {
- if (is_open(impl))
+ if (!do_assign(impl, protocol.type(), native_socket, ec))
{
- // 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_, ec) == socket_error_retval)
- return ec;
-
- impl.socket_ = invalid_socket;
- impl.flags_ = 0;
- impl.cancel_token_.reset();
-#if defined(ASIO_ENABLE_CANCELIO)
- impl.safe_cancellation_thread_id_ = 0;
-#endif // defined(ASIO_ENABLE_CANCELIO)
+ impl.protocol_ = protocol;
+ impl.have_remote_endpoint_ = native_socket.have_remote_endpoint();
+ impl.remote_endpoint_ = native_socket.remote_endpoint();
}
-
- ec = asio::error_code();
return ec;
}
// Get the native socket representation.
native_type native(implementation_type& impl)
{
- return impl.socket_;
- }
-
- // Cancel all operations associated with the socket.
- asio::error_code cancel(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)
-
- return ec;
- }
-
- // Determine whether the socket is at the out-of-band data mark.
- bool at_mark(const implementation_type& impl,
- asio::error_code& ec) const
- {
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return false;
- }
-
- asio::detail::ioctl_arg_type value = 0;
- socket_ops::ioctl(impl.socket_, SIOCATMARK, &value, ec);
- return ec ? false : value != 0;
- }
-
- // Determine the number of bytes available for reading.
- std::size_t available(const implementation_type& impl,
- asio::error_code& ec) const
- {
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
- asio::detail::ioctl_arg_type value = 0;
- socket_ops::ioctl(impl.socket_, FIONREAD, &value, ec);
- return ec ? static_cast<std::size_t>(0) : static_cast<std::size_t>(value);
+ if (impl.have_remote_endpoint_)
+ return native_type(impl.socket_, impl.remote_endpoint_);
+ return native_type(impl.socket_);
}
// Bind the socket to the specified local endpoint.
asio::error_code bind(implementation_type& impl,
const endpoint_type& endpoint, asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return ec;
- }
-
socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
return ec;
}
- // Place the socket into the state where it will listen for new connections.
- asio::error_code listen(implementation_type& impl, int backlog,
- asio::error_code& ec)
- {
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return ec;
- }
-
- socket_ops::listen(impl.socket_, backlog, ec);
- return ec;
- }
-
// Set a socket option.
template <typename Option>
asio::error_code set_option(implementation_type& impl,
const Option& option, asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return ec;
- }
-
- if (option.level(impl.protocol_) == custom_socket_option_level
- && option.name(impl.protocol_) == enable_connection_aborted_option)
- {
- if (option.size(impl.protocol_) != sizeof(int))
- {
- ec = asio::error::invalid_argument;
- }
- else
- {
- if (*reinterpret_cast<const int*>(option.data(impl.protocol_)))
- impl.flags_ |= implementation_type::enable_connection_aborted;
- else
- impl.flags_ &= ~implementation_type::enable_connection_aborted;
- ec = asio::error_code();
- }
- return ec;
- }
- else
- {
- if (option.level(impl.protocol_) == SOL_SOCKET
- && option.name(impl.protocol_) == SO_LINGER)
- {
- const ::linger* linger_option =
- reinterpret_cast<const ::linger*>(option.data(impl.protocol_));
- if (linger_option->l_onoff != 0 && linger_option->l_linger != 0)
- impl.flags_ |= implementation_type::close_might_block;
- else
- impl.flags_ &= ~implementation_type::close_might_block;
- }
-
- socket_ops::setsockopt(impl.socket_,
- option.level(impl.protocol_), option.name(impl.protocol_),
- option.data(impl.protocol_), option.size(impl.protocol_), ec);
- return ec;
- }
+ socket_ops::setsockopt(impl.socket_, impl.state_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), option.size(impl.protocol_), ec);
+ return ec;
}
// Set a socket option.
@@ -512,65 +192,12 @@ public:
asio::error_code get_option(const implementation_type& impl,
Option& option, asio::error_code& ec) const
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return ec;
- }
-
- if (option.level(impl.protocol_) == custom_socket_option_level
- && option.name(impl.protocol_) == enable_connection_aborted_option)
- {
- if (option.size(impl.protocol_) != sizeof(int))
- {
- ec = asio::error::invalid_argument;
- }
- else
- {
- int* target = reinterpret_cast<int*>(option.data(impl.protocol_));
- if (impl.flags_ & implementation_type::enable_connection_aborted)
- *target = 1;
- else
- *target = 0;
- option.resize(impl.protocol_, sizeof(int));
- ec = asio::error_code();
- }
- return ec;
- }
- else
- {
- size_t size = option.size(impl.protocol_);
- socket_ops::getsockopt(impl.socket_,
- option.level(impl.protocol_), option.name(impl.protocol_),
- option.data(impl.protocol_), &size, ec);
- if (!ec)
- option.resize(impl.protocol_, size);
- return ec;
- }
- }
-
- // Perform an IO control command on the socket.
- template <typename IO_Control_Command>
- asio::error_code io_control(implementation_type& impl,
- IO_Control_Command& command, asio::error_code& ec)
- {
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return ec;
- }
-
- socket_ops::ioctl(impl.socket_, command.name(),
- static_cast<ioctl_arg_type*>(command.data()), ec);
-
- if (!ec && command.name() == static_cast<int>(FIONBIO))
- {
- if (*static_cast<ioctl_arg_type*>(command.data()))
- impl.flags_ |= implementation_type::user_set_non_blocking;
- else
- impl.flags_ &= ~implementation_type::user_set_non_blocking;
- }
-
+ std::size_t size = option.size(impl.protocol_);
+ socket_ops::getsockopt(impl.socket_, impl.state_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), &size, ec);
+ if (!ec)
+ option.resize(impl.protocol_, size);
return ec;
}
@@ -578,12 +205,6 @@ public:
endpoint_type local_endpoint(const implementation_type& impl,
asio::error_code& ec) const
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return endpoint_type();
- }
-
endpoint_type endpoint;
std::size_t addr_len = endpoint.capacity();
if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
@@ -596,210 +217,13 @@ public:
endpoint_type remote_endpoint(const implementation_type& impl,
asio::error_code& ec) const
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
+ endpoint_type endpoint = impl.remote_endpoint_;
+ std::size_t addr_len = endpoint.capacity();
+ if (socket_ops::getpeername(impl.socket_, endpoint.data(),
+ &addr_len, impl.have_remote_endpoint_, ec))
return endpoint_type();
- }
-
- if (impl.socket_.have_remote_endpoint())
- {
- // Check if socket is still connected.
- DWORD connect_time = 0;
- size_t connect_time_len = sizeof(connect_time);
- if (socket_ops::getsockopt(impl.socket_, SOL_SOCKET, SO_CONNECT_TIME,
- &connect_time, &connect_time_len, ec) == socket_error_retval)
- {
- return endpoint_type();
- }
- if (connect_time == 0xFFFFFFFF)
- {
- ec = asio::error::not_connected;
- return endpoint_type();
- }
-
- ec = asio::error_code();
- return impl.socket_.remote_endpoint();
- }
- else
- {
- endpoint_type endpoint;
- std::size_t addr_len = endpoint.capacity();
- if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec))
- return endpoint_type();
- endpoint.resize(addr_len);
- return endpoint;
- }
- }
-
- /// Disable sends or receives on the socket.
- asio::error_code shutdown(implementation_type& impl,
- socket_base::shutdown_type what, asio::error_code& ec)
- {
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return ec;
- }
-
- socket_ops::shutdown(impl.socket_, what, ec);
- return ec;
- }
-
- // Send the given data to the peer. Returns the number of bytes sent.
- template <typename ConstBufferSequence>
- size_t send(implementation_type& impl, const ConstBufferSequence& buffers,
- socket_base::message_flags flags, asio::error_code& ec)
- {
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
- buffer_sequence_adapter<asio::const_buffer,
- ConstBufferSequence> bufs(buffers);
-
- // A request to receive 0 bytes on a stream socket is a no-op.
- if (impl.protocol_.type() == SOCK_STREAM && bufs.all_empty())
- {
- ec = asio::error_code();
- return 0;
- }
-
- // Send the data.
- DWORD bytes_transferred = 0;
- int result = ::WSASend(impl.socket_, bufs.buffers(),
- bufs.count(), &bytes_transferred, flags, 0, 0);
- if (result != 0)
- {
- DWORD last_error = ::WSAGetLastError();
- if (last_error == ERROR_NETNAME_DELETED)
- last_error = WSAECONNRESET;
- else if (last_error == ERROR_PORT_UNREACHABLE)
- last_error = WSAECONNREFUSED;
- ec = asio::error_code(last_error,
- asio::error::get_system_category());
- return 0;
- }
-
- ec = asio::error_code();
- return bytes_transferred;
- }
-
- // Wait until data can be sent without blocking.
- size_t send(implementation_type& impl, const null_buffers&,
- socket_base::message_flags, asio::error_code& ec)
- {
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
- // Wait for socket to become ready.
- socket_ops::poll_write(impl.socket_, ec);
-
- return 0;
- }
-
- template <typename ConstBufferSequence, typename Handler>
- class send_op : public operation
- {
- public:
- send_op(weak_cancel_token_type cancel_token,
- const ConstBufferSequence& buffers, Handler handler)
- : operation(&send_op::do_complete),
- cancel_token_(cancel_token),
- buffers_(buffers),
- 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 operation object.
- send_op* o(static_cast<send_op*>(base));
- typedef handler_alloc_traits<Handler, send_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- // Make the upcall if required.
- if (owner)
- {
-#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
- // Check whether buffers are still valid.
- buffer_sequence_adapter<asio::const_buffer,
- ConstBufferSequence>::validate(o->buffers_);
-#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-
- // Map non-portable errors to their portable counterparts.
- if (ec.value() == ERROR_NETNAME_DELETED)
- {
- if (o->cancel_token_.expired())
- ec = asio::error::operation_aborted;
- else
- ec = asio::error::connection_reset;
- }
- else if (ec.value() == ERROR_PORT_UNREACHABLE)
- {
- ec = asio::error::connection_refused;
- }
-
- // 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_, ec, bytes_transferred);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
- }
-
- private:
- weak_cancel_token_type cancel_token_;
- ConstBufferSequence buffers_;
- Handler handler_;
- };
-
- // Start an asynchronous send. The data being sent must be valid for the
- // lifetime of the asynchronous operation.
- template <typename ConstBufferSequence, typename Handler>
- void async_send(implementation_type& impl, const ConstBufferSequence& buffers,
- socket_base::message_flags flags, Handler handler)
- {
- // Allocate and construct an operation to wrap the handler.
- typedef send_op<ConstBufferSequence, 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,
- impl.cancel_token_, buffers, handler);
-
- buffer_sequence_adapter<asio::const_buffer,
- ConstBufferSequence> bufs(buffers);
-
- start_send_op(impl, bufs.buffers(), bufs.count(), flags,
- impl.protocol_.type() == SOCK_STREAM && bufs.all_empty(), ptr.get());
- ptr.release();
- }
-
- // Start an asynchronous wait until data can be sent without blocking.
- template <typename Handler>
- void async_send(implementation_type& impl, const null_buffers&,
- socket_base::message_flags, Handler handler)
- {
- // Allocate and construct an operation to wrap the handler.
- typedef null_buffers_op<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);
-
- start_reactor_op(impl, reactor::write_op, ptr.get());
- ptr.release();
+ endpoint.resize(addr_len);
+ return endpoint;
}
// Send a datagram to the specified endpoint. Returns the number of bytes
@@ -809,107 +233,25 @@ public:
const endpoint_type& destination, socket_base::message_flags flags,
asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
buffer_sequence_adapter<asio::const_buffer,
ConstBufferSequence> bufs(buffers);
- // Send the data.
- DWORD bytes_transferred = 0;
- int result = ::WSASendTo(impl.socket_, bufs.buffers(), bufs.count(),
- &bytes_transferred, flags, destination.data(),
- static_cast<int>(destination.size()), 0, 0);
- if (result != 0)
- {
- DWORD last_error = ::WSAGetLastError();
- if (last_error == ERROR_PORT_UNREACHABLE)
- last_error = WSAECONNREFUSED;
- ec = asio::error_code(last_error,
- asio::error::get_system_category());
- return 0;
- }
-
- ec = asio::error_code();
- return bytes_transferred;
+ return socket_ops::sync_sendto(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags,
+ destination.data(), destination.size(), ec);
}
// Wait until data can be sent without blocking.
size_t send_to(implementation_type& impl, const null_buffers&,
- socket_base::message_flags, const endpoint_type&,
+ const endpoint_type&, socket_base::message_flags,
asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
// Wait for socket to become ready.
socket_ops::poll_write(impl.socket_, ec);
return 0;
}
- template <typename ConstBufferSequence, typename Handler>
- class send_to_op : public operation
- {
- public:
- send_to_op(weak_cancel_token_type cancel_token,
- const ConstBufferSequence& buffers, Handler handler)
- : operation(&send_to_op::do_complete),
- cancel_token_(cancel_token),
- buffers_(buffers),
- 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 operation object.
- send_to_op* o(static_cast<send_to_op*>(base));
- typedef handler_alloc_traits<Handler, send_to_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- // Make the upcall if required.
- if (owner)
- {
-#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
- // Check whether buffers are still valid.
- buffer_sequence_adapter<asio::const_buffer,
- ConstBufferSequence>::validate(o->buffers_);
-#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-
- // Map non-portable errors to their portable counterparts.
- if (ec.value() == ERROR_PORT_UNREACHABLE)
- {
- ec = asio::error::connection_refused;
- }
-
- // 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_, ec, bytes_transferred);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
- }
-
- private:
- weak_cancel_token_type cancel_token_;
- ConstBufferSequence buffers_;
- Handler handler_;
- };
-
// Start an asynchronous send. The data being sent must be valid for the
// lifetime of the asynchronous operation.
template <typename ConstBufferSequence, typename Handler>
@@ -918,233 +260,35 @@ public:
socket_base::message_flags flags, Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef send_to_op<ConstBufferSequence, 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,
- impl.cancel_token_, buffers, handler);
+ typedef win_iocp_socket_send_op<ConstBufferSequence, Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.cancel_token_, buffers, handler);
buffer_sequence_adapter<asio::const_buffer,
ConstBufferSequence> bufs(buffers);
- start_send_to_op(impl, bufs.buffers(),
- bufs.count(), destination, flags, ptr.get());
- ptr.release();
+ start_send_to_op(impl, bufs.buffers(), bufs.count(),
+ destination.data(), static_cast<int>(destination.size()),
+ flags, p.p);
+ p.v = p.p = 0;
}
// Start an asynchronous wait until data can be sent without blocking.
template <typename Handler>
void async_send_to(implementation_type& impl, const null_buffers&,
- socket_base::message_flags, const endpoint_type&, Handler handler)
- {
- // Allocate and construct an operation to wrap the handler.
- typedef null_buffers_op<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);
-
- start_reactor_op(impl, reactor::write_op, ptr.get());
- ptr.release();
- }
-
- // Receive some data from the peer. Returns the number of bytes received.
- template <typename MutableBufferSequence>
- size_t receive(implementation_type& impl,
- const MutableBufferSequence& buffers,
- socket_base::message_flags flags, asio::error_code& ec)
- {
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
- buffer_sequence_adapter<asio::mutable_buffer,
- MutableBufferSequence> bufs(buffers);
-
- // A request to receive 0 bytes on a stream socket is a no-op.
- if (impl.protocol_.type() == SOCK_STREAM && bufs.all_empty())
- {
- ec = asio::error_code();
- return 0;
- }
-
- // Receive some data.
- DWORD bytes_transferred = 0;
- DWORD recv_flags = flags;
- int result = ::WSARecv(impl.socket_, bufs.buffers(),
- bufs.count(), &bytes_transferred, &recv_flags, 0, 0);
- if (result != 0)
- {
- DWORD last_error = ::WSAGetLastError();
- if (last_error == ERROR_NETNAME_DELETED)
- last_error = WSAECONNRESET;
- else if (last_error == ERROR_PORT_UNREACHABLE)
- last_error = WSAECONNREFUSED;
- ec = asio::error_code(last_error,
- asio::error::get_system_category());
- return 0;
- }
- if (bytes_transferred == 0 && impl.protocol_.type() == SOCK_STREAM)
- {
- ec = asio::error::eof;
- return 0;
- }
-
- ec = asio::error_code();
- return bytes_transferred;
- }
-
- // Wait until data can be received without blocking.
- size_t receive(implementation_type& impl, const null_buffers&,
- socket_base::message_flags, asio::error_code& ec)
- {
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
- // Wait for socket to become ready.
- socket_ops::poll_read(impl.socket_, ec);
-
- return 0;
- }
-
- template <typename MutableBufferSequence, typename Handler>
- class receive_op : public operation
- {
- public:
- receive_op(int protocol_type, weak_cancel_token_type cancel_token,
- const MutableBufferSequence& buffers, Handler handler)
- : operation(&receive_op::do_complete),
- protocol_type_(protocol_type),
- cancel_token_(cancel_token),
- buffers_(buffers),
- 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 operation object.
- receive_op* o(static_cast<receive_op*>(base));
- typedef handler_alloc_traits<Handler, receive_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- // Make the upcall if required.
- if (owner)
- {
-#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
- // Check whether buffers are still valid.
- buffer_sequence_adapter<asio::mutable_buffer,
- MutableBufferSequence>::validate(o->buffers_);
-#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-
- // Map non-portable errors to their portable counterparts.
- if (ec.value() == ERROR_NETNAME_DELETED)
- {
- if (o->cancel_token_.expired())
- ec = asio::error::operation_aborted;
- else
- ec = asio::error::connection_reset;
- }
- else if (ec.value() == ERROR_PORT_UNREACHABLE)
- {
- ec = asio::error::connection_refused;
- }
-
- // Check for connection closed.
- else if (!ec && bytes_transferred == 0
- && o->protocol_type_ == SOCK_STREAM
- && !buffer_sequence_adapter<asio::mutable_buffer,
- MutableBufferSequence>::all_empty(o->buffers_)
- && !boost::is_same<MutableBufferSequence, null_buffers>::value)
- {
- ec = asio::error::eof;
- }
-
- // 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_, ec, bytes_transferred);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
- }
-
- private:
- int protocol_type_;
- weak_cancel_token_type cancel_token_;
- MutableBufferSequence buffers_;
- Handler handler_;
- };
-
- // Start an asynchronous receive. The buffer for the data being received
- // must be valid for the lifetime of the asynchronous operation.
- template <typename MutableBufferSequence, typename Handler>
- void async_receive(implementation_type& impl,
- const MutableBufferSequence& buffers,
- socket_base::message_flags flags, Handler handler)
+ const endpoint_type&, socket_base::message_flags, Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef receive_op<MutableBufferSequence, Handler> value_type;
- typedef handler_alloc_traits<Handler, value_type> alloc_traits;
- raw_handler_ptr<alloc_traits> raw_ptr(handler);
- int protocol_type = impl.protocol_.type();
- handler_ptr<alloc_traits> ptr(raw_ptr, protocol_type,
- impl.cancel_token_, buffers, handler);
-
- buffer_sequence_adapter<asio::mutable_buffer,
- MutableBufferSequence> bufs(buffers);
+ typedef win_iocp_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.cancel_token_, handler);
- start_receive_op(impl, bufs.buffers(), bufs.count(), flags,
- protocol_type == SOCK_STREAM && bufs.all_empty(), ptr.get());
- ptr.release();
- }
-
- // Wait until data can be received without blocking.
- template <typename Handler>
- void async_receive(implementation_type& impl, const null_buffers& buffers,
- socket_base::message_flags flags, Handler handler)
- {
- if (impl.protocol_.type() == SOCK_STREAM)
- {
- // For stream sockets on Windows, we may issue a 0-byte overlapped
- // WSARecv to wait until there is data available on the socket.
-
- // Allocate and construct an operation to wrap the handler.
- typedef receive_op<null_buffers, Handler> value_type;
- typedef handler_alloc_traits<Handler, value_type> alloc_traits;
- raw_handler_ptr<alloc_traits> raw_ptr(handler);
- int protocol_type = impl.protocol_.type();
- handler_ptr<alloc_traits> ptr(raw_ptr, protocol_type,
- impl.cancel_token_, buffers, handler);
-
- ::WSABUF buf = { 0, 0 };
- start_receive_op(impl, &buf, 1, flags, false, ptr.get());
- ptr.release();
- }
- else
- {
- // Allocate and construct an operation to wrap the handler.
- typedef null_buffers_op<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);
-
- start_reactor_op(impl,
- (flags & socket_base::message_out_of_band)
- ? reactor::except_op : reactor::read_op,
- ptr.get());
- ptr.release();
- }
+ start_reactor_op(impl, reactor::write_op, p.p);
+ p.v = p.p = 0;
}
// Receive a datagram with the endpoint of the sender. Returns the number of
@@ -1155,41 +299,18 @@ public:
endpoint_type& sender_endpoint, socket_base::message_flags flags,
asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
buffer_sequence_adapter<asio::mutable_buffer,
MutableBufferSequence> bufs(buffers);
- // Receive some data.
- DWORD bytes_transferred = 0;
- DWORD recv_flags = flags;
- int endpoint_size = static_cast<int>(sender_endpoint.capacity());
- int result = ::WSARecvFrom(impl.socket_, bufs.buffers(),
- bufs.count(), &bytes_transferred, &recv_flags,
- sender_endpoint.data(), &endpoint_size, 0, 0);
- if (result != 0)
- {
- DWORD last_error = ::WSAGetLastError();
- if (last_error == ERROR_PORT_UNREACHABLE)
- last_error = WSAECONNREFUSED;
- ec = asio::error_code(last_error,
- asio::error::get_system_category());
- return 0;
- }
- if (bytes_transferred == 0 && impl.protocol_.type() == SOCK_STREAM)
- {
- ec = asio::error::eof;
- return 0;
- }
+ std::size_t addr_len = sender_endpoint.capacity();
+ std::size_t bytes_recvd = socket_ops::sync_recvfrom(
+ impl.socket_, impl.state_, bufs.buffers(), bufs.count(),
+ flags, sender_endpoint.data(), &addr_len, ec);
- sender_endpoint.resize(static_cast<std::size_t>(endpoint_size));
+ if (!ec)
+ sender_endpoint.resize(addr_len);
- ec = asio::error_code();
- return bytes_transferred;
+ return bytes_recvd;
}
// Wait until data can be received without blocking.
@@ -1197,12 +318,6 @@ public:
const null_buffers&, endpoint_type& sender_endpoint,
socket_base::message_flags, asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return 0;
- }
-
// Wait for socket to become ready.
socket_ops::poll_read(impl.socket_, ec);
@@ -1212,75 +327,6 @@ public:
return 0;
}
- template <typename MutableBufferSequence, typename Handler>
- class receive_from_op : public operation
- {
- public:
- receive_from_op(int protocol_type, endpoint_type& endpoint,
- const MutableBufferSequence& buffers, Handler handler)
- : operation(&receive_from_op::do_complete),
- protocol_type_(protocol_type),
- endpoint_(endpoint),
- endpoint_size_(static_cast<int>(endpoint.capacity())),
- buffers_(buffers),
- handler_(handler)
- {
- }
-
- int& endpoint_size()
- {
- return endpoint_size_;
- }
-
- static void do_complete(io_service_impl* owner, operation* base,
- asio::error_code ec, std::size_t bytes_transferred)
- {
- // Take ownership of the operation object.
- receive_from_op* o(static_cast<receive_from_op*>(base));
- typedef handler_alloc_traits<Handler, receive_from_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- // Make the upcall if required.
- if (owner)
- {
-#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)
- // Check whether buffers are still valid.
- buffer_sequence_adapter<asio::mutable_buffer,
- MutableBufferSequence>::validate(o->buffers_);
-#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)
-
- // Map non-portable errors to their portable counterparts.
- if (ec.value() == ERROR_PORT_UNREACHABLE)
- {
- ec = asio::error::connection_refused;
- }
-
- // Record the size of the endpoint returned by the operation.
- o->endpoint_.resize(o->endpoint_size_);
-
- // 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_, ec, bytes_transferred);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
- }
-
- private:
- int protocol_type_;
- endpoint_type& endpoint_;
- int endpoint_size_;
- weak_cancel_token_type cancel_token_;
- MutableBufferSequence buffers_;
- Handler handler_;
- };
-
// Start an asynchronous receive. The buffer for the data being received and
// the sender_endpoint object must both be valid for the lifetime of the
// asynchronous operation.
@@ -1290,19 +336,19 @@ public:
socket_base::message_flags flags, Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef receive_from_op<MutableBufferSequence, Handler> value_type;
- typedef handler_alloc_traits<Handler, value_type> alloc_traits;
- raw_handler_ptr<alloc_traits> raw_ptr(handler);
- int protocol_type = impl.protocol_.type();
- handler_ptr<alloc_traits> ptr(raw_ptr,
- protocol_type, sender_endp, buffers, handler);
+ typedef win_iocp_socket_recvfrom_op<
+ MutableBufferSequence, endpoint_type, Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(sender_endp, impl.cancel_token_, buffers, handler);
buffer_sequence_adapter<asio::mutable_buffer,
MutableBufferSequence> bufs(buffers);
start_receive_from_op(impl, bufs.buffers(), bufs.count(),
- sender_endp, flags, &ptr.get()->endpoint_size(), ptr.get());
- ptr.release();
+ sender_endp.data(), flags, &p.p->endpoint_size(), p.p);
+ p.v = p.p = 0;
}
// Wait until data can be received without blocking.
@@ -1312,19 +358,17 @@ public:
socket_base::message_flags flags, Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef null_buffers_op<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 win_iocp_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.cancel_token_, handler);
// Reset endpoint since it can be given no sensible value at this time.
sender_endpoint = endpoint_type();
- start_reactor_op(impl,
- (flags & socket_base::message_out_of_band)
- ? reactor::except_op : reactor::read_op,
- ptr.get());
- ptr.release();
+ start_null_buffers_receive_op(impl, flags, p.p);
+ p.v = p.p = 0;
}
// Accept a new connection.
@@ -1332,12 +376,6 @@ public:
asio::error_code accept(implementation_type& impl, Socket& peer,
endpoint_type* peer_endpoint, asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return ec;
- }
-
// We cannot accept a socket that is already open.
if (peer.is_open())
{
@@ -1345,222 +383,22 @@ public:
return ec;
}
- for (;;)
- {
- socket_holder new_socket;
- std::size_t addr_len = 0;
- if (peer_endpoint)
- {
- addr_len = peer_endpoint->capacity();
- new_socket.reset(socket_ops::accept(impl.socket_,
- peer_endpoint->data(), &addr_len, ec));
- }
- else
- {
- new_socket.reset(socket_ops::accept(impl.socket_, 0, 0, ec));
- }
-
- if (ec)
- {
- if (ec == asio::error::connection_aborted
- && !(impl.flags_ & implementation_type::enable_connection_aborted))
- {
- // Retry accept operation.
- continue;
- }
- else
- {
- return ec;
- }
- }
+ std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;
+ socket_holder new_socket(socket_ops::sync_accept(impl.socket_,
+ impl.state_, peer_endpoint ? peer_endpoint->data() : 0,
+ peer_endpoint ? &addr_len : 0, ec));
+ // On success, assign new connection to peer socket object.
+ if (new_socket.get() >= 0)
+ {
if (peer_endpoint)
peer_endpoint->resize(addr_len);
-
- peer.assign(impl.protocol_, new_socket.get(), ec);
- if (!ec)
+ if (!peer.assign(impl.protocol_, new_socket.get(), ec))
new_socket.release();
- return ec;
- }
- }
-
- template <typename Socket, typename Handler>
- class accept_op : public operation
- {
- public:
- accept_op(win_iocp_io_service& iocp_service, socket_type socket,
- Socket& peer, const protocol_type& protocol,
- endpoint_type* peer_endpoint, bool enable_connection_aborted,
- Handler handler)
- : operation(&accept_op::do_complete),
- iocp_service_(iocp_service),
- socket_(socket),
- peer_(peer),
- protocol_(protocol),
- peer_endpoint_(peer_endpoint),
- enable_connection_aborted_(enable_connection_aborted),
- handler_(handler)
- {
}
- socket_holder& new_socket()
- {
- return new_socket_;
- }
-
- void* output_buffer()
- {
- return output_buffer_;
- }
-
- DWORD address_length()
- {
- return sizeof(sockaddr_storage_type) + 16;
- }
-
- 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.
- accept_op* o(static_cast<accept_op*>(base));
- typedef handler_alloc_traits<Handler, accept_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- // Make the upcall if required.
- if (owner)
- {
- // Map Windows error ERROR_NETNAME_DELETED to connection_aborted.
- if (ec.value() == ERROR_NETNAME_DELETED)
- {
- ec = asio::error::connection_aborted;
- }
-
- // Restart the accept operation if we got the connection_aborted error
- // and the enable_connection_aborted socket option is not set.
- if (ec == asio::error::connection_aborted
- && !o->enable_connection_aborted_)
- {
- // Reset OVERLAPPED structure.
- o->reset();
-
- // Create a new socket for the next connection, since the AcceptEx
- // call fails with WSAEINVAL if we try to reuse the same socket.
- o->new_socket_.reset();
- o->new_socket_.reset(socket_ops::socket(o->protocol_.family(),
- o->protocol_.type(), o->protocol_.protocol(), ec));
- if (o->new_socket_.get() != invalid_socket)
- {
- // Accept a connection.
- DWORD bytes_read = 0;
- BOOL result = ::AcceptEx(o->socket_, o->new_socket_.get(),
- o->output_buffer(), 0, o->address_length(),
- o->address_length(), &bytes_read, o);
- DWORD last_error = ::WSAGetLastError();
- ec = asio::error_code(last_error,
- asio::error::get_system_category());
-
- // Check if the operation completed immediately.
- if (!result && last_error != WSA_IO_PENDING)
- {
- if (last_error == ERROR_NETNAME_DELETED
- || last_error == WSAECONNABORTED)
- {
- // Post this handler so that operation will be restarted again.
- o->iocp_service_.work_started();
- o->iocp_service_.on_completion(o, ec);
- ptr.release();
- return;
- }
- else
- {
- // Operation already complete. Continue with rest of this
- // handler.
- }
- }
- else
- {
- // Asynchronous operation has been successfully restarted.
- o->iocp_service_.work_started();
- o->iocp_service_.on_pending(o);
- ptr.release();
- return;
- }
- }
- }
-
- // Get the address of the peer.
- endpoint_type peer_endpoint;
- if (!ec)
- {
- LPSOCKADDR local_addr = 0;
- int local_addr_length = 0;
- LPSOCKADDR remote_addr = 0;
- int remote_addr_length = 0;
- GetAcceptExSockaddrs(o->output_buffer(), 0, o->address_length(),
- o->address_length(), &local_addr, &local_addr_length,
- &remote_addr, &remote_addr_length);
- if (static_cast<std::size_t>(remote_addr_length)
- > peer_endpoint.capacity())
- {
- ec = asio::error::invalid_argument;
- }
- else
- {
- using namespace std; // For memcpy.
- memcpy(peer_endpoint.data(), remote_addr, remote_addr_length);
- peer_endpoint.resize(static_cast<std::size_t>(remote_addr_length));
- }
- }
-
- // Need to set the SO_UPDATE_ACCEPT_CONTEXT option so that getsockname
- // and getpeername will work on the accepted socket.
- if (!ec)
- {
- SOCKET update_ctx_param = o->socket_;
- socket_ops::setsockopt(o->new_socket_.get(),
- SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
- &update_ctx_param, sizeof(SOCKET), ec);
- }
-
- // If the socket was successfully accepted, transfer ownership of the
- // socket to the peer object.
- if (!ec)
- {
- o->peer_.assign(o->protocol_,
- native_type(o->new_socket_.get(), peer_endpoint), ec);
- if (!ec)
- o->new_socket_.release();
- }
-
- // Pass endpoint back to caller.
- if (o->peer_endpoint_)
- *o->peer_endpoint_ = peer_endpoint;
-
- // 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(o->handler_, ec);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
- }
-
- private:
- win_iocp_io_service& iocp_service_;
- socket_type socket_;
- socket_holder new_socket_;
- Socket& peer_;
- protocol_type protocol_;
- endpoint_type* peer_endpoint_;
- unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];
- bool enable_connection_aborted_;
- Handler handler_;
- };
+ return ec;
+ }
// Start an asynchronous accept. The peer and peer_endpoint objects
// must be valid until the accept's handler is invoked.
@@ -1569,442 +407,54 @@ public:
endpoint_type* peer_endpoint, Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef accept_op<Socket, Handler> value_type;
- typedef handler_alloc_traits<Handler, value_type> alloc_traits;
- raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ typedef win_iocp_socket_accept_op<Socket, protocol_type, Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
bool enable_connection_aborted =
- (impl.flags_ & implementation_type::enable_connection_aborted);
- handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, impl.socket_, peer,
- impl.protocol_, peer_endpoint, enable_connection_aborted, handler);
+ (impl.state_ & socket_ops::enable_connection_aborted) != 0;
+ p.p = new (p.v) op(*this, impl.socket_, peer, impl.protocol_,
+ peer_endpoint, enable_connection_aborted, handler);
- start_accept_op(impl, peer.is_open(), ptr.get()->new_socket(),
- ptr.get()->output_buffer(), ptr.get()->address_length(), ptr.get());
- ptr.release();
+ start_accept_op(impl, peer.is_open(), p.p->new_socket(),
+ impl.protocol_.family(), impl.protocol_.type(),
+ impl.protocol_.protocol(), p.p->output_buffer(),
+ p.p->address_length(), p.p);
+ p.v = p.p = 0;
}
// Connect the socket to the specified endpoint.
asio::error_code connect(implementation_type& impl,
const endpoint_type& peer_endpoint, asio::error_code& ec)
{
- if (!is_open(impl))
- {
- ec = asio::error::bad_descriptor;
- return ec;
- }
-
- // Perform the connect operation.
- socket_ops::connect(impl.socket_,
+ socket_ops::sync_connect(impl.socket_,
peer_endpoint.data(), peer_endpoint.size(), ec);
return ec;
}
- class connect_op_base : public reactor_op
- {
- public:
- connect_op_base(socket_type socket, func_type complete_func)
- : reactor_op(&connect_op_base::do_perform, complete_func),
- socket_(socket)
- {
- }
-
- static bool do_perform(reactor_op* base)
- {
- connect_op_base* o(static_cast<connect_op_base*>(base));
-
- // Get the error code from the connect operation.
- int connect_error = 0;
- size_t connect_error_len = sizeof(connect_error);
- if (socket_ops::getsockopt(o->socket_, SOL_SOCKET, SO_ERROR,
- &connect_error, &connect_error_len, o->ec_) == socket_error_retval)
- return true;
-
- // The connection failed so the handler will be posted with an error code.
- if (connect_error)
- {
- o->ec_ = asio::error_code(connect_error,
- asio::error::get_system_category());
- }
-
- return true;
- }
-
- private:
- socket_type socket_;
- };
-
- template <typename Handler>
- class connect_op : public connect_op_base
- {
- public:
- connect_op(socket_type socket, Handler handler)
- : connect_op_base(socket, &connect_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.
- connect_op* o(static_cast<connect_op*>(base));
- typedef handler_alloc_traits<Handler, connect_op> alloc_traits;
- handler_ptr<alloc_traits> ptr(o->handler_, o);
-
- // 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(o->handler_, o->ec_);
- ptr.reset();
- asio::detail::fenced_block b;
- asio_handler_invoke_helpers::invoke(handler, handler);
- }
- }
-
- private:
- Handler handler_;
- };
-
// Start an asynchronous connect.
template <typename Handler>
void async_connect(implementation_type& impl,
const endpoint_type& peer_endpoint, Handler handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef connect_op<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, impl.socket_, handler);
-
- start_connect_op(impl, ptr.get(), peer_endpoint);
- ptr.release();
- }
-
-private:
- // Helper function to start an asynchronous send operation.
- void start_send_op(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,
- 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);
- }
- }
-
- // Helper function to start an asynchronous send_to operation.
- void start_send_to_op(implementation_type& impl, WSABUF* buffers,
- std::size_t buffer_count, const endpoint_type& destination,
- socket_base::message_flags flags, operation* op)
- {
- update_cancellation_thread_id(impl);
- iocp_service_.work_started();
+ typedef reactive_socket_connect_op<Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.socket_, handler);
- if (!is_open(impl))
- iocp_service_.on_completion(op, asio::error::bad_descriptor);
- else
- {
- DWORD bytes_transferred = 0;
- int result = ::WSASendTo(impl.socket_, buffers, buffer_count,
- &bytes_transferred, flags, destination.data(),
- static_cast<int>(destination.size()), 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);
- }
+ start_connect_op(impl, p.p, peer_endpoint.data(),
+ static_cast<int>(peer_endpoint.size()));
+ p.v = p.p = 0;
}
-
- // Helper function to start an asynchronous receive operation.
- void start_receive_op(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, 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);
- }
- }
-
- // Helper function to start an asynchronous receive_from operation.
- void start_receive_from_op(implementation_type& impl, WSABUF* buffers,
- std::size_t buffer_count, endpoint_type& sender_endpoint,
- socket_base::message_flags flags, int* endpoint_size, 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,
- buffer_count, &bytes_transferred, &recv_flags,
- sender_endpoint.data(), endpoint_size, 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);
- }
- }
-
- // Helper function to start an asynchronous receive_from operation.
- void start_accept_op(implementation_type& impl,
- bool peer_is_open, socket_holder& new_socket,
- 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(impl.protocol_.family(),
- impl.protocol_.type(), impl.protocol_.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);
- }
- }
- }
-
- // Start an asynchronous read or write operation using the the reactor.
- void start_reactor_op(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);
- }
-
- // Start the asynchronous connect operation using the reactor.
- void start_connect_op(implementation_type& impl,
- reactor_op* op, const endpoint_type& peer_endpoint)
- {
- reactor& r = get_reactor();
- update_cancellation_thread_id(impl);
-
- if (is_open(impl))
- {
- ioctl_arg_type non_blocking = 1;
- if (!socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, op->ec_))
- {
- if (socket_ops::connect(impl.socket_, peer_endpoint.data(),
- peer_endpoint.size(), op->ec_) != 0)
- {
- if (!op->ec_
- && !(impl.flags_ & implementation_type::user_set_non_blocking))
- {
- non_blocking = 0;
- socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, op->ec_);
- }
-
- 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, true);
- return;
- }
- }
- }
- }
- else
- op->ec_ = asio::error::bad_descriptor;
-
- iocp_service_.post_immediate_completion(op);
- }
-
- // Helper function to close a socket when the associated object is being
- // destroyed.
- void close_for_destruction(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_);
-
- // The socket destructor must not block. If the user has changed the
- // linger option to block in the foreground, we will change it back to the
- // default so that the closure is performed in the background.
- if (impl.flags_ & implementation_type::close_might_block)
- {
- ::linger opt;
- opt.l_onoff = 0;
- opt.l_linger = 0;
- asio::error_code ignored_ec;
- socket_ops::setsockopt(impl.socket_,
- SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec);
- }
-
- asio::error_code ignored_ec;
- socket_ops::close(impl.socket_, ignored_ec);
- impl.socket_ = invalid_socket;
- impl.flags_ = 0;
- impl.cancel_token_.reset();
-#if defined(ASIO_ENABLE_CANCELIO)
- impl.safe_cancellation_thread_id_ = 0;
-#endif // defined(ASIO_ENABLE_CANCELIO)
- }
- }
-
- // Update the ID of the thread from which cancellation is safe.
- void update_cancellation_thread_id(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)
- }
-
- // Helper function to get the reactor. If no reactor has been created yet, a
- // new one is obtained from the io_service and a pointer to it is cached in
- // this service.
- reactor& 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;
- }
-
- // Helper function to emulate InterlockedCompareExchangePointer functionality
- // for:
- // - very old Platform SDKs; and
- // - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
- void* 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
- }
-
- // Helper function to emulate InterlockedExchangePointer functionality for:
- // - very old Platform SDKs; and
- // - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
- void* 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
- }
-
- // The io_service used to obtain the reactor, if required.
- asio::io_service& io_service_;
-
- // The IOCP service used for running asynchronous operations and dispatching
- // handlers.
- win_iocp_io_service& iocp_service_;
-
- // The reactor used for performing connect operations. This object is created
- // only if needed.
- reactor* reactor_;
-
- // Mutex to protect access to the linked list of implementations.
- asio::detail::mutex mutex_;
-
- // The head of a linked list of all implementations.
- implementation_type* impl_list_;
};
} // namespace detail
} // namespace asio
-#endif // defined(ASIO_HAS_IOCP)
-
#include "asio/detail/pop_options.hpp"
+#endif // defined(ASIO_HAS_IOCP)
+
#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP
diff --git a/ext/asio/asio/detail/win_iocp_socket_service_base.hpp b/ext/asio/asio/detail/win_iocp_socket_service_base.hpp
new file mode 100644
index 0000000000..62010b3d14
--- /dev/null
+++ b/ext/asio/asio/detail/win_iocp_socket_service_base.hpp
@@ -0,0 +1,385 @@
+//
+// detail/win_iocp_socket_service_base.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_WIN_IOCP_SOCKET_SERVICE_BASE_HPP
+#define ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_BASE_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 <boost/type_traits/is_same.hpp>
+#include <boost/utility/addressof.hpp>
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
+#include "asio/socket_base.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/buffer_sequence_adapter.hpp"
+#include "asio/detail/fenced_block.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/mutex.hpp"
+#include "asio/detail/operation.hpp"
+#include "asio/detail/reactor.hpp"
+#include "asio/detail/reactor_op.hpp"
+#include "asio/detail/socket_holder.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/socket_types.hpp"
+#include "asio/detail/win_iocp_io_service.hpp"
+#include "asio/detail/win_iocp_null_buffers_op.hpp"
+#include "asio/detail/win_iocp_socket_send_op.hpp"
+#include "asio/detail/win_iocp_socket_recv_op.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace detail {
+
+class win_iocp_socket_service_base
+{
+public:
+ // The implementation type of the socket.
+ struct base_implementation_type
+ {
+ // The native socket representation.
+ socket_type socket_;
+
+ // The current state of the socket.
+ socket_ops::state_type state_;
+
+ // We use a shared pointer as a cancellation token here to work around the
+ // broken Windows support for cancellation. MSDN says that when you call
+ // closesocket any outstanding WSARecv or WSASend operations will complete
+ // with the error ERROR_OPERATION_ABORTED. In practice they complete with
+ // ERROR_NETNAME_DELETED, which means you can't tell the difference between
+ // a local cancellation and the socket being hard-closed by the peer.
+ socket_ops::shared_cancel_token_type cancel_token_;
+
+ // Per-descriptor data used by the reactor.
+ reactor::per_descriptor_data reactor_data_;
+
+#if defined(ASIO_ENABLE_CANCELIO)
+ // The ID of the thread from which it is safe to cancel asynchronous
+ // operations. 0 means no asynchronous operations have been started yet.
+ // ~0 means asynchronous operations have been started from more than one
+ // thread, and cancellation is not supported for the socket.
+ DWORD safe_cancellation_thread_id_;
+#endif // defined(ASIO_ENABLE_CANCELIO)
+
+ // Pointers to adjacent socket implementations in linked list.
+ base_implementation_type* next_;
+ base_implementation_type* prev_;
+ };
+
+ // Constructor.
+ ASIO_DECL win_iocp_socket_service_base(
+ asio::io_service& io_service);
+
+ // Destroy all user-defined handler objects owned by the service.
+ ASIO_DECL void shutdown_service();
+
+ // Construct a new socket implementation.
+ ASIO_DECL void construct(base_implementation_type& impl);
+
+ // Destroy a socket implementation.
+ ASIO_DECL void destroy(base_implementation_type& impl);
+
+ // Determine whether the socket is open.
+ bool is_open(const base_implementation_type& impl) const
+ {
+ return impl.socket_ != invalid_socket;
+ }
+
+ // Destroy a socket implementation.
+ ASIO_DECL asio::error_code close(
+ base_implementation_type& impl, asio::error_code& ec);
+
+ // Cancel all operations associated with the socket.
+ ASIO_DECL asio::error_code cancel(
+ base_implementation_type& impl, asio::error_code& ec);
+
+ // Determine whether the socket is at the out-of-band data mark.
+ bool at_mark(const base_implementation_type& impl,
+ asio::error_code& ec) const
+ {
+ return socket_ops::sockatmark(impl.socket_, ec);
+ }
+
+ // Determine the number of bytes available for reading.
+ std::size_t available(const base_implementation_type& impl,
+ asio::error_code& ec) const
+ {
+ return socket_ops::available(impl.socket_, ec);
+ }
+
+ // Place the socket into the state where it will listen for new connections.
+ asio::error_code listen(base_implementation_type& impl,
+ int backlog, asio::error_code& ec)
+ {
+ socket_ops::listen(impl.socket_, backlog, ec);
+ return ec;
+ }
+
+ // Perform an IO control command on the socket.
+ template <typename IO_Control_Command>
+ asio::error_code io_control(base_implementation_type& impl,
+ IO_Control_Command& command, asio::error_code& ec)
+ {
+ socket_ops::ioctl(impl.socket_, impl.state_, command.name(),
+ static_cast<ioctl_arg_type*>(command.data()), ec);
+ return ec;
+ }
+
+ /// Disable sends or receives on the socket.
+ asio::error_code shutdown(base_implementation_type& impl,
+ socket_base::shutdown_type what, asio::error_code& ec)
+ {
+ socket_ops::shutdown(impl.socket_, what, ec);
+ return ec;
+ }
+
+ // Send the given data to the peer. Returns the number of bytes sent.
+ template <typename ConstBufferSequence>
+ size_t send(base_implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, asio::error_code& ec)
+ {
+ buffer_sequence_adapter<asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_send(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+ }
+
+ // Wait until data can be sent without blocking.
+ size_t send(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, asio::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_write(impl.socket_, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_send(base_implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, Handler handler)
+ {
+ // Allocate and construct an operation to wrap the handler.
+ typedef win_iocp_socket_send_op<ConstBufferSequence, Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.cancel_token_, buffers, handler);
+
+ buffer_sequence_adapter<asio::const_buffer,
+ ConstBufferSequence> bufs(buffers);
+
+ start_send_op(impl, bufs.buffers(), bufs.count(), flags,
+ (impl.state_ & socket_ops::stream_oriented) != 0 && bufs.all_empty(),
+ p.p);
+ p.v = p.p = 0;
+ }
+
+ // Start an asynchronous wait until data can be sent without blocking.
+ template <typename Handler>
+ void async_send(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, Handler handler)
+ {
+ // Allocate and construct an operation to wrap the handler.
+ typedef win_iocp_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.cancel_token_, handler);
+
+ start_reactor_op(impl, reactor::write_op, p.p);
+ p.v = p.p = 0;
+ }
+
+ // Receive some data from the peer. Returns the number of bytes received.
+ template <typename MutableBufferSequence>
+ size_t receive(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, asio::error_code& ec)
+ {
+ buffer_sequence_adapter<asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ return socket_ops::sync_recv(impl.socket_, impl.state_,
+ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, asio::error_code& ec)
+ {
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, ec);
+
+ return 0;
+ }
+
+ // Start an asynchronous receive. The buffer for the data being received
+ // must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive(base_implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, Handler handler)
+ {
+ // Allocate and construct an operation to wrap the handler.
+ typedef win_iocp_socket_recv_op<MutableBufferSequence, Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.state_, impl.cancel_token_, buffers, handler);
+
+ buffer_sequence_adapter<asio::mutable_buffer,
+ MutableBufferSequence> bufs(buffers);
+
+ start_receive_op(impl, bufs.buffers(), bufs.count(), flags,
+ (impl.state_ & socket_ops::stream_oriented) != 0 && bufs.all_empty(),
+ p.p);
+ p.v = p.p = 0;
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler>
+ void async_receive(base_implementation_type& impl, const null_buffers&,
+ socket_base::message_flags flags, Handler handler)
+ {
+ // Allocate and construct an operation to wrap the handler.
+ typedef win_iocp_null_buffers_op<Handler> op;
+ typename op::ptr p = { boost::addressof(handler),
+ asio_handler_alloc_helpers::allocate(
+ sizeof(op), handler), 0 };
+ p.p = new (p.v) op(impl.cancel_token_, handler);
+
+ start_null_buffers_receive_op(impl, flags, p.p);
+ p.v = p.p = 0;
+ }
+
+ // Helper function to restart an asynchronous accept operation.
+ ASIO_DECL void restart_accept_op(socket_type s,
+ socket_holder& new_socket, int family, int type, int protocol,
+ void* output_buffer, DWORD address_length, operation* op);
+
+protected:
+ // Open a new socket implementation.
+ ASIO_DECL asio::error_code do_open(
+ base_implementation_type& impl, int family, int type,
+ int protocol, asio::error_code& ec);
+
+ // Assign a native socket to a socket implementation.
+ ASIO_DECL asio::error_code do_assign(
+ base_implementation_type& impl, int type,
+ socket_type native_socket, asio::error_code& ec);
+
+ // Helper function to start an asynchronous send operation.
+ ASIO_DECL void start_send_op(base_implementation_type& impl,
+ WSABUF* buffers, std::size_t buffer_count,
+ socket_base::message_flags flags, bool noop, operation* op);
+
+ // Helper function to start an asynchronous send_to operation.
+ ASIO_DECL void start_send_to_op(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);
+
+ // Helper function to start an asynchronous receive operation.
+ ASIO_DECL void start_receive_op(base_implementation_type& impl,
+ WSABUF* buffers, std::size_t buffer_count,
+ socket_base::message_flags flags, bool noop, operation* op);
+
+ // Helper function to start an asynchronous null_buffers receive operation.
+ ASIO_DECL void start_null_buffers_receive_op(
+ base_implementation_type& impl,
+ socket_base::message_flags flags, reactor_op* op);
+
+ // Helper function to start an asynchronous receive_from operation.
+ ASIO_DECL void start_receive_from_op(base_implementation_type& impl,
+ WSABUF* buffers, std::size_t buffer_count, socket_addr_type* addr,
+ socket_base::message_flags flags, int* addrlen, operation* op);
+
+ // Helper function to start an asynchronous accept operation.
+ ASIO_DECL void start_accept_op(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);
+
+ // Start an asynchronous read or write operation using the the reactor.
+ ASIO_DECL void start_reactor_op(base_implementation_type& impl,
+ int op_type, reactor_op* op);
+
+ // Start the asynchronous connect operation using the reactor.
+ ASIO_DECL void start_connect_op(base_implementation_type& impl,
+ reactor_op* op, const socket_addr_type* addr, std::size_t addrlen);
+
+ // Helper function to close a socket when the associated object is being
+ // destroyed.
+ ASIO_DECL void close_for_destruction(base_implementation_type& impl);
+
+ // Update the ID of the thread from which cancellation is safe.
+ ASIO_DECL void update_cancellation_thread_id(
+ base_implementation_type& impl);
+
+ // Helper function to get the reactor. If no reactor has been created yet, a
+ // new one is obtained from the io_service and a pointer to it is cached in
+ // this service.
+ ASIO_DECL reactor& get_reactor();
+
+ // Helper function to emulate InterlockedCompareExchangePointer functionality
+ // for:
+ // - very old Platform SDKs; and
+ // - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
+ ASIO_DECL void* interlocked_compare_exchange_pointer(
+ void** dest, void* exch, void* cmp);
+
+ // Helper function to emulate InterlockedExchangePointer functionality for:
+ // - very old Platform SDKs; and
+ // - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
+ ASIO_DECL void* interlocked_exchange_pointer(void** dest, void* val);
+
+ // The io_service used to obtain the reactor, if required.
+ asio::io_service& io_service_;
+
+ // The IOCP service used for running asynchronous operations and dispatching
+ // handlers.
+ win_iocp_io_service& iocp_service_;
+
+ // The reactor used for performing connect operations. This object is created
+ // only if needed.
+ reactor* reactor_;
+
+ // Mutex to protect access to the linked list of implementations.
+ asio::detail::mutex mutex_;
+
+ // The head of a linked list of all implementations.
+ base_implementation_type* impl_list_;
+};
+
+} // namespace detail
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/win_iocp_socket_service_base.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_IOCP)
+
+#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_BASE_HPP
diff --git a/ext/asio/asio/detail/win_mutex.hpp b/ext/asio/asio/detail/win_mutex.hpp
index 1280a4e402..59ad6976cd 100644
--- a/ext/asio/asio/detail/win_mutex.hpp
+++ b/ext/asio/asio/detail/win_mutex.hpp
@@ -1,8 +1,8 @@
//
-// win_mutex.hpp
-// ~~~~~~~~~~~~~
+// detail/win_mutex.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,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_WINDOWS)
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
#include "asio/detail/noncopyable.hpp"
-#include "asio/detail/socket_types.hpp"
#include "asio/detail/scoped_lock.hpp"
+#include "asio/detail/socket_types.hpp"
#include "asio/detail/push_options.hpp"
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
namespace asio {
namespace detail {
@@ -43,18 +35,7 @@ public:
typedef asio::detail::scoped_lock<win_mutex> scoped_lock;
// Constructor.
- win_mutex()
- {
- int error = do_init();
- if (error != 0)
- {
- asio::system_error e(
- asio::error_code(error,
- asio::error::get_system_category()),
- "mutex");
- boost::throw_exception(e);
- }
- }
+ ASIO_DECL win_mutex();
// Destructor.
~win_mutex()
@@ -78,35 +59,7 @@ private:
// Initialisation must be performed in a separate function to the constructor
// since the compiler does not support the use of structured exceptions and
// C++ exceptions in the same function.
- int 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
- ::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000);
-# endif
- return 0;
-#else
- __try
- {
-# if defined(UNDER_CE)
- ::InitializeCriticalSection(&crit_section_);
-# else
- ::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000);
-# endif
- }
- __except(GetExceptionCode() == STATUS_NO_MEMORY
- ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
- {
- return ERROR_OUTOFMEMORY;
- }
-
- return 0;
-#endif
- }
+ ASIO_DECL int do_init();
::CRITICAL_SECTION crit_section_;
};
@@ -114,8 +67,12 @@ private:
} // namespace detail
} // namespace asio
-#endif // defined(BOOST_WINDOWS)
-
#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/win_mutex.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_WINDOWS)
+
#endif // ASIO_DETAIL_WIN_MUTEX_HPP
diff --git a/ext/asio/asio/detail/win_thread.hpp b/ext/asio/asio/detail/win_thread.hpp
index 9bf0665c5e..e73d1a4965 100644
--- a/ext/asio/asio/detail/win_thread.hpp
+++ b/ext/asio/asio/detail/win_thread.hpp
@@ -1,8 +1,8 @@
//
-// win_thread.hpp
-// ~~~~~~~~~~~~~~
+// detail/win_thread.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,34 +15,24 @@
# 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_WINDOWS) && !defined(UNDER_CE)
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/push_options.hpp"
-#include <boost/throw_exception.hpp>
-#include <memory>
-#include <process.h>
-#include "asio/detail/pop_options.hpp"
namespace asio {
namespace detail {
-unsigned int __stdcall win_thread_function(void* arg);
+ASIO_DECL unsigned int __stdcall win_thread_function(void* arg);
#if defined(WINVER) && (WINVER < 0x0500)
-void __stdcall apc_function(ULONG data);
+ASIO_DECL void __stdcall apc_function(ULONG data);
#else
-void __stdcall apc_function(ULONG_PTR data);
+ASIO_DECL void __stdcall apc_function(ULONG_PTR data);
#endif
template <typename T>
@@ -73,92 +63,26 @@ class win_thread
public:
// Constructor.
template <typename Function>
- win_thread(Function f)
- : exit_event_(0)
+ win_thread(Function f, unsigned int stack_size = 0)
+ : thread_(0),
+ exit_event_(0)
{
- std::auto_ptr<func_base> arg(new func<Function>(f));
-
- ::HANDLE entry_event = 0;
- arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0);
- if (!entry_event)
- {
- DWORD last_error = ::GetLastError();
- asio::system_error e(
- asio::error_code(last_error,
- asio::error::get_system_category()),
- "thread.entry_event");
- boost::throw_exception(e);
- }
-
- arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0);
- if (!exit_event_)
- {
- DWORD last_error = ::GetLastError();
- ::CloseHandle(entry_event);
- asio::system_error e(
- asio::error_code(last_error,
- asio::error::get_system_category()),
- "thread.exit_event");
- boost::throw_exception(e);
- }
-
- unsigned int thread_id = 0;
- thread_ = reinterpret_cast<HANDLE>(::_beginthreadex(0, 0,
- win_thread_function, arg.get(), 0, &thread_id));
- if (!thread_)
- {
- DWORD last_error = ::GetLastError();
- if (entry_event)
- ::CloseHandle(entry_event);
- if (exit_event_)
- ::CloseHandle(exit_event_);
- asio::system_error e(
- asio::error_code(last_error,
- asio::error::get_system_category()),
- "thread");
- boost::throw_exception(e);
- }
- arg.release();
-
- if (entry_event)
- {
- ::WaitForSingleObject(entry_event, INFINITE);
- ::CloseHandle(entry_event);
- }
+ start_thread(new func<Function>(f), stack_size);
}
// Destructor.
- ~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.
- }
+ ASIO_DECL ~win_thread();
// Wait for the thread to exit.
- void join()
- {
- ::WaitForSingleObject(exit_event_, INFINITE);
- ::CloseHandle(exit_event_);
- if (terminate_threads())
- {
- ::TerminateThread(thread_, 0);
- }
- else
- {
- ::QueueUserAPC(apc_function, thread_, 0);
- ::WaitForSingleObject(thread_, INFINITE);
- }
- }
+ ASIO_DECL void join();
private:
- friend unsigned int __stdcall win_thread_function(void* arg);
+ friend ASIO_DECL unsigned int __stdcall win_thread_function(void* arg);
#if defined(WINVER) && (WINVER < 0x0500)
- friend void __stdcall apc_function(ULONG);
+ friend ASIO_DECL void __stdcall apc_function(ULONG);
#else
- friend void __stdcall apc_function(ULONG_PTR);
+ friend ASIO_DECL void __stdcall apc_function(ULONG_PTR);
#endif
class func_base
@@ -170,6 +94,12 @@ private:
::HANDLE exit_event_;
};
+ struct auto_func_base_ptr
+ {
+ func_base* ptr;
+ ~auto_func_base_ptr() { delete ptr; }
+ };
+
template <typename Function>
class func
: public func_base
@@ -189,44 +119,21 @@ private:
Function f_;
};
+ ASIO_DECL void start_thread(func_base* arg, unsigned int stack_size);
+
::HANDLE thread_;
::HANDLE exit_event_;
};
-inline 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)
-inline void __stdcall apc_function(ULONG) {}
-#else
-inline void __stdcall apc_function(ULONG_PTR) {}
-#endif
-
} // namespace detail
} // namespace asio
-#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
-
#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/win_thread.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
+
#endif // ASIO_DETAIL_WIN_THREAD_HPP
diff --git a/ext/asio/asio/detail/win_tss_ptr.hpp b/ext/asio/asio/detail/win_tss_ptr.hpp
index 5a4ed33cc2..fb055f6c43 100644
--- a/ext/asio/asio/detail/win_tss_ptr.hpp
+++ b/ext/asio/asio/detail/win_tss_ptr.hpp
@@ -1,8 +1,8 @@
//
-// win_tss_ptr.hpp
-// ~~~~~~~~~~~~~~~
+// detail/win_tss_ptr.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,50 +15,30 @@
# 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_WINDOWS)
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/push_options.hpp"
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
namespace asio {
namespace detail {
+// Helper function to create thread-specific storage.
+ASIO_DECL DWORD win_tss_ptr_create();
+
template <typename T>
class win_tss_ptr
: private noncopyable
{
public:
-#if defined(UNDER_CE)
- enum { out_of_indexes = 0xFFFFFFFF };
-#else
- enum { out_of_indexes = TLS_OUT_OF_INDEXES };
-#endif
-
// Constructor.
win_tss_ptr()
+ : tss_key_(win_tss_ptr_create())
{
- tss_key_ = ::TlsAlloc();
- if (tss_key_ == out_of_indexes)
- {
- DWORD last_error = ::GetLastError();
- asio::system_error e(
- asio::error_code(last_error,
- asio::error::get_system_category()),
- "tss");
- boost::throw_exception(e);
- }
}
// Destructor.
@@ -88,8 +68,12 @@ private:
} // namespace detail
} // namespace asio
-#endif // defined(BOOST_WINDOWS)
-
#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/detail/impl/win_tss_ptr.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_WINDOWS)
+
#endif // ASIO_DETAIL_WIN_TSS_PTR_HPP
diff --git a/ext/asio/asio/detail/wince_thread.hpp b/ext/asio/asio/detail/wince_thread.hpp
index 0b6de488a2..1dc999075c 100644
--- a/ext/asio/asio/detail/wince_thread.hpp
+++ b/ext/asio/asio/detail/wince_thread.hpp
@@ -1,8 +1,8 @@
//
-// wince_thread.hpp
-// ~~~~~~~~~~~~~~~~
+// detail/wince_thread.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,17 @@
# 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_WINDOWS) && defined(UNDER_CE)
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
+#include <memory>
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_types.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
#include "asio/detail/push_options.hpp"
-#include <boost/throw_exception.hpp>
-#include <memory>
-#include "asio/detail/pop_options.hpp"
namespace asio {
namespace detail {
@@ -53,11 +47,9 @@ public:
if (!thread_)
{
DWORD last_error = ::GetLastError();
- asio::system_error e(
- asio::error_code(last_error,
- asio::error::get_system_category()),
- "thread");
- boost::throw_exception(e);
+ asio::error_code ec(last_error,
+ asio::error::get_system_category());
+ asio::detail::throw_error(ec, "thread");
}
arg.release();
}
@@ -117,8 +109,8 @@ inline DWORD WINAPI wince_thread_function(LPVOID arg)
} // namespace detail
} // namespace asio
-#endif // defined(BOOST_WINDOWS) && defined(UNDER_CE)
-
#include "asio/detail/pop_options.hpp"
+#endif // defined(BOOST_WINDOWS) && defined(UNDER_CE)
+
#endif // ASIO_DETAIL_WINCE_THREAD_HPP
diff --git a/ext/asio/asio/detail/winsock_init.hpp b/ext/asio/asio/detail/winsock_init.hpp
index ae5c4bf598..a410859f3b 100644
--- a/ext/asio/asio/detail/winsock_init.hpp
+++ b/ext/asio/asio/detail/winsock_init.hpp
@@ -1,8 +1,8 @@
//
-// winsock_init.hpp
-// ~~~~~~~~~~~~~~~~
+// detail/winsock_init.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,106 +15,76 @@
# 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_WINDOWS) || defined(__CYGWIN__)
#include "asio/detail/push_options.hpp"
-#include <boost/shared_ptr.hpp>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
-#include "asio/detail/noncopyable.hpp"
-#include "asio/detail/socket_types.hpp"
namespace asio {
namespace detail {
-template <int Major = 2, int Minor = 0>
-class winsock_init
- : private noncopyable
+class winsock_init_base
{
-private:
- // Structure to perform the actual initialisation.
- struct do_init
+protected:
+ // Structure to track result of initialisation and number of uses. POD is used
+ // to ensure that the values are zero-initialised prior to any code being run.
+ struct data
{
- do_init()
- {
- WSADATA wsa_data;
- result_ = ::WSAStartup(MAKEWORD(Major, Minor), &wsa_data);
- }
-
- ~do_init()
- {
- ::WSACleanup();
- }
-
- int result() const
- {
- return result_;
- }
-
- // Helper function to manage a do_init singleton. The static instance of the
- // winsock_init object ensures that this function is always called before
- // main, and therefore before any other threads can get started. The do_init
- // instance must be static in this function to ensure that it gets
- // initialised before any other global objects try to use it.
- static boost::shared_ptr<do_init> instance()
- {
- static boost::shared_ptr<do_init> init(new do_init);
- return init;
- }
-
- private:
- int result_;
+ long init_count_;
+ long result_;
};
+ ASIO_DECL static void startup(data& d,
+ unsigned char major, unsigned char minor);
+
+ ASIO_DECL static void cleanup(data& d);
+
+ ASIO_DECL static void throw_on_error(data& d);
+};
+
+template <int Major = 2, int Minor = 0>
+class winsock_init : private winsock_init_base
+{
public:
- // Constructor.
- winsock_init()
- : ref_(do_init::instance())
+ winsock_init(bool allow_throw = true)
+ {
+ startup(data_, Major, Minor);
+ if (allow_throw)
+ throw_on_error(data_);
+ }
+
+ winsock_init(const winsock_init&)
{
- // Check whether winsock was successfully initialised. This check is not
- // performed for the global instance since there will be nobody around to
- // catch the exception.
- if (this != &instance_ && ref_->result() != 0)
- {
- asio::system_error e(
- asio::error_code(ref_->result(),
- asio::error::get_system_category()),
- "winsock");
- boost::throw_exception(e);
- }
+ startup(data_, Major, Minor);
+ throw_on_error(data_);
}
- // Destructor.
~winsock_init()
{
+ cleanup(data_);
}
private:
- // Instance to force initialisation of winsock at global scope.
- static winsock_init instance_;
-
- // Reference to singleton do_init object to ensure that winsock does not get
- // cleaned up until the last user has finished with it.
- boost::shared_ptr<do_init> ref_;
+ static data data_;
};
template <int Major, int Minor>
-winsock_init<Major, Minor> winsock_init<Major, Minor>::instance_;
+winsock_init_base::data winsock_init<Major, Minor>::data_;
+
+// Static variable to ensure that winsock is initialised before main, and
+// therefore before any other threads can get started.
+static const winsock_init<>& winsock_init_instance = winsock_init<>(false);
} // 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/winsock_init.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
#endif // ASIO_DETAIL_WINSOCK_INIT_HPP
diff --git a/ext/asio/asio/detail/wrapped_handler.hpp b/ext/asio/asio/detail/wrapped_handler.hpp
index e40a7f1585..bcebf6ee1d 100644
--- a/ext/asio/asio/detail/wrapped_handler.hpp
+++ b/ext/asio/asio/detail/wrapped_handler.hpp
@@ -1,8 +1,8 @@
//
-// wrapped_handler.hpp
-// ~~~~~~~~~~~~~~~~~~~
+// detail/wrapped_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,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 <boost/type_traits/add_reference.hpp>
-#include "asio/detail/pop_options.hpp"
-
#include "asio/detail/bind_handler.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 {
@@ -34,9 +30,7 @@ class wrapped_handler
public:
typedef void result_type;
- wrapped_handler(
- typename boost::add_reference<Dispatcher>::type dispatcher,
- Handler handler)
+ wrapped_handler(Dispatcher dispatcher, Handler handler)
: dispatcher_(dispatcher),
handler_(handler)
{
diff --git a/ext/asio/asio/error.hpp b/ext/asio/asio/error.hpp
index 73caac6abd..138b5d789c 100644
--- a/ext/asio/asio/error.hpp
+++ b/ext/asio/asio/error.hpp
@@ -2,7 +2,7 @@
// error.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 <cerrno>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error_code.hpp"
-#include "asio/detail/socket_types.hpp"
+#include "asio/detail/config.hpp"
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# include <winerror.h>
+#else
+# include <cerrno>
+# include <netdb.h>
+#endif
#if defined(GENERATING_DOCUMENTATION)
/// INTERNAL ONLY.
@@ -50,6 +48,8 @@
# define ASIO_WIN_OR_POSIX(e_win, e_posix) e_posix
#endif
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace error {
@@ -212,7 +212,21 @@ enum ssl_errors
{
};
-// boostify: error category definitions go here.
+// boostify: error category definitions start here.
+
+} // namespace error
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/error_code.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace error {
+
+// boostify: error category definitions end here.
inline asio::error_code make_error_code(basic_errors e)
{
@@ -247,14 +261,16 @@ inline asio::error_code make_error_code(ssl_errors e)
} // namespace error
} // namespace asio
+#include "asio/detail/pop_options.hpp"
+
#undef ASIO_NATIVE_ERROR
#undef ASIO_SOCKET_ERROR
#undef ASIO_NETDB_ERROR
#undef ASIO_GETADDRINFO_ERROR
#undef ASIO_WIN_OR_POSIX
-#include "asio/impl/error_code.ipp"
-
-#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/impl/error.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
#endif // ASIO_ERROR_HPP
diff --git a/ext/asio/asio/error_code.hpp b/ext/asio/asio/error_code.hpp
index 6657f3f2ee..1af449bda1 100644
--- a/ext/asio/asio/error_code.hpp
+++ b/ext/asio/asio/error_code.hpp
@@ -2,7 +2,7 @@
// error_code.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,8 @@
# 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 <string>
-#include "asio/detail/pop_options.hpp"
#if defined(GENERATING_DOCUMENTATION)
# define ASIO_WIN_OR_POSIX(e_win, e_posix) implementation_defined
@@ -30,6 +26,8 @@
# define ASIO_WIN_OR_POSIX(e_win, e_posix) e_posix
#endif
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace error
@@ -106,7 +104,7 @@ public:
}
/// Get the message associated with the error.
- std::string message() const;
+ ASIO_DECL std::string message() const;
struct unspecified_bool_type_t
{
@@ -114,14 +112,12 @@ public:
typedef void (*unspecified_bool_type)(unspecified_bool_type_t);
- static void unspecified_bool_true(unspecified_bool_type_t)
- {
- }
+ static void unspecified_bool_true(unspecified_bool_type_t) {}
/// Operator returns non-null if there is a non-success error code.
operator unspecified_bool_type() const
{
- if (value_ == 0)
+ if (!value_)
return 0;
else
return &error_code::unspecified_bool_true;
@@ -130,7 +126,7 @@ public:
/// Operator to test if the error represents success.
bool operator!() const
{
- return value_ == 0;
+ return !value_;
}
/// Equality operator to compare two error objects.
@@ -155,10 +151,12 @@ private:
} // namespace asio
-#undef ASIO_WIN_OR_POSIX
+#include "asio/detail/pop_options.hpp"
-#include "asio/error.hpp"
+#undef ASIO_WIN_OR_POSIX
-#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/impl/error_code.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
#endif // ASIO_ERROR_CODE_HPP
diff --git a/ext/asio/asio/handler_alloc_hook.hpp b/ext/asio/asio/handler_alloc_hook.hpp
index 87783cdfa5..dd930b6936 100644
--- a/ext/asio/asio/handler_alloc_hook.hpp
+++ b/ext/asio/asio/handler_alloc_hook.hpp
@@ -2,7 +2,7 @@
// handler_alloc_hook.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 {
diff --git a/ext/asio/asio/handler_invoke_hook.hpp b/ext/asio/asio/handler_invoke_hook.hpp
index b3d7e45440..ef22359b13 100644
--- a/ext/asio/asio/handler_invoke_hook.hpp
+++ b/ext/asio/asio/handler_invoke_hook.hpp
@@ -2,7 +2,7 @@
// handler_invoke_hook.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,6 +15,8 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+#include "asio/detail/config.hpp"
+
#include "asio/detail/push_options.hpp"
namespace asio {
diff --git a/ext/asio/asio/impl/error.ipp b/ext/asio/asio/impl/error.ipp
new file mode 100644
index 0000000000..54388b31ae
--- /dev/null
+++ b/ext/asio/asio/impl/error.ipp
@@ -0,0 +1,33 @@
+//
+// impl/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_IMPL_ERROR_IPP
+#define ASIO_IMPL_ERROR_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace error {
+
+// boostify: error category function definitions go here.
+
+} // namespace error
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IMPL_ERROR_IPP
diff --git a/ext/asio/asio/impl/error_code.ipp b/ext/asio/asio/impl/error_code.ipp
index 614925dd41..ed37a17dd3 100644
--- a/ext/asio/asio/impl/error_code.ipp
+++ b/ext/asio/asio/impl/error_code.ipp
@@ -1,50 +1,55 @@
//
-// error_code.ipp
-// ~~~~~~~~~~~~~~
+// impl/error_code.ipp
+// ~~~~~~~~~~~~~~~~~~~
//
-// 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)
//
-#ifndef ASIO_ERROR_CODE_IPP
-#define ASIO_ERROR_CODE_IPP
+#ifndef ASIO_IMPL_ERROR_CODE_IPP
+#define ASIO_IMPL_ERROR_CODE_IPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# 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 <cerrno>
-#include <cstring>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
+#include "asio/detail/config.hpp"
#include "asio/detail/local_free_on_block_exit.hpp"
#include "asio/detail/socket_types.hpp"
+#include "asio/error.hpp"
+#include "asio/error_code.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
-inline std::string error_code::message() const
+std::string error_code::message() const
{
- if (*this == error::already_open)
- return "Already open.";
- if (*this == error::not_found)
- return "Not found.";
- if (*this == error::fd_set_failure)
- return "The descriptor does not fit into the select call's fd_set.";
+ if (category_ == error::get_misc_category())
+ {
+ if (value_ == error::already_open)
+ return "Already open.";
+ if (value_ == error::not_found)
+ return "Not found.";
+ if (value_ == error::fd_set_failure)
+ return "The descriptor does not fit into the select call's fd_set.";
+ if (value_ == error::not_found)
+ return "Element not found.";
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+ if (value_ == error::eof)
+ return "End of file.";
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+ }
if (category_ == error::get_ssl_category())
return "SSL error.";
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
value_type value = value_;
- if (category() != error::get_system_category() && *this != error::eof)
- return "asio error";
- if (*this == error::eof)
+ if (category_ == error::get_misc_category() && value_ == error::eof)
value = ERROR_HANDLE_EOF;
+ else if (category_ != error::get_system_category())
+ return "asio error";
char* msg = 0;
DWORD length = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
@@ -60,29 +65,31 @@ inline std::string error_code::message() const
else
return "asio error";
#else // defined(BOOST_WINDOWS)
- if (*this == error::eof)
- return "End of file.";
- if (*this == error::host_not_found)
- return "Host not found (authoritative).";
- if (*this == error::host_not_found_try_again)
- return "Host not found (non-authoritative), try again later.";
- if (*this == error::no_recovery)
- return "A non-recoverable error occurred during database lookup.";
- if (*this == error::no_data)
- return "The query is valid, but it does not have associated data.";
- if (*this == error::not_found)
- return "Element not found.";
+ if (category_ == error::get_netdb_category())
+ {
+ if (value_ == error::host_not_found)
+ return "Host not found (authoritative).";
+ if (value_ == error::host_not_found_try_again)
+ return "Host not found (non-authoritative), try again later.";
+ if (value_ == error::no_recovery)
+ return "A non-recoverable error occurred during database lookup.";
+ if (value_ == error::no_data)
+ return "The query is valid, but it does not have associated data.";
+ }
+ if (category_ == error::get_addrinfo_category())
+ {
+ if (value_ == error::service_not_found)
+ return "Service not found.";
+ if (value_ == error::socket_type_not_supported)
+ return "Socket type not supported.";
+ }
+ if (category_ != error::get_system_category())
+ return "asio error";
#if !defined(__sun)
- if (*this == error::operation_aborted)
+ if (value_ == error::operation_aborted)
return "Operation aborted.";
#endif // !defined(__sun)
- if (*this == error::service_not_found)
- return "Service not found.";
- if (*this == error::socket_type_not_supported)
- return "Socket type not supported.";
- if (category() != error::get_system_category())
- return "asio error";
-#if defined(__sun) || defined(__QNX__)
+#if defined(__sun) || defined(__QNX__) || defined(__SYMBIAN32__)
using namespace std;
return strerror(value_);
#elif defined(__MACH__) && defined(__APPLE__) \
@@ -102,4 +109,4 @@ inline std::string error_code::message() const
#include "asio/detail/pop_options.hpp"
-#endif // ASIO_ERROR_CODE_IPP
+#endif // ASIO_IMPL_ERROR_CODE_IPP
diff --git a/ext/asio/asio/impl/io_service.hpp b/ext/asio/asio/impl/io_service.hpp
new file mode 100644
index 0000000000..f0c1730692
--- /dev/null
+++ b/ext/asio/asio/impl/io_service.hpp
@@ -0,0 +1,132 @@
+//
+// impl/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_IMPL_IO_SERVICE_HPP
+#define ASIO_IMPL_IO_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/service_registry.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+template <typename Service>
+inline Service& use_service(io_service& ios)
+{
+ // Check that Service meets the necessary type requirements.
+ (void)static_cast<io_service::service*>(static_cast<Service*>(0));
+ (void)static_cast<const io_service::id*>(&Service::id);
+
+ return ios.service_registry_->template use_service<Service>();
+}
+
+template <typename Service>
+inline void add_service(io_service& ios, Service* svc)
+{
+ // Check that Service meets the necessary type requirements.
+ (void)static_cast<io_service::service*>(static_cast<Service*>(0));
+ (void)static_cast<const io_service::id*>(&Service::id);
+
+ ios.service_registry_->template add_service<Service>(svc);
+}
+
+template <typename Service>
+inline bool has_service(io_service& ios)
+{
+ // Check that Service meets the necessary type requirements.
+ (void)static_cast<io_service::service*>(static_cast<Service*>(0));
+ (void)static_cast<const io_service::id*>(&Service::id);
+
+ return ios.service_registry_->template has_service<Service>();
+}
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+# include "asio/detail/win_iocp_io_service.hpp"
+#else
+# include "asio/detail/task_io_service.hpp"
+#endif
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+template <typename Handler>
+inline void io_service::dispatch(Handler handler)
+{
+ impl_.dispatch(handler);
+}
+
+template <typename Handler>
+inline void io_service::post(Handler handler)
+{
+ impl_.post(handler);
+}
+
+template <typename Handler>
+#if defined(GENERATING_DOCUMENTATION)
+unspecified
+#else
+inline detail::wrapped_handler<io_service&, Handler>
+#endif
+io_service::wrap(Handler handler)
+{
+ return detail::wrapped_handler<io_service&, Handler>(*this, handler);
+}
+
+inline io_service::work::work(asio::io_service& io_service)
+ : io_service_(io_service)
+{
+ io_service_.impl_.work_started();
+}
+
+inline io_service::work::work(const work& other)
+ : io_service_(other.io_service_)
+{
+ io_service_.impl_.work_started();
+}
+
+inline io_service::work::~work()
+{
+ io_service_.impl_.work_finished();
+}
+
+inline asio::io_service& io_service::work::io_service()
+{
+ return io_service_;
+}
+
+inline asio::io_service& io_service::work::get_io_service()
+{
+ return io_service_;
+}
+
+inline asio::io_service& io_service::service::io_service()
+{
+ return owner_;
+}
+
+inline asio::io_service& io_service::service::get_io_service()
+{
+ return owner_;
+}
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IMPL_IO_SERVICE_HPP
diff --git a/ext/asio/asio/impl/io_service.ipp b/ext/asio/asio/impl/io_service.ipp
index c3fed3b820..eb19b8ffd0 100644
--- a/ext/asio/asio/impl/io_service.ipp
+++ b/ext/asio/asio/impl/io_service.ipp
@@ -1,26 +1,23 @@
//
-// io_service.ipp
-// ~~~~~~~~~~~~~~
+// impl/io_service.ipp
+// ~~~~~~~~~~~~~~~~~~~
//
-// 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)
//
-#ifndef ASIO_IO_SERVICE_IPP
-#define ASIO_IO_SERVICE_IPP
+#ifndef ASIO_IMPL_IO_SERVICE_IPP
+#define ASIO_IMPL_IO_SERVICE_IPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# 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/limits.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/io_service.hpp"
#include "asio/detail/service_registry.hpp"
#include "asio/detail/throw_error.hpp"
@@ -28,31 +25,32 @@
# include "asio/detail/win_iocp_io_service.hpp"
#else
# include "asio/detail/task_io_service.hpp"
-# include "asio/detail/reactor.hpp"
#endif
+#include "asio/detail/push_options.hpp"
+
namespace asio {
-inline io_service::io_service()
+io_service::io_service()
: service_registry_(new asio::detail::service_registry(*this)),
impl_(service_registry_->use_service<impl_type>())
{
impl_.init((std::numeric_limits<std::size_t>::max)());
}
-inline io_service::io_service(std::size_t concurrency_hint)
+io_service::io_service(std::size_t concurrency_hint)
: service_registry_(new asio::detail::service_registry(*this)),
impl_(service_registry_->use_service<impl_type>())
{
impl_.init(concurrency_hint);
}
-inline io_service::~io_service()
+io_service::~io_service()
{
delete service_registry_;
}
-inline std::size_t io_service::run()
+std::size_t io_service::run()
{
asio::error_code ec;
std::size_t s = impl_.run(ec);
@@ -60,12 +58,12 @@ inline std::size_t io_service::run()
return s;
}
-inline std::size_t io_service::run(asio::error_code& ec)
+std::size_t io_service::run(asio::error_code& ec)
{
return impl_.run(ec);
}
-inline std::size_t io_service::run_one()
+std::size_t io_service::run_one()
{
asio::error_code ec;
std::size_t s = impl_.run_one(ec);
@@ -73,12 +71,12 @@ inline std::size_t io_service::run_one()
return s;
}
-inline std::size_t io_service::run_one(asio::error_code& ec)
+std::size_t io_service::run_one(asio::error_code& ec)
{
return impl_.run_one(ec);
}
-inline std::size_t io_service::poll()
+std::size_t io_service::poll()
{
asio::error_code ec;
std::size_t s = impl_.poll(ec);
@@ -86,12 +84,12 @@ inline std::size_t io_service::poll()
return s;
}
-inline std::size_t io_service::poll(asio::error_code& ec)
+std::size_t io_service::poll(asio::error_code& ec)
{
return impl_.poll(ec);
}
-inline std::size_t io_service::poll_one()
+std::size_t io_service::poll_one()
{
asio::error_code ec;
std::size_t s = impl_.poll_one(ec);
@@ -99,126 +97,43 @@ inline std::size_t io_service::poll_one()
return s;
}
-inline std::size_t io_service::poll_one(asio::error_code& ec)
+std::size_t io_service::poll_one(asio::error_code& ec)
{
return impl_.poll_one(ec);
}
-inline void io_service::stop()
+void io_service::stop()
{
impl_.stop();
}
-inline void io_service::reset()
+void io_service::reset()
{
impl_.reset();
}
-template <typename Handler>
-inline void io_service::dispatch(Handler handler)
-{
- impl_.dispatch(handler);
-}
-
-template <typename Handler>
-inline void io_service::post(Handler handler)
-{
- impl_.post(handler);
-}
-
-template <typename Handler>
-#if defined(GENERATING_DOCUMENTATION)
-unspecified
-#else
-inline detail::wrapped_handler<io_service&, Handler>
-#endif
-io_service::wrap(Handler handler)
-{
- return detail::wrapped_handler<io_service&, Handler>(*this, handler);
-}
-
-inline io_service::work::work(asio::io_service& io_service)
- : io_service_(io_service)
-{
- io_service_.impl_.work_started();
-}
-
-inline io_service::work::work(const work& other)
- : io_service_(other.io_service_)
-{
- io_service_.impl_.work_started();
-}
-
-inline io_service::work::~work()
-{
- io_service_.impl_.work_finished();
-}
-
-inline asio::io_service& io_service::work::io_service()
-{
- return io_service_;
-}
-
-inline asio::io_service& io_service::work::get_io_service()
-{
- return io_service_;
-}
-
-inline io_service::service::service(asio::io_service& owner)
+io_service::service::service(asio::io_service& owner)
: owner_(owner),
next_(0)
{
}
-inline io_service::service::~service()
-{
-}
-
-inline asio::io_service& io_service::service::io_service()
-{
- return owner_;
-}
-
-inline asio::io_service& io_service::service::get_io_service()
+io_service::service::~service()
{
- return owner_;
}
-template <typename Service>
-inline Service& use_service(io_service& ios)
+service_already_exists::service_already_exists()
+ : std::logic_error("Service already exists.")
{
- // Check that Service meets the necessary type requirements.
- (void)static_cast<io_service::service*>(static_cast<Service*>(0));
- (void)static_cast<const io_service::id*>(&Service::id);
-
- return ios.service_registry_->template use_service<Service>();
}
-template <typename Service>
-void add_service(io_service& ios, Service* svc)
+invalid_service_owner::invalid_service_owner()
+ : std::logic_error("Invalid service owner.")
{
- // Check that Service meets the necessary type requirements.
- (void)static_cast<io_service::service*>(static_cast<Service*>(0));
- (void)static_cast<const io_service::id*>(&Service::id);
-
- if (&ios != &svc->io_service())
- boost::throw_exception(invalid_service_owner());
- if (!ios.service_registry_->template add_service<Service>(svc))
- boost::throw_exception(service_already_exists());
-}
-
-template <typename Service>
-bool has_service(io_service& ios)
-{
- // Check that Service meets the necessary type requirements.
- (void)static_cast<io_service::service*>(static_cast<Service*>(0));
- (void)static_cast<const io_service::id*>(&Service::id);
-
- return ios.service_registry_->template has_service<Service>();
}
} // namespace asio
#include "asio/detail/pop_options.hpp"
-#endif // ASIO_IO_SERVICE_IPP
+#endif // ASIO_IMPL_IO_SERVICE_IPP
diff --git a/ext/asio/asio/impl/read.hpp b/ext/asio/asio/impl/read.hpp
new file mode 100644
index 0000000000..bd5d7b533e
--- /dev/null
+++ b/ext/asio/asio/impl/read.hpp
@@ -0,0 +1,386 @@
+//
+// impl/read.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_IMPL_READ_HPP
+#define ASIO_IMPL_READ_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <algorithm>
+#include "asio/buffer.hpp"
+#include "asio/completion_condition.hpp"
+#include "asio/detail/base_from_completion_cond.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/consuming_buffers.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+template <typename SyncReadStream, typename MutableBufferSequence,
+ typename CompletionCondition>
+std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition, asio::error_code& ec)
+{
+ ec = asio::error_code();
+ asio::detail::consuming_buffers<
+ mutable_buffer, MutableBufferSequence> tmp(buffers);
+ std::size_t total_transferred = 0;
+ tmp.prepare(detail::adapt_completion_condition_result(
+ completion_condition(ec, total_transferred)));
+ while (tmp.begin() != tmp.end())
+ {
+ std::size_t bytes_transferred = s.read_some(tmp, ec);
+ tmp.consume(bytes_transferred);
+ total_transferred += bytes_transferred;
+ tmp.prepare(detail::adapt_completion_condition_result(
+ completion_condition(ec, total_transferred)));
+ }
+ return total_transferred;
+}
+
+template <typename SyncReadStream, typename MutableBufferSequence>
+inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncReadStream, typename MutableBufferSequence,
+ typename CompletionCondition>
+inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = read(s, buffers, completion_condition, ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+template <typename SyncReadStream, typename Allocator,
+ typename CompletionCondition>
+std::size_t read(SyncReadStream& s,
+ asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, asio::error_code& ec)
+{
+ ec = asio::error_code();
+ std::size_t total_transferred = 0;
+ std::size_t max_size = detail::adapt_completion_condition_result(
+ completion_condition(ec, total_transferred));
+ std::size_t bytes_available = read_size_helper(b, max_size);
+ while (bytes_available > 0)
+ {
+ std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
+ b.commit(bytes_transferred);
+ total_transferred += bytes_transferred;
+ max_size = detail::adapt_completion_condition_result(
+ completion_condition(ec, total_transferred));
+ bytes_available = read_size_helper(b, max_size);
+ }
+ return total_transferred;
+}
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read(SyncReadStream& s,
+ asio::basic_streambuf<Allocator>& b)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = read(s, b, transfer_all(), ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncReadStream, typename Allocator,
+ typename CompletionCondition>
+inline std::size_t read(SyncReadStream& s,
+ asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = read(s, b, completion_condition, ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+namespace detail
+{
+ template <typename AsyncReadStream, typename MutableBufferSequence,
+ typename CompletionCondition, typename ReadHandler>
+ class read_op
+ : detail::base_from_completion_cond<CompletionCondition>
+ {
+ public:
+ read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition, ReadHandler handler)
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ stream_(stream),
+ buffers_(buffers),
+ total_transferred_(0),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const asio::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ switch (start)
+ {
+ case 1:
+ buffers_.prepare(this->check_for_completion(ec, total_transferred_));
+ for (;;)
+ {
+ stream_.async_read_some(buffers_, *this);
+ return; default:
+ total_transferred_ += bytes_transferred;
+ buffers_.consume(bytes_transferred);
+ buffers_.prepare(this->check_for_completion(ec, total_transferred_));
+ if ((!ec && bytes_transferred == 0)
+ || buffers_.begin() == buffers_.end())
+ break;
+ }
+
+ handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+ }
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ asio::detail::consuming_buffers<
+ mutable_buffer, MutableBufferSequence> buffers_;
+ std::size_t total_transferred_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncReadStream,
+ typename CompletionCondition, typename ReadHandler>
+ class read_op<AsyncReadStream, asio::mutable_buffers_1,
+ CompletionCondition, ReadHandler>
+ : detail::base_from_completion_cond<CompletionCondition>
+ {
+ public:
+ read_op(AsyncReadStream& stream,
+ const asio::mutable_buffers_1& buffers,
+ CompletionCondition completion_condition,
+ ReadHandler handler)
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ stream_(stream),
+ buffer_(buffers),
+ total_transferred_(0),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const asio::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ std::size_t n = 0;
+ switch (start)
+ {
+ case 1:
+ n = this->check_for_completion(ec, total_transferred_);
+ for (;;)
+ {
+ stream_.async_read_some(asio::buffer(
+ buffer_ + total_transferred_, n), *this);
+ return; default:
+ total_transferred_ += bytes_transferred;
+ if ((!ec && bytes_transferred == 0)
+ || (n = this->check_for_completion(ec, total_transferred_)) == 0
+ || total_transferred_ == asio::buffer_size(buffer_))
+ break;
+ }
+
+ handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+ }
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ asio::mutable_buffer buffer_;
+ std::size_t total_transferred_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncReadStream, typename MutableBufferSequence,
+ typename CompletionCondition, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_op<AsyncReadStream, MutableBufferSequence,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ return asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream, typename MutableBufferSequence,
+ typename CompletionCondition, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_op<AsyncReadStream, MutableBufferSequence,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream,
+ typename MutableBufferSequence, typename CompletionCondition,
+ typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_op<AsyncReadStream, MutableBufferSequence,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncReadStream, typename MutableBufferSequence,
+ typename CompletionCondition, typename ReadHandler>
+inline void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition, ReadHandler handler)
+{
+ detail::read_op<AsyncReadStream, MutableBufferSequence,
+ CompletionCondition, ReadHandler>(
+ s, buffers, completion_condition, handler)(
+ asio::error_code(), 0, 1);
+}
+
+template <typename AsyncReadStream, typename MutableBufferSequence,
+ typename ReadHandler>
+inline void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
+ ReadHandler handler)
+{
+ async_read(s, buffers, transfer_all(), handler);
+}
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+namespace detail
+{
+ template <typename AsyncReadStream, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+ class read_streambuf_op
+ : detail::base_from_completion_cond<CompletionCondition>
+ {
+ public:
+ read_streambuf_op(AsyncReadStream& stream,
+ basic_streambuf<Allocator>& streambuf,
+ CompletionCondition completion_condition, ReadHandler handler)
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ stream_(stream),
+ streambuf_(streambuf),
+ total_transferred_(0),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const asio::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ std::size_t max_size, bytes_available;
+ switch (start)
+ {
+ case 1:
+ max_size = this->check_for_completion(ec, total_transferred_);
+ bytes_available = read_size_helper(streambuf_, max_size);
+ for (;;)
+ {
+ stream_.async_read_some(streambuf_.prepare(bytes_available), *this);
+ return; default:
+ total_transferred_ += bytes_transferred;
+ streambuf_.commit(bytes_transferred);
+ max_size = this->check_for_completion(ec, total_transferred_);
+ bytes_available = read_size_helper(streambuf_, max_size);
+ if ((!ec && bytes_transferred == 0) || bytes_available == 0)
+ break;
+ }
+
+ handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+ }
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ asio::basic_streambuf<Allocator>& streambuf_;
+ std::size_t total_transferred_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncReadStream, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_streambuf_op<AsyncReadStream, Allocator,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ return asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_streambuf_op<AsyncReadStream, Allocator,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream,
+ typename Allocator, typename CompletionCondition, typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_streambuf_op<AsyncReadStream, Allocator,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncReadStream, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+inline void async_read(AsyncReadStream& s,
+ asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, ReadHandler handler)
+{
+ detail::read_streambuf_op<AsyncReadStream,
+ Allocator, CompletionCondition, ReadHandler>(
+ s, b, completion_condition, handler)(
+ asio::error_code(), 0, 1);
+}
+
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+inline void async_read(AsyncReadStream& s,
+ asio::basic_streambuf<Allocator>& b, ReadHandler handler)
+{
+ async_read(s, b, transfer_all(), handler);
+}
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IMPL_READ_HPP
diff --git a/ext/asio/asio/impl/read_at.hpp b/ext/asio/asio/impl/read_at.hpp
new file mode 100644
index 0000000000..da57fe36aa
--- /dev/null
+++ b/ext/asio/asio/impl/read_at.hpp
@@ -0,0 +1,410 @@
+//
+// impl/read_at.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_IMPL_READ_AT_HPP
+#define ASIO_IMPL_READ_AT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <algorithm>
+#include "asio/buffer.hpp"
+#include "asio/completion_condition.hpp"
+#include "asio/detail/base_from_completion_cond.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/consuming_buffers.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
+ typename CompletionCondition>
+std::size_t read_at(SyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition, asio::error_code& ec)
+{
+ ec = asio::error_code();
+ asio::detail::consuming_buffers<
+ mutable_buffer, MutableBufferSequence> tmp(buffers);
+ std::size_t total_transferred = 0;
+ tmp.prepare(detail::adapt_completion_condition_result(
+ completion_condition(ec, total_transferred)));
+ while (tmp.begin() != tmp.end())
+ {
+ std::size_t bytes_transferred = d.read_some_at(
+ offset + total_transferred, tmp, ec);
+ tmp.consume(bytes_transferred);
+ total_transferred += bytes_transferred;
+ tmp.prepare(detail::adapt_completion_condition_result(
+ completion_condition(ec, total_transferred)));
+ }
+ return total_transferred;
+}
+
+template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
+inline std::size_t read_at(SyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, const MutableBufferSequence& buffers)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = read_at(
+ d, offset, buffers, transfer_all(), ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
+ typename CompletionCondition>
+inline std::size_t read_at(SyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = read_at(
+ d, offset, buffers, completion_condition, ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+template <typename SyncRandomAccessReadDevice, typename Allocator,
+ typename CompletionCondition>
+std::size_t read_at(SyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, asio::error_code& ec)
+{
+ ec = asio::error_code();
+ std::size_t total_transferred = 0;
+ std::size_t max_size = detail::adapt_completion_condition_result(
+ completion_condition(ec, total_transferred));
+ std::size_t bytes_available = read_size_helper(b, max_size);
+ while (bytes_available > 0)
+ {
+ std::size_t bytes_transferred = d.read_some_at(
+ offset + total_transferred, b.prepare(bytes_available), ec);
+ b.commit(bytes_transferred);
+ total_transferred += bytes_transferred;
+ max_size = detail::adapt_completion_condition_result(
+ completion_condition(ec, total_transferred));
+ bytes_available = read_size_helper(b, max_size);
+ }
+ return total_transferred;
+}
+
+template <typename SyncRandomAccessReadDevice, typename Allocator>
+inline std::size_t read_at(SyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, asio::basic_streambuf<Allocator>& b)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = read_at(
+ d, offset, b, transfer_all(), ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncRandomAccessReadDevice, typename Allocator,
+ typename CompletionCondition>
+inline std::size_t read_at(SyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = read_at(
+ d, offset, b, completion_condition, ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+namespace detail
+{
+ template <typename AsyncRandomAccessReadDevice,
+ typename MutableBufferSequence, typename CompletionCondition,
+ typename ReadHandler>
+ class read_at_op
+ : detail::base_from_completion_cond<CompletionCondition>
+ {
+ public:
+ read_at_op(AsyncRandomAccessReadDevice& device,
+ boost::uint64_t offset, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition, ReadHandler handler)
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ device_(device),
+ offset_(offset),
+ buffers_(buffers),
+ total_transferred_(0),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const asio::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ switch (start)
+ {
+ case 1:
+ buffers_.prepare(this->check_for_completion(ec, total_transferred_));
+ for (;;)
+ {
+ device_.async_read_some_at(
+ offset_ + total_transferred_, buffers_, *this);
+ return; default:
+ total_transferred_ += bytes_transferred;
+ buffers_.consume(bytes_transferred);
+ buffers_.prepare(this->check_for_completion(ec, total_transferred_));
+ if ((!ec && bytes_transferred == 0)
+ || buffers_.begin() == buffers_.end())
+ break;
+ }
+
+ handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+ }
+ }
+
+ //private:
+ AsyncRandomAccessReadDevice& device_;
+ boost::uint64_t offset_;
+ asio::detail::consuming_buffers<
+ mutable_buffer, MutableBufferSequence> buffers_;
+ std::size_t total_transferred_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncRandomAccessReadDevice,
+ typename CompletionCondition, typename ReadHandler>
+ class read_at_op<AsyncRandomAccessReadDevice,
+ asio::mutable_buffers_1, CompletionCondition, ReadHandler>
+ : detail::base_from_completion_cond<CompletionCondition>
+ {
+ public:
+ read_at_op(AsyncRandomAccessReadDevice& device,
+ boost::uint64_t offset, const asio::mutable_buffers_1& buffers,
+ CompletionCondition completion_condition, ReadHandler handler)
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ device_(device),
+ offset_(offset),
+ buffer_(buffers),
+ total_transferred_(0),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const asio::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ std::size_t n = 0;
+ switch (start)
+ {
+ case 1:
+ n = this->check_for_completion(ec, total_transferred_);
+ for (;;)
+ {
+ device_.async_read_some_at(offset_ + total_transferred_,
+ asio::buffer(buffer_ + total_transferred_, n), *this);
+ return; default:
+ total_transferred_ += bytes_transferred;
+ if ((!ec && bytes_transferred == 0)
+ || (n = this->check_for_completion(ec, total_transferred_)) == 0
+ || total_transferred_ == asio::buffer_size(buffer_))
+ break;
+ }
+
+ handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+ }
+ }
+
+ //private:
+ AsyncRandomAccessReadDevice& device_;
+ boost::uint64_t offset_;
+ asio::mutable_buffer buffer_;
+ std::size_t total_transferred_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncRandomAccessReadDevice,
+ typename MutableBufferSequence, typename CompletionCondition,
+ typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ return asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename AsyncRandomAccessReadDevice,
+ typename MutableBufferSequence, typename CompletionCondition,
+ typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncRandomAccessReadDevice,
+ typename MutableBufferSequence, typename CompletionCondition,
+ typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
+ typename CompletionCondition, typename ReadHandler>
+inline void async_read_at(AsyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition, ReadHandler handler)
+{
+ detail::read_at_op<AsyncRandomAccessReadDevice,
+ MutableBufferSequence, CompletionCondition, ReadHandler>(
+ d, offset, buffers, completion_condition, handler)(
+ asio::error_code(), 0, 1);
+}
+
+template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
+ typename ReadHandler>
+inline void async_read_at(AsyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, const MutableBufferSequence& buffers,
+ ReadHandler handler)
+{
+ async_read_at(d, offset, buffers, transfer_all(), handler);
+}
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+namespace detail
+{
+ template <typename AsyncRandomAccessReadDevice, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+ class read_at_streambuf_op
+ : detail::base_from_completion_cond<CompletionCondition>
+ {
+ public:
+ read_at_streambuf_op(AsyncRandomAccessReadDevice& device,
+ boost::uint64_t offset, basic_streambuf<Allocator>& streambuf,
+ CompletionCondition completion_condition, ReadHandler handler)
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ device_(device),
+ offset_(offset),
+ streambuf_(streambuf),
+ total_transferred_(0),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const asio::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ std::size_t max_size, bytes_available;
+ switch (start)
+ {
+ case 1:
+ max_size = this->check_for_completion(ec, total_transferred_);
+ bytes_available = read_size_helper(streambuf_, max_size);
+ for (;;)
+ {
+ device_.async_read_some_at(offset_ + total_transferred_,
+ streambuf_.prepare(bytes_available), *this);
+ return; default:
+ total_transferred_ += bytes_transferred;
+ streambuf_.commit(bytes_transferred);
+ max_size = this->check_for_completion(ec, total_transferred_);
+ bytes_available = read_size_helper(streambuf_, max_size);
+ if ((!ec && bytes_transferred == 0) || bytes_available == 0)
+ break;
+ }
+
+ handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+ }
+ }
+
+ //private:
+ AsyncRandomAccessReadDevice& device_;
+ boost::uint64_t offset_;
+ asio::basic_streambuf<Allocator>& streambuf_;
+ std::size_t total_transferred_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncRandomAccessReadDevice, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ return asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename AsyncRandomAccessReadDevice, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncRandomAccessReadDevice,
+ typename Allocator, typename CompletionCondition, typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncRandomAccessReadDevice, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+inline void async_read_at(AsyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, ReadHandler handler)
+{
+ detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
+ Allocator, CompletionCondition, ReadHandler>(
+ d, offset, b, completion_condition, handler)(
+ asio::error_code(), 0, 1);
+}
+
+template <typename AsyncRandomAccessReadDevice, typename Allocator,
+ typename ReadHandler>
+inline void async_read_at(AsyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
+ ReadHandler handler)
+{
+ async_read_at(d, offset, b, transfer_all(), handler);
+}
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IMPL_READ_AT_HPP
diff --git a/ext/asio/asio/impl/read_until.hpp b/ext/asio/asio/impl/read_until.hpp
new file mode 100644
index 0000000000..ceacca7fdd
--- /dev/null
+++ b/ext/asio/asio/impl/read_until.hpp
@@ -0,0 +1,902 @@
+//
+// impl/read_until.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_IMPL_READ_UNTIL_HPP
+#define ASIO_IMPL_READ_UNTIL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <algorithm>
+#include <string>
+#include <vector>
+#include <utility>
+#include <boost/limits.hpp>
+#include "asio/buffer.hpp"
+#include "asio/buffers_iterator.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+ asio::basic_streambuf<Allocator>& b, char delim)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = read_until(s, b, delim, ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncReadStream, typename Allocator>
+std::size_t read_until(SyncReadStream& s,
+ asio::basic_streambuf<Allocator>& b, char delim,
+ asio::error_code& ec)
+{
+ std::size_t search_position = 0;
+ for (;;)
+ {
+ // Determine the range of the data to be searched.
+ typedef typename asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = b.data();
+ iterator begin = iterator::begin(buffers);
+ iterator start = begin + search_position;
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ iterator iter = std::find(start, end, delim);
+ if (iter != end)
+ {
+ // Found a match. We're done.
+ ec = asio::error_code();
+ return iter - begin + 1;
+ }
+ else
+ {
+ // No match. Next search can start with the new data.
+ search_position = end - begin;
+ }
+
+ // Check if buffer is full.
+ if (b.size() == b.max_size())
+ {
+ ec = error::not_found;
+ return 0;
+ }
+
+ // Need more data.
+ std::size_t bytes_to_read = read_size_helper(b, 65536);
+ b.commit(s.read_some(b.prepare(bytes_to_read), ec));
+ if (ec)
+ return 0;
+ }
+}
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+ asio::basic_streambuf<Allocator>& b, const std::string& delim)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = read_until(s, b, delim, ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+namespace detail
+{
+ // Algorithm that finds a subsequence of equal values in a sequence. Returns
+ // (iterator,true) if a full match was found, in which case the iterator
+ // points to the beginning of the match. Returns (iterator,false) if a
+ // partial match was found at the end of the first sequence, in which case
+ // the iterator points to the beginning of the partial match. Returns
+ // (last1,false) if no full or partial match was found.
+ template <typename Iterator1, typename Iterator2>
+ std::pair<Iterator1, bool> partial_search(
+ Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
+ {
+ for (Iterator1 iter1 = first1; iter1 != last1; ++iter1)
+ {
+ Iterator1 test_iter1 = iter1;
+ Iterator2 test_iter2 = first2;
+ for (;; ++test_iter1, ++test_iter2)
+ {
+ if (test_iter2 == last2)
+ return std::make_pair(iter1, true);
+ if (test_iter1 == last1)
+ {
+ if (test_iter2 != first2)
+ return std::make_pair(iter1, false);
+ else
+ break;
+ }
+ if (*test_iter1 != *test_iter2)
+ break;
+ }
+ }
+ return std::make_pair(last1, false);
+ }
+} // namespace detail
+
+template <typename SyncReadStream, typename Allocator>
+std::size_t read_until(SyncReadStream& s,
+ asio::basic_streambuf<Allocator>& b, const std::string& delim,
+ asio::error_code& ec)
+{
+ std::size_t search_position = 0;
+ for (;;)
+ {
+ // Determine the range of the data to be searched.
+ typedef typename asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = b.data();
+ iterator begin = iterator::begin(buffers);
+ iterator start = begin + search_position;
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ std::pair<iterator, bool> result = detail::partial_search(
+ start, end, delim.begin(), delim.end());
+ if (result.first != end)
+ {
+ if (result.second)
+ {
+ // Full match. We're done.
+ ec = asio::error_code();
+ return result.first - begin + delim.length();
+ }
+ else
+ {
+ // Partial match. Next search needs to start from beginning of match.
+ search_position = result.first - begin;
+ }
+ }
+ else
+ {
+ // No match. Next search can start with the new data.
+ search_position = end - begin;
+ }
+
+ // Check if buffer is full.
+ if (b.size() == b.max_size())
+ {
+ ec = error::not_found;
+ return 0;
+ }
+
+ // Need more data.
+ std::size_t bytes_to_read = read_size_helper(b, 65536);
+ b.commit(s.read_some(b.prepare(bytes_to_read), ec));
+ if (ec)
+ return 0;
+ }
+}
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+ asio::basic_streambuf<Allocator>& b, const boost::regex& expr)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = read_until(s, b, expr, ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncReadStream, typename Allocator>
+std::size_t read_until(SyncReadStream& s,
+ asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
+ asio::error_code& ec)
+{
+ std::size_t search_position = 0;
+ for (;;)
+ {
+ // Determine the range of the data to be searched.
+ typedef typename asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = b.data();
+ iterator begin = iterator::begin(buffers);
+ iterator start = begin + search_position;
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ boost::match_results<iterator,
+ typename std::vector<boost::sub_match<iterator> >::allocator_type>
+ match_results;
+ if (regex_search(start, end, match_results, expr,
+ boost::match_default | boost::match_partial))
+ {
+ if (match_results[0].matched)
+ {
+ // Full match. We're done.
+ ec = asio::error_code();
+ return match_results[0].second - begin;
+ }
+ else
+ {
+ // Partial match. Next search needs to start from beginning of match.
+ search_position = match_results[0].first - begin;
+ }
+ }
+ else
+ {
+ // No match. Next search can start with the new data.
+ search_position = end - begin;
+ }
+
+ // Check if buffer is full.
+ if (b.size() == b.max_size())
+ {
+ ec = error::not_found;
+ return 0;
+ }
+
+ // Need more data.
+ std::size_t bytes_to_read = read_size_helper(b, 65536);
+ b.commit(s.read_some(b.prepare(bytes_to_read), ec));
+ if (ec)
+ return 0;
+ }
+}
+
+template <typename SyncReadStream, typename Allocator, typename MatchCondition>
+std::size_t read_until(SyncReadStream& s,
+ asio::basic_streambuf<Allocator>& b,
+ MatchCondition match_condition, asio::error_code& ec,
+ typename boost::enable_if<is_match_condition<MatchCondition> >::type*)
+{
+ std::size_t search_position = 0;
+ for (;;)
+ {
+ // Determine the range of the data to be searched.
+ typedef typename asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = b.data();
+ iterator begin = iterator::begin(buffers);
+ iterator start = begin + search_position;
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ std::pair<iterator, bool> result = match_condition(start, end);
+ if (result.second)
+ {
+ // Full match. We're done.
+ ec = asio::error_code();
+ return result.first - begin;
+ }
+ else if (result.first != end)
+ {
+ // Partial match. Next search needs to start from beginning of match.
+ search_position = result.first - begin;
+ }
+ else
+ {
+ // No match. Next search can start with the new data.
+ search_position = end - begin;
+ }
+
+ // Check if buffer is full.
+ if (b.size() == b.max_size())
+ {
+ ec = error::not_found;
+ return 0;
+ }
+
+ // Need more data.
+ std::size_t bytes_to_read = read_size_helper(b, 65536);
+ b.commit(s.read_some(b.prepare(bytes_to_read), ec));
+ if (ec)
+ return 0;
+ }
+}
+
+template <typename SyncReadStream, typename Allocator, typename MatchCondition>
+inline std::size_t read_until(SyncReadStream& s,
+ asio::basic_streambuf<Allocator>& b, MatchCondition match_condition,
+ typename boost::enable_if<is_match_condition<MatchCondition> >::type*)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = read_until(s, b, match_condition, ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+namespace detail
+{
+ template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ class read_until_delim_op
+ {
+ public:
+ read_until_delim_op(AsyncReadStream& stream,
+ asio::basic_streambuf<Allocator>& streambuf,
+ char delim, ReadHandler handler)
+ : stream_(stream),
+ streambuf_(streambuf),
+ delim_(delim),
+ search_position_(0),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const asio::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
+ std::size_t bytes_to_read;
+ switch (start)
+ {
+ case 1:
+ for (;;)
+ {
+ {
+ // Determine the range of the data to be searched.
+ typedef typename asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = streambuf_.data();
+ iterator begin = iterator::begin(buffers);
+ iterator start = begin + search_position_;
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ iterator iter = std::find(start, end, delim_);
+ if (iter != end)
+ {
+ // Found a match. We're done.
+ search_position_ = iter - begin + 1;
+ bytes_to_read = 0;
+ }
+
+ // No match yet. Check if buffer is full.
+ else if (streambuf_.size() == streambuf_.max_size())
+ {
+ search_position_ = not_found;
+ bytes_to_read = 0;
+ }
+
+ // Need to read some more data.
+ else
+ {
+ // Next search can start with the new data.
+ search_position_ = end - begin;
+ bytes_to_read = read_size_helper(streambuf_, 65536);
+ }
+ }
+
+ // Check if we're done.
+ if (!start && bytes_to_read == 0)
+ break;
+
+ // Start a new asynchronous read operation to obtain more data.
+ stream_.async_read_some(streambuf_.prepare(bytes_to_read), *this);
+ return; default:
+ streambuf_.commit(bytes_transferred);
+ if (ec || bytes_transferred == 0)
+ break;
+ }
+
+ const asio::error_code result_ec =
+ (search_position_ == not_found)
+ ? error::not_found : ec;
+
+ const std::size_t result_n =
+ (ec || search_position_ == not_found)
+ ? 0 : search_position_;
+
+ handler_(result_ec, result_n);
+ }
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ asio::basic_streambuf<Allocator>& streambuf_;
+ char delim_;
+ std::size_t search_position_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_until_delim_op<AsyncReadStream,
+ Allocator, ReadHandler>* this_handler)
+ {
+ return asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_until_delim_op<AsyncReadStream,
+ Allocator, ReadHandler>* this_handler)
+ {
+ asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream, typename Allocator,
+ typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_until_delim_op<AsyncReadStream,
+ Allocator, ReadHandler>* this_handler)
+ {
+ asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+void async_read_until(AsyncReadStream& s,
+ asio::basic_streambuf<Allocator>& b, char delim, ReadHandler handler)
+{
+ detail::read_until_delim_op<
+ AsyncReadStream, Allocator, ReadHandler>(
+ s, b, delim, handler)(
+ asio::error_code(), 0, 1);
+}
+
+namespace detail
+{
+ template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ class read_until_delim_string_op
+ {
+ public:
+ read_until_delim_string_op(AsyncReadStream& stream,
+ asio::basic_streambuf<Allocator>& streambuf,
+ const std::string& delim, ReadHandler handler)
+ : stream_(stream),
+ streambuf_(streambuf),
+ delim_(delim),
+ search_position_(0),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const asio::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
+ std::size_t bytes_to_read;
+ switch (start)
+ {
+ case 1:
+ for (;;)
+ {
+ {
+ // Determine the range of the data to be searched.
+ typedef typename asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = streambuf_.data();
+ iterator begin = iterator::begin(buffers);
+ iterator start = begin + search_position_;
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ std::pair<iterator, bool> result = detail::partial_search(
+ start, end, delim_.begin(), delim_.end());
+ if (result.first != end && result.second)
+ {
+ // Full match. We're done.
+ search_position_ = result.first - begin + delim_.length();
+ bytes_to_read = 0;
+ }
+
+ // No match yet. Check if buffer is full.
+ else if (streambuf_.size() == streambuf_.max_size())
+ {
+ search_position_ = not_found;
+ bytes_to_read = 0;
+ }
+
+ // Need to read some more data.
+ else
+ {
+ if (result.first != end)
+ {
+ // Partial match. Next search needs to start from beginning of
+ // match.
+ search_position_ = result.first - begin;
+ }
+ else
+ {
+ // Next search can start with the new data.
+ search_position_ = end - begin;
+ }
+
+ bytes_to_read = read_size_helper(streambuf_, 65536);
+ }
+ }
+
+ // Check if we're done.
+ if (!start && bytes_to_read == 0)
+ break;
+
+ // Start a new asynchronous read operation to obtain more data.
+ stream_.async_read_some(streambuf_.prepare(bytes_to_read), *this);
+ return; default:
+ streambuf_.commit(bytes_transferred);
+ if (ec || bytes_transferred == 0)
+ break;
+ }
+
+ const asio::error_code result_ec =
+ (search_position_ == not_found)
+ ? error::not_found : ec;
+
+ const std::size_t result_n =
+ (ec || search_position_ == not_found)
+ ? 0 : search_position_;
+
+ handler_(result_ec, result_n);
+ }
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ asio::basic_streambuf<Allocator>& streambuf_;
+ std::string delim_;
+ std::size_t search_position_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_until_delim_string_op<AsyncReadStream,
+ Allocator, ReadHandler>* this_handler)
+ {
+ return asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_until_delim_string_op<AsyncReadStream,
+ Allocator, ReadHandler>* this_handler)
+ {
+ asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream,
+ typename Allocator, typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_until_delim_string_op<AsyncReadStream,
+ Allocator, ReadHandler>* this_handler)
+ {
+ asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+void async_read_until(AsyncReadStream& s,
+ asio::basic_streambuf<Allocator>& b, const std::string& delim,
+ ReadHandler handler)
+{
+ detail::read_until_delim_string_op<
+ AsyncReadStream, Allocator, ReadHandler>(
+ s, b, delim, handler)(
+ asio::error_code(), 0, 1);
+}
+
+namespace detail
+{
+ template <typename AsyncReadStream, typename Allocator,
+ typename RegEx, typename ReadHandler>
+ class read_until_expr_op
+ {
+ public:
+ read_until_expr_op(AsyncReadStream& stream,
+ asio::basic_streambuf<Allocator>& streambuf,
+ const boost::regex& expr, ReadHandler handler)
+ : stream_(stream),
+ streambuf_(streambuf),
+ expr_(expr),
+ search_position_(0),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const asio::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
+ std::size_t bytes_to_read;
+ switch (start)
+ {
+ case 1:
+ for (;;)
+ {
+ {
+ // Determine the range of the data to be searched.
+ typedef typename asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = streambuf_.data();
+ iterator begin = iterator::begin(buffers);
+ iterator start = begin + search_position_;
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ boost::match_results<iterator,
+ typename std::vector<boost::sub_match<iterator> >::allocator_type>
+ match_results;
+ bool match = regex_search(start, end, match_results, expr_,
+ boost::match_default | boost::match_partial);
+ if (match && match_results[0].matched)
+ {
+ // Full match. We're done.
+ search_position_ = match_results[0].second - begin;
+ bytes_to_read = 0;
+ }
+
+ // No match yet. Check if buffer is full.
+ else if (streambuf_.size() == streambuf_.max_size())
+ {
+ search_position_ = not_found;
+ bytes_to_read = 0;
+ }
+
+ // Need to read some more data.
+ else
+ {
+ if (match)
+ {
+ // Partial match. Next search needs to start from beginning of
+ // match.
+ search_position_ = match_results[0].first - begin;
+ }
+ else
+ {
+ // Next search can start with the new data.
+ search_position_ = end - begin;
+ }
+
+ bytes_to_read = read_size_helper(streambuf_, 65536);
+ }
+ }
+
+ // Check if we're done.
+ if (!start && bytes_to_read == 0)
+ break;
+
+ // Start a new asynchronous read operation to obtain more data.
+ stream_.async_read_some(streambuf_.prepare(bytes_to_read), *this);
+ return; default:
+ streambuf_.commit(bytes_transferred);
+ if (ec || bytes_transferred == 0)
+ break;
+ }
+
+ const asio::error_code result_ec =
+ (search_position_ == not_found)
+ ? error::not_found : ec;
+
+ const std::size_t result_n =
+ (ec || search_position_ == not_found)
+ ? 0 : search_position_;
+
+ handler_(result_ec, result_n);
+ }
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ asio::basic_streambuf<Allocator>& streambuf_;
+ RegEx expr_;
+ std::size_t search_position_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncReadStream, typename Allocator,
+ typename RegEx, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_until_expr_op<AsyncReadStream,
+ Allocator, RegEx, ReadHandler>* this_handler)
+ {
+ return asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream, typename Allocator,
+ typename RegEx, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_until_expr_op<AsyncReadStream,
+ Allocator, RegEx, ReadHandler>* this_handler)
+ {
+ asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream, typename Allocator,
+ typename RegEx, typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_until_expr_op<AsyncReadStream,
+ Allocator, RegEx, ReadHandler>* this_handler)
+ {
+ asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+void async_read_until(AsyncReadStream& s,
+ asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
+ ReadHandler handler)
+{
+ detail::read_until_expr_op<AsyncReadStream,
+ Allocator, boost::regex, ReadHandler>(
+ s, b, expr, handler)(
+ asio::error_code(), 0, 1);
+}
+
+namespace detail
+{
+ template <typename AsyncReadStream, typename Allocator,
+ typename MatchCondition, typename ReadHandler>
+ class read_until_match_op
+ {
+ public:
+ read_until_match_op(AsyncReadStream& stream,
+ asio::basic_streambuf<Allocator>& streambuf,
+ MatchCondition match_condition, ReadHandler handler)
+ : stream_(stream),
+ streambuf_(streambuf),
+ match_condition_(match_condition),
+ search_position_(0),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const asio::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
+ std::size_t bytes_to_read;
+ switch (start)
+ {
+ case 1:
+ for (;;)
+ {
+ {
+ // Determine the range of the data to be searched.
+ typedef typename asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = streambuf_.data();
+ iterator begin = iterator::begin(buffers);
+ iterator start = begin + search_position_;
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ std::pair<iterator, bool> result = match_condition_(start, end);
+ if (result.second)
+ {
+ // Full match. We're done.
+ search_position_ = result.first - begin;
+ bytes_to_read = 0;
+ }
+
+ // No match yet. Check if buffer is full.
+ else if (streambuf_.size() == streambuf_.max_size())
+ {
+ search_position_ = not_found;
+ bytes_to_read = 0;
+ }
+
+ // Need to read some more data.
+ else
+ {
+ if (result.first != end)
+ {
+ // Partial match. Next search needs to start from beginning of
+ // match.
+ search_position_ = result.first - begin;
+ }
+ else
+ {
+ // Next search can start with the new data.
+ search_position_ = end - begin;
+ }
+
+ bytes_to_read = read_size_helper(streambuf_, 65536);
+ }
+ }
+
+ // Check if we're done.
+ if (!start && bytes_to_read == 0)
+ break;
+
+ // Start a new asynchronous read operation to obtain more data.
+ stream_.async_read_some(streambuf_.prepare(bytes_to_read), *this);
+ return; default:
+ streambuf_.commit(bytes_transferred);
+ if (ec || bytes_transferred == 0)
+ break;
+ }
+
+ const asio::error_code result_ec =
+ (search_position_ == not_found)
+ ? error::not_found : ec;
+
+ const std::size_t result_n =
+ (ec || search_position_ == not_found)
+ ? 0 : search_position_;
+
+ handler_(result_ec, result_n);
+ }
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ asio::basic_streambuf<Allocator>& streambuf_;
+ MatchCondition match_condition_;
+ std::size_t search_position_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncReadStream, typename Allocator,
+ typename MatchCondition, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_until_match_op<AsyncReadStream,
+ Allocator, MatchCondition, ReadHandler>* this_handler)
+ {
+ return asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream, typename Allocator,
+ typename MatchCondition, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_until_match_op<AsyncReadStream,
+ Allocator, MatchCondition, ReadHandler>* this_handler)
+ {
+ asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream, typename Allocator,
+ typename MatchCondition, typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_until_match_op<AsyncReadStream,
+ Allocator, MatchCondition, ReadHandler>* this_handler)
+ {
+ asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncReadStream, typename Allocator,
+ typename MatchCondition, typename ReadHandler>
+void async_read_until(AsyncReadStream& s,
+ asio::basic_streambuf<Allocator>& b,
+ MatchCondition match_condition, ReadHandler handler,
+ typename boost::enable_if<is_match_condition<MatchCondition> >::type*)
+{
+ detail::read_until_match_op<
+ AsyncReadStream, Allocator, MatchCondition, ReadHandler>(
+ s, b, match_condition, handler)(
+ asio::error_code(), 0, 1);
+}
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IMPL_READ_UNTIL_HPP
diff --git a/ext/asio/asio/impl/serial_port_base.hpp b/ext/asio/asio/impl/serial_port_base.hpp
new file mode 100644
index 0000000000..758e65251e
--- /dev/null
+++ b/ext/asio/asio/impl/serial_port_base.hpp
@@ -0,0 +1,59 @@
+//
+// impl/serial_port_base.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// 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_IMPL_SERIAL_PORT_BASE_HPP
+#define ASIO_IMPL_SERIAL_PORT_BASE_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 {
+
+inline serial_port_base::baud_rate::baud_rate(unsigned int rate)
+ : value_(rate)
+{
+}
+
+inline unsigned int serial_port_base::baud_rate::value() const
+{
+ return value_;
+}
+
+inline serial_port_base::flow_control::type
+serial_port_base::flow_control::value() const
+{
+ return value_;
+}
+
+inline serial_port_base::parity::type serial_port_base::parity::value() const
+{
+ return value_;
+}
+
+inline serial_port_base::stop_bits::type
+serial_port_base::stop_bits::value() const
+{
+ return value_;
+}
+
+inline unsigned int serial_port_base::character_size::value() const
+{
+ return value_;
+}
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IMPL_SERIAL_PORT_BASE_HPP
diff --git a/ext/asio/asio/impl/serial_port_base.ipp b/ext/asio/asio/impl/serial_port_base.ipp
index 64ab6a45a0..4d3204dab3 100644
--- a/ext/asio/asio/impl/serial_port_base.ipp
+++ b/ext/asio/asio/impl/serial_port_base.ipp
@@ -1,40 +1,43 @@
//
-// serial_port_base.ipp
-// ~~~~~~~~~~~~~~~~~~~~
+// impl/serial_port_base.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// 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
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-#ifndef ASIO_SERIAL_PORT_BASE_IPP
-#define ASIO_SERIAL_PORT_BASE_IPP
+#ifndef ASIO_IMPL_SERIAL_PORT_BASE_IPP
+#define ASIO_IMPL_SERIAL_PORT_BASE_IPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# 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"
+#if defined(ASIO_HAS_SERIAL_PORT)
+
+#include <stdexcept>
#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
+#include "asio/error.hpp"
+#include "asio/serial_port_base.hpp"
-namespace asio {
+#if defined(GENERATING_DOCUMENTATION)
+# define ASIO_OPTION_STORAGE implementation_defined
+#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# define ASIO_OPTION_STORAGE DCB
+#else
+# define ASIO_OPTION_STORAGE termios
+#endif
-inline serial_port_base::baud_rate::baud_rate(unsigned int rate)
- : value_(rate)
-{
-}
+#include "asio/detail/push_options.hpp"
-inline unsigned int serial_port_base::baud_rate::value() const
-{
- return value_;
-}
+namespace asio {
-inline asio::error_code serial_port_base::baud_rate::store(
+asio::error_code serial_port_base::baud_rate::store(
ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const
{
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -122,7 +125,7 @@ inline asio::error_code serial_port_base::baud_rate::store(
return ec;
}
-inline asio::error_code serial_port_base::baud_rate::load(
+asio::error_code serial_port_base::baud_rate::load(
const ASIO_OPTION_STORAGE& storage, asio::error_code& ec)
{
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -204,7 +207,7 @@ inline asio::error_code serial_port_base::baud_rate::load(
return ec;
}
-inline serial_port_base::flow_control::flow_control(
+serial_port_base::flow_control::flow_control(
serial_port_base::flow_control::type t)
: value_(t)
{
@@ -215,13 +218,7 @@ inline serial_port_base::flow_control::flow_control(
}
}
-inline serial_port_base::flow_control::type
-serial_port_base::flow_control::value() const
-{
- return value_;
-}
-
-inline asio::error_code serial_port_base::flow_control::store(
+asio::error_code serial_port_base::flow_control::store(
ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const
{
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -255,12 +252,16 @@ inline asio::error_code serial_port_base::flow_control::store(
storage.c_iflag &= ~(IXOFF | IXON);
# if defined(_BSD_SOURCE)
storage.c_cflag &= ~CRTSCTS;
+# elif defined(__QNXNTO__)
+ storage.c_cflag &= ~(IHFLOW | OHFLOW);
# endif
break;
case software:
storage.c_iflag |= IXOFF | IXON;
# if defined(_BSD_SOURCE)
storage.c_cflag &= ~CRTSCTS;
+# elif defined(__QNXNTO__)
+ storage.c_cflag &= ~(IHFLOW | OHFLOW);
# endif
break;
case hardware:
@@ -268,6 +269,10 @@ inline asio::error_code serial_port_base::flow_control::store(
storage.c_iflag &= ~(IXOFF | IXON);
storage.c_cflag |= CRTSCTS;
break;
+# elif defined(__QNXNTO__)
+ storage.c_iflag &= ~(IXOFF | IXON);
+ storage.c_cflag |= (IHFLOW | OHFLOW);
+ break;
# else
ec = asio::error::operation_not_supported;
return ec;
@@ -280,7 +285,7 @@ inline asio::error_code serial_port_base::flow_control::store(
return ec;
}
-inline asio::error_code serial_port_base::flow_control::load(
+asio::error_code serial_port_base::flow_control::load(
const ASIO_OPTION_STORAGE& storage, asio::error_code& ec)
{
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -306,6 +311,11 @@ inline asio::error_code serial_port_base::flow_control::load(
{
value_ = hardware;
}
+# elif defined(__QNXNTO__)
+ else if (storage.c_cflag & IHFLOW && storage.c_cflag & OHFLOW)
+ {
+ value_ = hardware;
+ }
# endif
else
{
@@ -316,7 +326,7 @@ inline asio::error_code serial_port_base::flow_control::load(
return ec;
}
-inline serial_port_base::parity::parity(serial_port_base::parity::type t)
+serial_port_base::parity::parity(serial_port_base::parity::type t)
: value_(t)
{
if (t != none && t != odd && t != even)
@@ -326,12 +336,7 @@ inline serial_port_base::parity::parity(serial_port_base::parity::type t)
}
}
-inline serial_port_base::parity::type serial_port_base::parity::value() const
-{
- return value_;
-}
-
-inline asio::error_code serial_port_base::parity::store(
+asio::error_code serial_port_base::parity::store(
ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const
{
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -378,7 +383,7 @@ inline asio::error_code serial_port_base::parity::store(
return ec;
}
-inline asio::error_code serial_port_base::parity::load(
+asio::error_code serial_port_base::parity::load(
const ASIO_OPTION_STORAGE& storage, asio::error_code& ec)
{
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -415,7 +420,7 @@ inline asio::error_code serial_port_base::parity::load(
return ec;
}
-inline serial_port_base::stop_bits::stop_bits(
+serial_port_base::stop_bits::stop_bits(
serial_port_base::stop_bits::type t)
: value_(t)
{
@@ -426,13 +431,7 @@ inline serial_port_base::stop_bits::stop_bits(
}
}
-inline serial_port_base::stop_bits::type
-serial_port_base::stop_bits::value() const
-{
- return value_;
-}
-
-inline asio::error_code serial_port_base::stop_bits::store(
+asio::error_code serial_port_base::stop_bits::store(
ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const
{
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -468,7 +467,7 @@ inline asio::error_code serial_port_base::stop_bits::store(
return ec;
}
-inline asio::error_code serial_port_base::stop_bits::load(
+asio::error_code serial_port_base::stop_bits::load(
const ASIO_OPTION_STORAGE& storage, asio::error_code& ec)
{
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -495,7 +494,7 @@ inline asio::error_code serial_port_base::stop_bits::load(
return ec;
}
-inline serial_port_base::character_size::character_size(unsigned int t)
+serial_port_base::character_size::character_size(unsigned int t)
: value_(t)
{
if (t < 5 || t > 8)
@@ -505,12 +504,7 @@ inline serial_port_base::character_size::character_size(unsigned int t)
}
}
-inline unsigned int serial_port_base::character_size::value() const
-{
- return value_;
-}
-
-inline asio::error_code serial_port_base::character_size::store(
+asio::error_code serial_port_base::character_size::store(
ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const
{
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -530,7 +524,7 @@ inline asio::error_code serial_port_base::character_size::store(
return ec;
}
-inline asio::error_code serial_port_base::character_size::load(
+asio::error_code serial_port_base::character_size::load(
const ASIO_OPTION_STORAGE& storage, asio::error_code& ec)
{
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -554,4 +548,8 @@ inline asio::error_code serial_port_base::character_size::load(
#include "asio/detail/pop_options.hpp"
-#endif // ASIO_SERIAL_PORT_BASE_IPP
+#undef ASIO_OPTION_STORAGE
+
+#endif // defined(ASIO_HAS_SERIAL_PORT)
+
+#endif // ASIO_IMPL_SERIAL_PORT_BASE_IPP
diff --git a/ext/asio/asio/impl/src.cpp b/ext/asio/asio/impl/src.cpp
new file mode 100644
index 0000000000..1dac400b66
--- /dev/null
+++ b/ext/asio/asio/impl/src.cpp
@@ -0,0 +1,25 @@
+//
+// impl/src.cpp
+// ~~~~~~~~~~~~
+//
+// 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)
+//
+
+#if defined(_MSC_VER) \
+ || defined(__BORLANDC__) \
+ || defined(__DMC__)
+# pragma message ( \
+ "This file is deprecated. " \
+ "Please #include <asio/impl/src.hpp> instead.")
+#elif defined(__GNUC__) \
+ || defined(__HP_aCC) \
+ || defined(__SUNPRO_CC) \
+ || defined(__IBMCPP__)
+# warning "This file is deprecated."
+# warning "Please #include <asio/impl/src.hpp> instead."
+#endif
+
+#include "asio/impl/src.hpp"
diff --git a/ext/asio/asio/impl/src.hpp b/ext/asio/asio/impl/src.hpp
new file mode 100644
index 0000000000..b37eabddb8
--- /dev/null
+++ b/ext/asio/asio/impl/src.hpp
@@ -0,0 +1,65 @@
+//
+// impl/src.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_IMPL_SRC_HPP
+#define ASIO_IMPL_SRC_HPP
+
+#define ASIO_SOURCE
+
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HEADER_ONLY)
+# error Do not compile Asio library source with ASIO_HEADER_ONLY defined
+#endif
+
+#include "asio/impl/error.ipp"
+#include "asio/impl/error_code.ipp"
+#include "asio/impl/io_service.ipp"
+#include "asio/impl/serial_port_base.ipp"
+#include "asio/detail/impl/descriptor_ops.ipp"
+#include "asio/detail/impl/dev_poll_reactor.ipp"
+#include "asio/detail/impl/epoll_reactor.ipp"
+#include "asio/detail/impl/eventfd_select_interrupter.ipp"
+#include "asio/detail/impl/kqueue_reactor.ipp"
+#include "asio/detail/impl/pipe_select_interrupter.ipp"
+#include "asio/detail/impl/posix_event.ipp"
+#include "asio/detail/impl/posix_mutex.ipp"
+#include "asio/detail/impl/posix_thread.ipp"
+#include "asio/detail/impl/posix_tss_ptr.ipp"
+#include "asio/detail/impl/reactive_descriptor_service.ipp"
+#include "asio/detail/impl/reactive_serial_port_service.ipp"
+#include "asio/detail/impl/reactive_socket_service_base.ipp"
+#include "asio/detail/impl/resolver_service_base.ipp"
+#include "asio/detail/impl/select_reactor.ipp"
+#include "asio/detail/impl/service_registry.ipp"
+#include "asio/detail/impl/socket_ops.ipp"
+#include "asio/detail/impl/socket_select_interrupter.ipp"
+#include "asio/detail/impl/strand_service.ipp"
+#include "asio/detail/impl/task_io_service.ipp"
+#include "asio/detail/impl/throw_error.ipp"
+#include "asio/detail/impl/timer_queue.ipp"
+#include "asio/detail/impl/timer_queue_set.ipp"
+#include "asio/detail/impl/win_iocp_handle_service.ipp"
+#include "asio/detail/impl/win_iocp_io_service.ipp"
+#include "asio/detail/impl/win_iocp_serial_port_service.ipp"
+#include "asio/detail/impl/win_iocp_socket_service_base.ipp"
+#include "asio/detail/impl/win_event.ipp"
+#include "asio/detail/impl/win_mutex.ipp"
+#include "asio/detail/impl/win_thread.ipp"
+#include "asio/detail/impl/win_tss_ptr.ipp"
+#include "asio/detail/impl/winsock_init.ipp"
+#include "asio/ip/impl/address.ipp"
+#include "asio/ip/impl/address_v4.ipp"
+#include "asio/ip/impl/address_v6.ipp"
+#include "asio/ip/impl/host_name.ipp"
+#include "asio/ip/detail/impl/endpoint.ipp"
+#include "asio/local/detail/impl/endpoint.ipp"
+
+#endif // ASIO_IMPL_SRC_HPP
diff --git a/ext/asio/asio/impl/write.hpp b/ext/asio/asio/impl/write.hpp
new file mode 100644
index 0000000000..91cb65ecbf
--- /dev/null
+++ b/ext/asio/asio/impl/write.hpp
@@ -0,0 +1,396 @@
+//
+// impl/write.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_IMPL_WRITE_HPP
+#define ASIO_IMPL_WRITE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/buffer.hpp"
+#include "asio/completion_condition.hpp"
+#include "asio/detail/base_from_completion_cond.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/consuming_buffers.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+template <typename SyncWriteStream, typename ConstBufferSequence,
+ typename CompletionCondition>
+std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition, asio::error_code& ec)
+{
+ ec = asio::error_code();
+ asio::detail::consuming_buffers<
+ const_buffer, ConstBufferSequence> tmp(buffers);
+ std::size_t total_transferred = 0;
+ tmp.prepare(detail::adapt_completion_condition_result(
+ completion_condition(ec, total_transferred)));
+ while (tmp.begin() != tmp.end())
+ {
+ std::size_t bytes_transferred = s.write_some(tmp, ec);
+ tmp.consume(bytes_transferred);
+ total_transferred += bytes_transferred;
+ tmp.prepare(detail::adapt_completion_condition_result(
+ completion_condition(ec, total_transferred)));
+ }
+ return total_transferred;
+}
+
+template <typename SyncWriteStream, typename ConstBufferSequence>
+inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncWriteStream, typename ConstBufferSequence,
+ typename CompletionCondition>
+inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = write(s, buffers, completion_condition, ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+template <typename SyncWriteStream, typename Allocator,
+ typename CompletionCondition>
+std::size_t write(SyncWriteStream& s,
+ asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, asio::error_code& ec)
+{
+ std::size_t bytes_transferred = write(s, b.data(), completion_condition, ec);
+ b.consume(bytes_transferred);
+ return bytes_transferred;
+}
+
+template <typename SyncWriteStream, typename Allocator>
+inline std::size_t write(SyncWriteStream& s,
+ asio::basic_streambuf<Allocator>& b)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = write(s, b, transfer_all(), ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncWriteStream, typename Allocator,
+ typename CompletionCondition>
+inline std::size_t write(SyncWriteStream& s,
+ asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = write(s, b, completion_condition, ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+namespace detail
+{
+ template <typename AsyncWriteStream, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+ class write_op
+ : detail::base_from_completion_cond<CompletionCondition>
+ {
+ public:
+ write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition, WriteHandler handler)
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ stream_(stream),
+ buffers_(buffers),
+ total_transferred_(0),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const asio::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ switch (start)
+ {
+ case 1:
+ buffers_.prepare(this->check_for_completion(ec, total_transferred_));
+ for (;;)
+ {
+ stream_.async_write_some(buffers_, *this);
+ return; default:
+ total_transferred_ += bytes_transferred;
+ buffers_.consume(bytes_transferred);
+ buffers_.prepare(this->check_for_completion(ec, total_transferred_));
+ if ((!ec && bytes_transferred == 0)
+ || buffers_.begin() == buffers_.end())
+ break;
+ }
+
+ handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+ }
+ }
+
+ //private:
+ AsyncWriteStream& stream_;
+ asio::detail::consuming_buffers<
+ const_buffer, ConstBufferSequence> buffers_;
+ std::size_t total_transferred_;
+ WriteHandler handler_;
+ };
+
+ template <typename AsyncWriteStream,
+ typename CompletionCondition, typename WriteHandler>
+ class write_op<AsyncWriteStream, asio::mutable_buffers_1,
+ CompletionCondition, WriteHandler>
+ : detail::base_from_completion_cond<CompletionCondition>
+ {
+ public:
+ write_op(AsyncWriteStream& stream,
+ const asio::mutable_buffers_1& buffers,
+ CompletionCondition completion_condition,
+ WriteHandler handler)
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ stream_(stream),
+ buffer_(buffers),
+ total_transferred_(0),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const asio::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ std::size_t n = 0;
+ switch (start)
+ {
+ case 1:
+ n = this->check_for_completion(ec, total_transferred_);
+ for (;;)
+ {
+ stream_.async_write_some(asio::buffer(
+ buffer_ + total_transferred_, n), *this);
+ return; default:
+ total_transferred_ += bytes_transferred;
+ if ((!ec && bytes_transferred == 0)
+ || (n = this->check_for_completion(ec, total_transferred_)) == 0
+ || total_transferred_ == asio::buffer_size(buffer_))
+ break;
+ }
+
+ handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+ }
+ }
+
+ //private:
+ AsyncWriteStream& stream_;
+ asio::mutable_buffer buffer_;
+ std::size_t total_transferred_;
+ WriteHandler handler_;
+ };
+
+ template <typename AsyncWriteStream,
+ typename CompletionCondition, typename WriteHandler>
+ class write_op<AsyncWriteStream, asio::const_buffers_1,
+ CompletionCondition, WriteHandler>
+ : detail::base_from_completion_cond<CompletionCondition>
+ {
+ public:
+ write_op(AsyncWriteStream& stream,
+ const asio::const_buffers_1& buffers,
+ CompletionCondition completion_condition,
+ WriteHandler handler)
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ stream_(stream),
+ buffer_(buffers),
+ total_transferred_(0),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const asio::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ std::size_t n = 0;
+ switch (start)
+ {
+ case 1:
+ n = this->check_for_completion(ec, total_transferred_);
+ for (;;)
+ {
+ stream_.async_write_some(asio::buffer(
+ buffer_ + total_transferred_, n), *this);
+ return; default:
+ total_transferred_ += bytes_transferred;
+ if ((!ec && bytes_transferred == 0)
+ || (n = this->check_for_completion(ec, total_transferred_)) == 0
+ || total_transferred_ == asio::buffer_size(buffer_))
+ break;
+ }
+
+ handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+ }
+ }
+
+ //private:
+ AsyncWriteStream& stream_;
+ asio::const_buffer buffer_;
+ std::size_t total_transferred_;
+ WriteHandler handler_;
+ };
+
+ template <typename AsyncWriteStream, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ write_op<AsyncWriteStream, ConstBufferSequence,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ return asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename AsyncWriteStream, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ write_op<AsyncWriteStream, ConstBufferSequence,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncWriteStream,
+ typename ConstBufferSequence, typename CompletionCondition,
+ typename WriteHandler>
+ inline void asio_handler_invoke(const Function& function,
+ write_op<AsyncWriteStream, ConstBufferSequence,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncWriteStream, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition, WriteHandler handler)
+{
+ detail::write_op<AsyncWriteStream, ConstBufferSequence,
+ CompletionCondition, WriteHandler>(
+ s, buffers, completion_condition, handler)(
+ asio::error_code(), 0, 1);
+}
+
+template <typename AsyncWriteStream, typename ConstBufferSequence,
+ typename WriteHandler>
+inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
+ WriteHandler handler)
+{
+ async_write(s, buffers, transfer_all(), handler);
+}
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+namespace detail
+{
+ template <typename AsyncWriteStream, typename Allocator,
+ typename WriteHandler>
+ class write_streambuf_handler
+ {
+ public:
+ write_streambuf_handler(asio::basic_streambuf<Allocator>& streambuf,
+ WriteHandler handler)
+ : streambuf_(streambuf),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const asio::error_code& ec,
+ const std::size_t bytes_transferred)
+ {
+ streambuf_.consume(bytes_transferred);
+ handler_(ec, bytes_transferred);
+ }
+
+ //private:
+ asio::basic_streambuf<Allocator>& streambuf_;
+ WriteHandler handler_;
+ };
+
+ template <typename AsyncWriteStream, typename Allocator,
+ typename WriteHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ write_streambuf_handler<AsyncWriteStream,
+ Allocator, WriteHandler>* this_handler)
+ {
+ return asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename AsyncWriteStream, typename Allocator,
+ typename WriteHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ write_streambuf_handler<AsyncWriteStream,
+ Allocator, WriteHandler>* this_handler)
+ {
+ asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncWriteStream, typename Allocator,
+ typename WriteHandler>
+ inline void asio_handler_invoke(const Function& function,
+ write_streambuf_handler<AsyncWriteStream,
+ Allocator, WriteHandler>* this_handler)
+ {
+ asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncWriteStream, typename Allocator,
+ typename CompletionCondition, typename WriteHandler>
+inline void async_write(AsyncWriteStream& s,
+ asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, WriteHandler handler)
+{
+ async_write(s, b.data(), completion_condition,
+ detail::write_streambuf_handler<
+ AsyncWriteStream, Allocator, WriteHandler>(b, handler));
+}
+
+template <typename AsyncWriteStream, typename Allocator, typename WriteHandler>
+inline void async_write(AsyncWriteStream& s,
+ asio::basic_streambuf<Allocator>& b, WriteHandler handler)
+{
+ async_write(s, b, transfer_all(), handler);
+}
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IMPL_WRITE_HPP
diff --git a/ext/asio/asio/impl/write_at.hpp b/ext/asio/asio/impl/write_at.hpp
new file mode 100644
index 0000000000..1de6800801
--- /dev/null
+++ b/ext/asio/asio/impl/write_at.hpp
@@ -0,0 +1,417 @@
+//
+// impl/write_at.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_IMPL_WRITE_AT_HPP
+#define ASIO_IMPL_WRITE_AT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/buffer.hpp"
+#include "asio/completion_condition.hpp"
+#include "asio/detail/base_from_completion_cond.hpp"
+#include "asio/detail/bind_handler.hpp"
+#include "asio/detail/consuming_buffers.hpp"
+#include "asio/detail/handler_alloc_helpers.hpp"
+#include "asio/detail/handler_invoke_helpers.hpp"
+#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename CompletionCondition>
+std::size_t write_at(SyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition, asio::error_code& ec)
+{
+ ec = asio::error_code();
+ asio::detail::consuming_buffers<
+ const_buffer, ConstBufferSequence> tmp(buffers);
+ std::size_t total_transferred = 0;
+ tmp.prepare(detail::adapt_completion_condition_result(
+ completion_condition(ec, total_transferred)));
+ while (tmp.begin() != tmp.end())
+ {
+ std::size_t bytes_transferred = d.write_some_at(
+ offset + total_transferred, tmp, ec);
+ tmp.consume(bytes_transferred);
+ total_transferred += bytes_transferred;
+ tmp.prepare(detail::adapt_completion_condition_result(
+ completion_condition(ec, total_transferred)));
+ }
+ return total_transferred;
+}
+
+template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>
+inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, const ConstBufferSequence& buffers)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = write_at(
+ d, offset, buffers, transfer_all(), ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename CompletionCondition>
+inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = write_at(
+ d, offset, buffers, completion_condition, ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+template <typename SyncRandomAccessWriteDevice, typename Allocator,
+ typename CompletionCondition>
+std::size_t write_at(SyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, asio::error_code& ec)
+{
+ std::size_t bytes_transferred = write_at(
+ d, offset, b.data(), completion_condition, ec);
+ b.consume(bytes_transferred);
+ return bytes_transferred;
+}
+
+template <typename SyncRandomAccessWriteDevice, typename Allocator>
+inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, asio::basic_streambuf<Allocator>& b)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = write_at(d, offset, b, transfer_all(), ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncRandomAccessWriteDevice, typename Allocator,
+ typename CompletionCondition>
+inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition)
+{
+ asio::error_code ec;
+ std::size_t bytes_transferred = write_at(
+ d, offset, b, completion_condition, ec);
+ asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+namespace detail
+{
+ template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+ class write_at_op
+ : detail::base_from_completion_cond<CompletionCondition>
+ {
+ public:
+ write_at_op(AsyncRandomAccessWriteDevice& device,
+ boost::uint64_t offset, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition, WriteHandler handler)
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ device_(device),
+ offset_(offset),
+ buffers_(buffers),
+ total_transferred_(0),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const asio::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ switch (start)
+ {
+ case 1:
+ buffers_.prepare(this->check_for_completion(ec, total_transferred_));
+ for (;;)
+ {
+ device_.async_write_some_at(
+ offset_ + total_transferred_, buffers_, *this);
+ return; default:
+ total_transferred_ += bytes_transferred;
+ buffers_.consume(bytes_transferred);
+ buffers_.prepare(this->check_for_completion(ec, total_transferred_));
+ if ((!ec && bytes_transferred == 0)
+ || buffers_.begin() == buffers_.end())
+ break;
+ }
+
+ handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+ }
+ }
+
+ //private:
+ AsyncRandomAccessWriteDevice& device_;
+ boost::uint64_t offset_;
+ asio::detail::consuming_buffers<
+ const_buffer, ConstBufferSequence> buffers_;
+ std::size_t total_transferred_;
+ WriteHandler handler_;
+ };
+
+ template <typename AsyncRandomAccessWriteDevice,
+ typename CompletionCondition, typename WriteHandler>
+ class write_at_op<AsyncRandomAccessWriteDevice,
+ asio::mutable_buffers_1, CompletionCondition, WriteHandler>
+ : detail::base_from_completion_cond<CompletionCondition>
+ {
+ public:
+ write_at_op(AsyncRandomAccessWriteDevice& device,
+ boost::uint64_t offset, const asio::mutable_buffers_1& buffers,
+ CompletionCondition completion_condition,
+ WriteHandler handler)
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ device_(device),
+ offset_(offset),
+ buffer_(buffers),
+ total_transferred_(0),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const asio::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ std::size_t n = 0;
+ switch (start)
+ {
+ case 1:
+ n = this->check_for_completion(ec, total_transferred_);
+ for (;;)
+ {
+ device_.async_write_some_at(offset_ + total_transferred_,
+ asio::buffer(buffer_ + total_transferred_, n), *this);
+ return; default:
+ total_transferred_ += bytes_transferred;
+ if ((!ec && bytes_transferred == 0)
+ || (n = this->check_for_completion(ec, total_transferred_)) == 0
+ || total_transferred_ == asio::buffer_size(buffer_))
+ break;
+ }
+
+ handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+ }
+ }
+
+ //private:
+ AsyncRandomAccessWriteDevice& device_;
+ boost::uint64_t offset_;
+ asio::mutable_buffer buffer_;
+ std::size_t total_transferred_;
+ WriteHandler handler_;
+ };
+
+ template <typename AsyncRandomAccessWriteDevice,
+ typename CompletionCondition, typename WriteHandler>
+ class write_at_op<AsyncRandomAccessWriteDevice, asio::const_buffers_1,
+ CompletionCondition, WriteHandler>
+ : detail::base_from_completion_cond<CompletionCondition>
+ {
+ public:
+ write_at_op(AsyncRandomAccessWriteDevice& device,
+ boost::uint64_t offset, const asio::const_buffers_1& buffers,
+ CompletionCondition completion_condition,
+ WriteHandler handler)
+ : detail::base_from_completion_cond<
+ CompletionCondition>(completion_condition),
+ device_(device),
+ offset_(offset),
+ buffer_(buffers),
+ total_transferred_(0),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const asio::error_code& ec,
+ std::size_t bytes_transferred, int start = 0)
+ {
+ std::size_t n = 0;
+ switch (start)
+ {
+ case 1:
+ n = this->check_for_completion(ec, total_transferred_);
+ for (;;)
+ {
+ device_.async_write_some_at(offset_ + total_transferred_,
+ asio::buffer(buffer_ + total_transferred_, n), *this);
+ return; default:
+ total_transferred_ += bytes_transferred;
+ if ((!ec && bytes_transferred == 0)
+ || (n = this->check_for_completion(ec, total_transferred_)) == 0
+ || total_transferred_ == asio::buffer_size(buffer_))
+ break;
+ }
+
+ handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+ }
+ }
+
+ //private:
+ AsyncRandomAccessWriteDevice& device_;
+ boost::uint64_t offset_;
+ asio::const_buffer buffer_;
+ std::size_t total_transferred_;
+ WriteHandler handler_;
+ };
+
+ template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ return asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncRandomAccessWriteDevice,
+ typename ConstBufferSequence, typename CompletionCondition,
+ typename WriteHandler>
+ inline void asio_handler_invoke(const Function& function,
+ write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+inline void async_write_at(AsyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition, WriteHandler handler)
+{
+ detail::write_at_op<AsyncRandomAccessWriteDevice,
+ ConstBufferSequence, CompletionCondition, WriteHandler>(
+ d, offset, buffers, completion_condition, handler)(
+ asio::error_code(), 0, 1);
+}
+
+template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename WriteHandler>
+inline void async_write_at(AsyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, const ConstBufferSequence& buffers,
+ WriteHandler handler)
+{
+ async_write_at(d, offset, buffers, transfer_all(), handler);
+}
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+namespace detail
+{
+ template <typename AsyncRandomAccessWriteDevice,
+ typename Allocator, typename WriteHandler>
+ class write_at_streambuf_op
+ {
+ public:
+ write_at_streambuf_op(
+ asio::basic_streambuf<Allocator>& streambuf,
+ WriteHandler handler)
+ : streambuf_(streambuf),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const asio::error_code& ec,
+ const std::size_t bytes_transferred)
+ {
+ streambuf_.consume(bytes_transferred);
+ handler_(ec, bytes_transferred);
+ }
+
+ //private:
+ asio::basic_streambuf<Allocator>& streambuf_;
+ WriteHandler handler_;
+ };
+
+ template <typename AsyncRandomAccessWriteDevice, typename Allocator,
+ typename WriteHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ write_at_streambuf_op<AsyncRandomAccessWriteDevice,
+ Allocator, WriteHandler>* this_handler)
+ {
+ return asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename AsyncRandomAccessWriteDevice, typename Allocator,
+ typename WriteHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ write_at_streambuf_op<AsyncRandomAccessWriteDevice,
+ Allocator, WriteHandler>* this_handler)
+ {
+ asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncRandomAccessWriteDevice,
+ typename Allocator, typename WriteHandler>
+ inline void asio_handler_invoke(const Function& function,
+ write_at_streambuf_op<AsyncRandomAccessWriteDevice,
+ Allocator, WriteHandler>* this_handler)
+ {
+ asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncRandomAccessWriteDevice, typename Allocator,
+ typename CompletionCondition, typename WriteHandler>
+inline void async_write_at(AsyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, WriteHandler handler)
+{
+ async_write_at(d, offset, b.data(), completion_condition,
+ detail::write_at_streambuf_op<
+ AsyncRandomAccessWriteDevice, Allocator, WriteHandler>(b, handler));
+}
+
+template <typename AsyncRandomAccessWriteDevice, typename Allocator,
+ typename WriteHandler>
+inline void async_write_at(AsyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
+ WriteHandler handler)
+{
+ async_write_at(d, offset, b, transfer_all(), handler);
+}
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IMPL_WRITE_AT_HPP
diff --git a/ext/asio/asio/io_service.hpp b/ext/asio/asio/io_service.hpp
index 62d9e54f9c..4fc3e05fb5 100644
--- a/ext/asio/asio/io_service.hpp
+++ b/ext/asio/asio/io_service.hpp
@@ -2,7 +2,7 @@
// io_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,25 +15,29 @@
# 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 <stdexcept>
#include <typeinfo>
-#include <boost/config.hpp>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error_code.hpp"
#include "asio/detail/noncopyable.hpp"
-#include "asio/detail/reactor_fwd.hpp"
#include "asio/detail/service_registry_fwd.hpp"
-#include "asio/detail/signal_init.hpp"
-#include "asio/detail/task_io_service_fwd.hpp"
-#include "asio/detail/win_iocp_io_service_fwd.hpp"
-#include "asio/detail/winsock_init.hpp"
#include "asio/detail/wrapped_handler.hpp"
+#include "asio/error_code.hpp"
+
+#if defined(ASIO_HAS_IOCP)
+# include "asio/detail/win_iocp_io_service_fwd.hpp"
+#else
+# include "asio/detail/task_io_service_fwd.hpp"
+#endif
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# include "asio/detail/winsock_init.hpp"
+#elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \
+ || defined(__osf__)
+# include "asio/detail/signal_init.hpp"
+#endif
+
+#include "asio/detail/push_options.hpp"
namespace asio {
@@ -45,7 +49,7 @@ template <typename Service> bool has_service(io_service& ios);
#if defined(ASIO_HAS_IOCP)
namespace detail { typedef win_iocp_io_service io_service_impl; }
#else
-namespace detail { typedef task_io_service<reactor> io_service_impl; }
+namespace detail { typedef task_io_service io_service_impl; }
#endif
/// Provides core I/O functionality.
@@ -196,7 +200,7 @@ public:
class strand;
/// Constructor.
- io_service();
+ ASIO_DECL io_service();
/// Constructor.
/**
@@ -205,7 +209,7 @@ public:
* @param concurrency_hint A suggestion to the implementation on how many
* threads it should allow to run simultaneously.
*/
- explicit io_service(std::size_t concurrency_hint);
+ ASIO_DECL explicit io_service(std::size_t concurrency_hint);
/// Destructor.
/**
@@ -239,7 +243,7 @@ public:
* destructor defined above destroys all handlers, causing all @c shared_ptr
* references to all connection objects to be destroyed.
*/
- ~io_service();
+ ASIO_DECL ~io_service();
/// Run the io_service object's event processing loop.
/**
@@ -265,7 +269,7 @@ public:
* The poll() function may also be used to dispatch ready handlers, but
* without blocking.
*/
- std::size_t run();
+ ASIO_DECL std::size_t run();
/// Run the io_service object's event processing loop.
/**
@@ -291,7 +295,7 @@ public:
* The poll() function may also be used to dispatch ready handlers, but
* without blocking.
*/
- std::size_t run(asio::error_code& ec);
+ ASIO_DECL std::size_t run(asio::error_code& ec);
/// Run the io_service object's event processing loop to execute at most one
/// handler.
@@ -303,7 +307,7 @@ public:
*
* @throws asio::system_error Thrown on failure.
*/
- std::size_t run_one();
+ ASIO_DECL std::size_t run_one();
/// Run the io_service object's event processing loop to execute at most one
/// handler.
@@ -315,7 +319,7 @@ public:
*
* @return The number of handlers that were executed.
*/
- std::size_t run_one(asio::error_code& ec);
+ ASIO_DECL std::size_t run_one(asio::error_code& ec);
/// Run the io_service object's event processing loop to execute ready
/// handlers.
@@ -327,7 +331,7 @@ public:
*
* @throws asio::system_error Thrown on failure.
*/
- std::size_t poll();
+ ASIO_DECL std::size_t poll();
/// Run the io_service object's event processing loop to execute ready
/// handlers.
@@ -339,7 +343,7 @@ public:
*
* @return The number of handlers that were executed.
*/
- std::size_t poll(asio::error_code& ec);
+ ASIO_DECL std::size_t poll(asio::error_code& ec);
/// Run the io_service object's event processing loop to execute one ready
/// handler.
@@ -351,7 +355,7 @@ public:
*
* @throws asio::system_error Thrown on failure.
*/
- std::size_t poll_one();
+ ASIO_DECL std::size_t poll_one();
/// Run the io_service object's event processing loop to execute one ready
/// handler.
@@ -363,7 +367,7 @@ public:
*
* @return The number of handlers that were executed.
*/
- std::size_t poll_one(asio::error_code& ec);
+ ASIO_DECL std::size_t poll_one(asio::error_code& ec);
/// Stop the io_service object's event processing loop.
/**
@@ -372,7 +376,7 @@ public:
* return as soon as possible. Subsequent calls to run(), run_one(), poll()
* or poll_one() will return immediately until reset() is called.
*/
- void stop();
+ ASIO_DECL void stop();
/// Reset the io_service in preparation for a subsequent run() invocation.
/**
@@ -385,7 +389,7 @@ public:
* This function must not be called while there are any unfinished calls to
* the run(), run_one(), poll() or poll_one() functions.
*/
- void reset();
+ ASIO_DECL void reset();
/// Request the io_service to invoke the given handler.
/**
@@ -605,10 +609,10 @@ protected:
/**
* @param owner The io_service object that owns the service.
*/
- service(asio::io_service& owner);
+ ASIO_DECL service(asio::io_service& owner);
/// Destructor.
- virtual ~service();
+ ASIO_DECL virtual ~service();
private:
/// Destroy all user-defined handler objects owned by the service.
@@ -631,10 +635,7 @@ class service_already_exists
: public std::logic_error
{
public:
- service_already_exists()
- : std::logic_error("Service already exists.")
- {
- }
+ ASIO_DECL service_already_exists();
};
/// Exception thrown when trying to add a service object to an io_service where
@@ -643,16 +644,44 @@ class invalid_service_owner
: public std::logic_error
{
public:
- invalid_service_owner()
- : std::logic_error("Invalid service owner.")
+ ASIO_DECL invalid_service_owner();
+};
+
+namespace detail {
+
+// Special derived service id type to keep classes header-file only.
+template <typename Type>
+class service_id
+ : public asio::io_service::id
+{
+};
+
+// Special service base class to keep classes header-file only.
+template <typename Type>
+class service_base
+ : public asio::io_service::service
+{
+public:
+ static asio::detail::service_id<Type> id;
+
+ // Constructor.
+ service_base(asio::io_service& io_service)
+ : asio::io_service::service(io_service)
{
}
};
-} // namespace asio
+template <typename Type>
+asio::detail::service_id<Type> service_base<Type>::id;
-#include "asio/impl/io_service.ipp"
+} // namespace detail
+} // namespace asio
#include "asio/detail/pop_options.hpp"
+#include "asio/impl/io_service.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/impl/io_service.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
#endif // ASIO_IO_SERVICE_HPP
diff --git a/ext/asio/asio/ip/address.hpp b/ext/asio/asio/ip/address.hpp
index 92ee4ae43d..47683dbda6 100644
--- a/ext/asio/asio/ip/address.hpp
+++ b/ext/asio/asio/ip/address.hpp
@@ -1,8 +1,8 @@
//
-// address.hpp
-// ~~~~~~~~~~~
+// ip/address.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,21 +15,17 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include <string>
+#include "asio/error_code.hpp"
+#include "asio/ip/address_v4.hpp"
+#include "asio/ip/address_v6.hpp"
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
#if !defined(BOOST_NO_IOSTREAM)
# include <iosfwd>
#endif // !defined(BOOST_NO_IOSTREAM)
-#include <string>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-#include "asio/error.hpp"
-#include "asio/ip/address_v4.hpp"
-#include "asio/ip/address_v6.hpp"
-#include "asio/detail/throw_error.hpp"
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace ip {
@@ -47,63 +43,27 @@ class address
{
public:
/// Default constructor.
- address()
- : type_(ipv4),
- ipv4_address_(),
- ipv6_address_()
- {
- }
+ ASIO_DECL address();
/// Construct an address from an IPv4 address.
- address(const asio::ip::address_v4& ipv4_address)
- : type_(ipv4),
- ipv4_address_(ipv4_address),
- ipv6_address_()
- {
- }
+ ASIO_DECL address(const asio::ip::address_v4& ipv4_address);
/// Construct an address from an IPv6 address.
- address(const asio::ip::address_v6& ipv6_address)
- : type_(ipv6),
- ipv4_address_(),
- ipv6_address_(ipv6_address)
- {
- }
+ ASIO_DECL address(const asio::ip::address_v6& ipv6_address);
/// Copy constructor.
- address(const address& other)
- : type_(other.type_),
- ipv4_address_(other.ipv4_address_),
- ipv6_address_(other.ipv6_address_)
- {
- }
+ ASIO_DECL address(const address& other);
/// Assign from another address.
- address& operator=(const address& other)
- {
- type_ = other.type_;
- ipv4_address_ = other.ipv4_address_;
- ipv6_address_ = other.ipv6_address_;
- return *this;
- }
+ ASIO_DECL address& operator=(const address& other);
/// Assign from an IPv4 address.
- address& operator=(const asio::ip::address_v4& ipv4_address)
- {
- type_ = ipv4;
- ipv4_address_ = ipv4_address;
- ipv6_address_ = asio::ip::address_v6();
- return *this;
- }
+ ASIO_DECL address& operator=(
+ const asio::ip::address_v4& ipv4_address);
/// Assign from an IPv6 address.
- address& operator=(const asio::ip::address_v6& ipv6_address)
- {
- type_ = ipv6;
- ipv4_address_ = asio::ip::address_v4();
- ipv6_address_ = ipv6_address;
- return *this;
- }
+ ASIO_DECL address& operator=(
+ const asio::ip::address_v6& ipv6_address);
/// Get whether the address is an IP version 4 address.
bool is_v4() const
@@ -118,127 +78,63 @@ public:
}
/// Get the address as an IP version 4 address.
- asio::ip::address_v4 to_v4() const
- {
- if (type_ != ipv4)
- {
- asio::system_error e(
- asio::error::address_family_not_supported);
- boost::throw_exception(e);
- }
- return ipv4_address_;
- }
+ ASIO_DECL asio::ip::address_v4 to_v4() const;
/// Get the address as an IP version 6 address.
- asio::ip::address_v6 to_v6() const
- {
- if (type_ != ipv6)
- {
- asio::system_error e(
- asio::error::address_family_not_supported);
- boost::throw_exception(e);
- }
- return ipv6_address_;
- }
+ ASIO_DECL asio::ip::address_v6 to_v6() const;
/// Get the address as a string in dotted decimal format.
- std::string to_string() const
- {
- if (type_ == ipv6)
- return ipv6_address_.to_string();
- return ipv4_address_.to_string();
- }
+ ASIO_DECL std::string to_string() const;
/// Get the address as a string in dotted decimal format.
- std::string to_string(asio::error_code& ec) const
- {
- if (type_ == ipv6)
- return ipv6_address_.to_string(ec);
- return ipv4_address_.to_string(ec);
- }
+ ASIO_DECL std::string to_string(asio::error_code& ec) const;
/// Create an address from an IPv4 address string in dotted decimal form,
/// or from an IPv6 address in hexadecimal notation.
- static address from_string(const char* str)
- {
- asio::error_code ec;
- address addr = from_string(str, ec);
- asio::detail::throw_error(ec);
- return addr;
- }
+ ASIO_DECL static address from_string(const char* str);
/// Create an address from an IPv4 address string in dotted decimal form,
/// or from an IPv6 address in hexadecimal notation.
- static address from_string(const char* str, asio::error_code& ec)
- {
- asio::ip::address_v6 ipv6_address =
- asio::ip::address_v6::from_string(str, ec);
- if (!ec)
- {
- address tmp;
- tmp.type_ = ipv6;
- tmp.ipv6_address_ = ipv6_address;
- return tmp;
- }
-
- asio::ip::address_v4 ipv4_address =
- asio::ip::address_v4::from_string(str, ec);
- if (!ec)
- {
- address tmp;
- tmp.type_ = ipv4;
- tmp.ipv4_address_ = ipv4_address;
- return tmp;
- }
-
- return address();
- }
+ ASIO_DECL static address from_string(
+ const char* str, asio::error_code& ec);
/// Create an address from an IPv4 address string in dotted decimal form,
/// or from an IPv6 address in hexadecimal notation.
- static address from_string(const std::string& str)
- {
- return from_string(str.c_str());
- }
+ ASIO_DECL static address from_string(const std::string& str);
/// Create an address from an IPv4 address string in dotted decimal form,
/// or from an IPv6 address in hexadecimal notation.
- static address from_string(const std::string& str,
- asio::error_code& ec)
+ ASIO_DECL static address from_string(
+ const std::string& str, asio::error_code& ec);
+
+ /// Compare two addresses for equality.
+ ASIO_DECL friend bool operator==(const address& a1, const address& a2);
+
+ /// Compare two addresses for inequality.
+ friend bool operator!=(const address& a1, const address& a2)
{
- return from_string(str.c_str(), ec);
+ return !(a1 == a2);
}
- /// Compare two addresses for equality.
- friend bool operator==(const address& a1, const address& a2)
+ /// Compare addresses for ordering.
+ ASIO_DECL friend bool operator<(const address& a1, const address& a2);
+
+ /// Compare addresses for ordering.
+ friend bool operator>(const address& a1, const address& a2)
{
- if (a1.type_ != a2.type_)
- return false;
- if (a1.type_ == ipv6)
- return a1.ipv6_address_ == a2.ipv6_address_;
- return a1.ipv4_address_ == a2.ipv4_address_;
+ return a2 < a1;
}
- /// Compare two addresses for inequality.
- friend bool operator!=(const address& a1, const address& a2)
+ /// Compare addresses for ordering.
+ friend bool operator<=(const address& a1, const address& a2)
{
- if (a1.type_ != a2.type_)
- return true;
- if (a1.type_ == ipv6)
- return a1.ipv6_address_ != a2.ipv6_address_;
- return a1.ipv4_address_ != a2.ipv4_address_;
+ return !(a2 < a1);
}
/// Compare addresses for ordering.
- friend bool operator<(const address& a1, const address& a2)
+ friend bool operator>=(const address& a1, const address& a2)
{
- if (a1.type_ < a2.type_)
- return true;
- if (a1.type_ > a2.type_)
- return false;
- if (a1.type_ == ipv6)
- return a1.ipv6_address_ < a2.ipv6_address_;
- return a1.ipv4_address_ < a2.ipv4_address_;
+ return !(a1 < a2);
}
private:
@@ -268,11 +164,7 @@ private:
*/
template <typename Elem, typename Traits>
std::basic_ostream<Elem, Traits>& operator<<(
- std::basic_ostream<Elem, Traits>& os, const address& addr)
-{
- os << addr.to_string();
- return os;
-}
+ std::basic_ostream<Elem, Traits>& os, const address& addr);
#endif // !defined(BOOST_NO_IOSTREAM)
@@ -281,4 +173,9 @@ std::basic_ostream<Elem, Traits>& operator<<(
#include "asio/detail/pop_options.hpp"
+#include "asio/ip/impl/address.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/ip/impl/address.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
#endif // ASIO_IP_ADDRESS_HPP
diff --git a/ext/asio/asio/ip/address_v4.hpp b/ext/asio/asio/ip/address_v4.hpp
index 1b495560fe..7567ef9b42 100644
--- a/ext/asio/asio/ip/address_v4.hpp
+++ b/ext/asio/asio/ip/address_v4.hpp
@@ -1,8 +1,8 @@
//
-// address_v4.hpp
-// ~~~~~~~~~~~~~~
+// ip/address_v4.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,18 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include <string>
+#include <boost/array.hpp>
+#include "asio/detail/socket_types.hpp"
+#include "asio/detail/winsock_init.hpp"
+#include "asio/error_code.hpp"
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
#if !defined(BOOST_NO_IOSTREAM)
# include <iosfwd>
#endif // !defined(BOOST_NO_IOSTREAM)
-#include <climits>
-#include <string>
-#include <stdexcept>
-#include <boost/array.hpp>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-#include "asio/error.hpp"
-#include "asio/detail/socket_ops.hpp"
-#include "asio/detail/socket_types.hpp"
-#include "asio/detail/throw_error.hpp"
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace ip {
@@ -59,34 +53,10 @@ public:
}
/// Construct an address from raw bytes.
- explicit address_v4(const bytes_type& bytes)
- {
-#if UCHAR_MAX > 0xFF
- if (bytes[0] > 0xFF || bytes[1] > 0xFF
- || bytes[2] > 0xFF || bytes[3] > 0xFF)
- {
- std::out_of_range ex("address_v4 from bytes_type");
- boost::throw_exception(ex);
- }
-#endif // UCHAR_MAX > 0xFF
-
- using namespace std; // For memcpy.
- memcpy(&addr_.s_addr, bytes.elems, 4);
- }
+ ASIO_DECL explicit address_v4(const bytes_type& bytes);
/// Construct an address from a unsigned long in host byte order.
- explicit address_v4(unsigned long addr)
- {
-#if ULONG_MAX > 0xFFFFFFFF
- if (addr > 0xFFFFFFFF)
- {
- std::out_of_range ex("address_v4 from unsigned long");
- boost::throw_exception(ex);
- }
-#endif // ULONG_MAX > 0xFFFFFFFF
-
- addr_.s_addr = asio::detail::socket_ops::host_to_network_long(addr);
- }
+ ASIO_DECL explicit address_v4(unsigned long addr);
/// Copy constructor.
address_v4(const address_v4& other)
@@ -102,96 +72,42 @@ public:
}
/// Get the address in bytes, in network byte order.
- bytes_type to_bytes() const
- {
- using namespace std; // For memcpy.
- bytes_type bytes;
- memcpy(bytes.elems, &addr_.s_addr, 4);
- return bytes;
- }
+ ASIO_DECL bytes_type to_bytes() const;
/// Get the address as an unsigned long in host byte order
- unsigned long to_ulong() const
- {
- return asio::detail::socket_ops::network_to_host_long(addr_.s_addr);
- }
+ ASIO_DECL unsigned long to_ulong() const;
/// Get the address as a string in dotted decimal format.
- std::string to_string() const
- {
- asio::error_code ec;
- std::string addr = to_string(ec);
- asio::detail::throw_error(ec);
- return addr;
- }
+ ASIO_DECL std::string to_string() const;
/// Get the address as a string in dotted decimal format.
- std::string to_string(asio::error_code& ec) const
- {
- char addr_str[asio::detail::max_addr_v4_str_len];
- const char* addr =
- asio::detail::socket_ops::inet_ntop(AF_INET, &addr_, addr_str,
- asio::detail::max_addr_v4_str_len, 0, ec);
- if (addr == 0)
- return std::string();
- return addr;
- }
+ ASIO_DECL std::string to_string(asio::error_code& ec) const;
/// Create an address from an IP address string in dotted decimal form.
- static address_v4 from_string(const char* str)
- {
- asio::error_code ec;
- address_v4 addr = from_string(str, ec);
- asio::detail::throw_error(ec);
- return addr;
- }
+ ASIO_DECL static address_v4 from_string(const char* str);
/// Create an address from an IP address string in dotted decimal form.
- static address_v4 from_string(const char* str, asio::error_code& ec)
- {
- address_v4 tmp;
- if (asio::detail::socket_ops::inet_pton(
- AF_INET, str, &tmp.addr_, 0, ec) <= 0)
- return address_v4();
- return tmp;
- }
+ ASIO_DECL static address_v4 from_string(
+ const char* str, asio::error_code& ec);
/// Create an address from an IP address string in dotted decimal form.
- static address_v4 from_string(const std::string& str)
- {
- return from_string(str.c_str());
- }
+ ASIO_DECL static address_v4 from_string(const std::string& str);
/// Create an address from an IP address string in dotted decimal form.
- static address_v4 from_string(const std::string& str,
- asio::error_code& ec)
- {
- return from_string(str.c_str(), ec);
- }
+ ASIO_DECL static address_v4 from_string(
+ const std::string& str, asio::error_code& ec);
/// Determine whether the address is a class A address.
- bool is_class_a() const
- {
- return IN_CLASSA(to_ulong());
- }
+ ASIO_DECL bool is_class_a() const;
/// Determine whether the address is a class B address.
- bool is_class_b() const
- {
- return IN_CLASSB(to_ulong());
- }
+ ASIO_DECL bool is_class_b() const;
/// Determine whether the address is a class C address.
- bool is_class_c() const
- {
- return IN_CLASSC(to_ulong());
- }
+ ASIO_DECL bool is_class_c() const;
/// Determine whether the address is a multicast address.
- bool is_multicast() const
- {
- return IN_MULTICAST(to_ulong());
- }
+ ASIO_DECL bool is_multicast() const;
/// Compare two addresses for equality.
friend bool operator==(const address_v4& a1, const address_v4& a2)
@@ -249,23 +165,12 @@ public:
/// Obtain an address object that represents the broadcast address that
/// corresponds to the specified address and netmask.
- static address_v4 broadcast(const address_v4& addr, const address_v4& mask)
- {
- return address_v4(addr.to_ulong() | ~mask.to_ulong());
- }
+ ASIO_DECL static address_v4 broadcast(
+ const address_v4& addr, const address_v4& mask);
/// Obtain the netmask that corresponds to the address, based on its address
/// class.
- static address_v4 netmask(const address_v4& addr)
- {
- if (addr.is_class_a())
- return address_v4(0xFF000000);
- if (addr.is_class_b())
- return address_v4(0xFFFF0000);
- if (addr.is_class_c())
- return address_v4(0xFFFFFF00);
- return address_v4(0xFFFFFFFF);
- }
+ ASIO_DECL static address_v4 netmask(const address_v4& addr);
private:
// The underlying IPv4 address.
@@ -288,22 +193,7 @@ private:
*/
template <typename Elem, typename Traits>
std::basic_ostream<Elem, Traits>& operator<<(
- std::basic_ostream<Elem, Traits>& os, const address_v4& addr)
-{
- asio::error_code ec;
- std::string s = addr.to_string(ec);
- if (ec)
- {
- if (os.exceptions() & std::ios::failbit)
- asio::detail::throw_error(ec);
- else
- os.setstate(std::ios_base::failbit);
- }
- else
- for (std::string::iterator i = s.begin(); i != s.end(); ++i)
- os << os.widen(*i);
- return os;
-}
+ std::basic_ostream<Elem, Traits>& os, const address_v4& addr);
#endif // !defined(BOOST_NO_IOSTREAM)
@@ -312,4 +202,9 @@ std::basic_ostream<Elem, Traits>& operator<<(
#include "asio/detail/pop_options.hpp"
+#include "asio/ip/impl/address_v4.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/ip/impl/address_v4.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
#endif // ASIO_IP_ADDRESS_V4_HPP
diff --git a/ext/asio/asio/ip/address_v6.hpp b/ext/asio/asio/ip/address_v6.hpp
index 8d2c08393d..261c6514eb 100644
--- a/ext/asio/asio/ip/address_v6.hpp
+++ b/ext/asio/asio/ip/address_v6.hpp
@@ -1,8 +1,8 @@
//
-// address_v6.hpp
-// ~~~~~~~~~~~~~~
+// ip/address_v6.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,26 +15,19 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include <string>
+#include <boost/array.hpp>
+#include "asio/detail/socket_types.hpp"
+#include "asio/detail/winsock_init.hpp"
+#include "asio/error_code.hpp"
+#include "asio/ip/address_v4.hpp"
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
#if !defined(BOOST_NO_IOSTREAM)
# include <iosfwd>
#endif // !defined(BOOST_NO_IOSTREAM)
-#include <cstring>
-#include <string>
-#include <stdexcept>
-#include <typeinfo>
-#include <boost/array.hpp>
-#include <boost/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-#include "asio/error.hpp"
-#include "asio/detail/socket_ops.hpp"
-#include "asio/detail/socket_types.hpp"
-#include "asio/detail/throw_error.hpp"
-#include "asio/ip/address_v4.hpp"
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace ip {
@@ -55,46 +48,17 @@ public:
typedef boost::array<unsigned char, 16> bytes_type;
/// Default constructor.
- address_v6()
- : scope_id_(0)
- {
- asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
- addr_ = tmp_addr;
- }
+ ASIO_DECL address_v6();
/// Construct an address from raw bytes and scope ID.
- explicit address_v6(const bytes_type& bytes, unsigned long scope_id = 0)
- : scope_id_(scope_id)
- {
-#if UCHAR_MAX > 0xFF
- for (std::size_t i = 0; i < bytes.size(); ++i)
- {
- if (bytes[i] > 0xFF)
- {
- std::out_of_range ex("address_v6 from bytes_type");
- boost::throw_exception(ex);
- }
- }
-#endif // UCHAR_MAX > 0xFF
-
- using namespace std; // For memcpy.
- memcpy(addr_.s6_addr, bytes.elems, 16);
- }
+ ASIO_DECL explicit address_v6(const bytes_type& bytes,
+ unsigned long scope_id = 0);
/// Copy constructor.
- address_v6(const address_v6& other)
- : addr_(other.addr_),
- scope_id_(other.scope_id_)
- {
- }
+ ASIO_DECL address_v6(const address_v6& other);
/// Assign from another address.
- address_v6& operator=(const address_v6& other)
- {
- addr_ = other.addr_;
- scope_id_ = other.scope_id_;
- return *this;
- }
+ ASIO_DECL address_v6& operator=(const address_v6& other);
/// The scope ID of the address.
/**
@@ -115,217 +79,80 @@ public:
}
/// Get the address in bytes, in network byte order.
- bytes_type to_bytes() const
- {
- using namespace std; // For memcpy.
- bytes_type bytes;
- memcpy(bytes.elems, addr_.s6_addr, 16);
- return bytes;
- }
+ ASIO_DECL bytes_type to_bytes() const;
/// Get the address as a string.
- std::string to_string() const
- {
- asio::error_code ec;
- std::string addr = to_string(ec);
- asio::detail::throw_error(ec);
- return addr;
- }
+ ASIO_DECL std::string to_string() const;
/// Get the address as a string.
- std::string to_string(asio::error_code& ec) const
- {
- char addr_str[asio::detail::max_addr_v6_str_len];
- const char* addr =
- asio::detail::socket_ops::inet_ntop(AF_INET6, &addr_, addr_str,
- asio::detail::max_addr_v6_str_len, scope_id_, ec);
- if (addr == 0)
- return std::string();
- return addr;
- }
+ ASIO_DECL std::string to_string(asio::error_code& ec) const;
/// Create an address from an IP address string.
- static address_v6 from_string(const char* str)
- {
- asio::error_code ec;
- address_v6 addr = from_string(str, ec);
- asio::detail::throw_error(ec);
- return addr;
- }
+ ASIO_DECL static address_v6 from_string(const char* str);
/// Create an address from an IP address string.
- static address_v6 from_string(const char* str, asio::error_code& ec)
- {
- address_v6 tmp;
- if (asio::detail::socket_ops::inet_pton(
- AF_INET6, str, &tmp.addr_, &tmp.scope_id_, ec) <= 0)
- return address_v6();
- return tmp;
- }
+ ASIO_DECL static address_v6 from_string(
+ const char* str, asio::error_code& ec);
/// Create an address from an IP address string.
- static address_v6 from_string(const std::string& str)
- {
- return from_string(str.c_str());
- }
+ ASIO_DECL static address_v6 from_string(const std::string& str);
/// Create an address from an IP address string.
- static address_v6 from_string(const std::string& str,
- asio::error_code& ec)
- {
- return from_string(str.c_str(), ec);
- }
+ ASIO_DECL static address_v6 from_string(
+ const std::string& str, asio::error_code& ec);
/// Converts an IPv4-mapped or IPv4-compatible address to an IPv4 address.
- address_v4 to_v4() const
- {
- if (!is_v4_mapped() && !is_v4_compatible())
- {
- std::bad_cast ex;
- boost::throw_exception(ex);
- }
-
- address_v4::bytes_type v4_bytes = { { addr_.s6_addr[12],
- addr_.s6_addr[13], addr_.s6_addr[14], addr_.s6_addr[15] } };
- return address_v4(v4_bytes);
- }
+ ASIO_DECL address_v4 to_v4() const;
/// Determine whether the address is a loopback address.
- bool is_loopback() const
- {
-#if defined(__BORLANDC__)
- return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)
- && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)
- && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)
- && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)
- && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)
- && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0)
- && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0)
- && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 1));
-#else
- using namespace asio::detail;
- return IN6_IS_ADDR_LOOPBACK(&addr_) != 0;
-#endif
- }
+ ASIO_DECL bool is_loopback() const;
/// Determine whether the address is unspecified.
- bool is_unspecified() const
- {
-#if defined(__BORLANDC__)
- return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)
- && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)
- && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)
- && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)
- && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)
- && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0)
- && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0)
- && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 0));
-#else
- using namespace asio::detail;
- return IN6_IS_ADDR_UNSPECIFIED(&addr_) != 0;
-#endif
- }
+ ASIO_DECL bool is_unspecified() const;
/// Determine whether the address is link local.
- bool is_link_local() const
- {
- using namespace asio::detail;
- return IN6_IS_ADDR_LINKLOCAL(&addr_) != 0;
- }
+ ASIO_DECL bool is_link_local() const;
/// Determine whether the address is site local.
- bool is_site_local() const
- {
- using namespace asio::detail;
- return IN6_IS_ADDR_SITELOCAL(&addr_) != 0;
- }
+ ASIO_DECL bool is_site_local() const;
/// Determine whether the address is a mapped IPv4 address.
- bool is_v4_mapped() const
- {
- using namespace asio::detail;
- return IN6_IS_ADDR_V4MAPPED(&addr_) != 0;
- }
+ ASIO_DECL bool is_v4_mapped() const;
/// Determine whether the address is an IPv4-compatible address.
- bool is_v4_compatible() const
- {
- using namespace asio::detail;
- return IN6_IS_ADDR_V4COMPAT(&addr_) != 0;
- }
+ ASIO_DECL bool is_v4_compatible() const;
/// Determine whether the address is a multicast address.
- bool is_multicast() const
- {
- using namespace asio::detail;
- return IN6_IS_ADDR_MULTICAST(&addr_) != 0;
- }
+ ASIO_DECL bool is_multicast() const;
/// Determine whether the address is a global multicast address.
- bool is_multicast_global() const
- {
- using namespace asio::detail;
- return IN6_IS_ADDR_MC_GLOBAL(&addr_) != 0;
- }
+ ASIO_DECL bool is_multicast_global() const;
/// Determine whether the address is a link-local multicast address.
- bool is_multicast_link_local() const
- {
- using namespace asio::detail;
- return IN6_IS_ADDR_MC_LINKLOCAL(&addr_) != 0;
- }
+ ASIO_DECL bool is_multicast_link_local() const;
/// Determine whether the address is a node-local multicast address.
- bool is_multicast_node_local() const
- {
- using namespace asio::detail;
- return IN6_IS_ADDR_MC_NODELOCAL(&addr_) != 0;
- }
+ ASIO_DECL bool is_multicast_node_local() const;
/// Determine whether the address is a org-local multicast address.
- bool is_multicast_org_local() const
- {
- using namespace asio::detail;
- return IN6_IS_ADDR_MC_ORGLOCAL(&addr_) != 0;
- }
+ ASIO_DECL bool is_multicast_org_local() const;
/// Determine whether the address is a site-local multicast address.
- bool is_multicast_site_local() const
- {
- using namespace asio::detail;
- return IN6_IS_ADDR_MC_SITELOCAL(&addr_) != 0;
- }
+ ASIO_DECL bool is_multicast_site_local() const;
/// Compare two addresses for equality.
- friend bool operator==(const address_v6& a1, const address_v6& a2)
- {
- using namespace std; // For memcmp.
- return memcmp(&a1.addr_, &a2.addr_,
- sizeof(asio::detail::in6_addr_type)) == 0
- && a1.scope_id_ == a2.scope_id_;
- }
+ ASIO_DECL friend bool operator==(
+ const address_v6& a1, const address_v6& a2);
/// Compare two addresses for inequality.
friend bool operator!=(const address_v6& a1, const address_v6& a2)
{
- using namespace std; // For memcmp.
- return memcmp(&a1.addr_, &a2.addr_,
- sizeof(asio::detail::in6_addr_type)) != 0
- || a1.scope_id_ != a2.scope_id_;
+ return !(a1 == a2);
}
/// Compare addresses for ordering.
- friend bool operator<(const address_v6& a1, const address_v6& a2)
- {
- using namespace std; // For memcmp.
- int memcmp_result = memcmp(&a1.addr_, &a2.addr_,
- sizeof(asio::detail::in6_addr_type));
- if (memcmp_result < 0)
- return true;
- if (memcmp_result > 0)
- return false;
- return a1.scope_id_ < a2.scope_id_;
- }
+ ASIO_DECL friend bool operator<(
+ const address_v6& a1, const address_v6& a2);
/// Compare addresses for ordering.
friend bool operator>(const address_v6& a1, const address_v6& a2)
@@ -352,31 +179,13 @@ public:
}
/// Obtain an address object that represents the loopback address.
- static address_v6 loopback()
- {
- address_v6 tmp;
- asio::detail::in6_addr_type tmp_addr = IN6ADDR_LOOPBACK_INIT;
- tmp.addr_ = tmp_addr;
- return tmp;
- }
+ ASIO_DECL static address_v6 loopback();
/// Create an IPv4-mapped IPv6 address.
- static address_v6 v4_mapped(const address_v4& addr)
- {
- address_v4::bytes_type v4_bytes = addr.to_bytes();
- bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF,
- v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };
- return address_v6(v6_bytes);
- }
+ ASIO_DECL static address_v6 v4_mapped(const address_v4& addr);
/// Create an IPv4-compatible IPv6 address.
- static address_v6 v4_compatible(const address_v4& addr)
- {
- address_v4::bytes_type v4_bytes = addr.to_bytes();
- bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };
- return address_v6(v6_bytes);
- }
+ ASIO_DECL static address_v6 v4_compatible(const address_v4& addr);
private:
// The underlying IPv6 address.
@@ -402,22 +211,7 @@ private:
*/
template <typename Elem, typename Traits>
std::basic_ostream<Elem, Traits>& operator<<(
- std::basic_ostream<Elem, Traits>& os, const address_v6& addr)
-{
- asio::error_code ec;
- std::string s = addr.to_string(ec);
- if (ec)
- {
- if (os.exceptions() & std::ios::failbit)
- asio::detail::throw_error(ec);
- else
- os.setstate(std::ios_base::failbit);
- }
- else
- for (std::string::iterator i = s.begin(); i != s.end(); ++i)
- os << os.widen(*i);
- return os;
-}
+ std::basic_ostream<Elem, Traits>& os, const address_v6& addr);
#endif // !defined(BOOST_NO_IOSTREAM)
@@ -426,4 +220,9 @@ std::basic_ostream<Elem, Traits>& operator<<(
#include "asio/detail/pop_options.hpp"
+#include "asio/ip/impl/address_v6.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/ip/impl/address_v6.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
#endif // ASIO_IP_ADDRESS_V6_HPP
diff --git a/ext/asio/asio/ip/basic_endpoint.hpp b/ext/asio/asio/ip/basic_endpoint.hpp
index 4ad3f682b7..5e5ef0b01c 100644
--- a/ext/asio/asio/ip/basic_endpoint.hpp
+++ b/ext/asio/asio/ip/basic_endpoint.hpp
@@ -1,8 +1,8 @@
//
-// basic_endpoint.hpp
-// ~~~~~~~~~~~~~~~~~~
+// ip/basic_endpoint.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,25 +15,15 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include "asio/ip/address.hpp"
+#include "asio/ip/detail/endpoint.hpp"
-#include "asio/detail/push_options.hpp"
-#include <boost/config.hpp>
-#include <boost/throw_exception.hpp>
-#include <boost/detail/workaround.hpp>
-#include <cstring>
#if !defined(BOOST_NO_IOSTREAM)
-# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-# include <ostream>
-# endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-# include <sstream>
+# include <iosfwd>
#endif // !defined(BOOST_NO_IOSTREAM)
-#include "asio/detail/pop_options.hpp"
-#include "asio/error.hpp"
-#include "asio/ip/address.hpp"
-#include "asio/detail/socket_ops.hpp"
-#include "asio/detail/socket_types.hpp"
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace ip {
@@ -67,11 +57,8 @@ public:
/// Default constructor.
basic_endpoint()
- : data_()
+ : impl_()
{
- data_.v4.sin_family = AF_INET;
- data_.v4.sin_port = 0;
- data_.v4.sin_addr.s_addr = INADDR_ANY;
}
/// Construct an endpoint using a port number, specified in the host's byte
@@ -91,74 +78,35 @@ public:
* @endcode
*/
basic_endpoint(const InternetProtocol& protocol, unsigned short port_num)
- : data_()
+ : impl_(protocol.family(), port_num)
{
- using namespace std; // For memcpy.
- if (protocol.family() == PF_INET)
- {
- data_.v4.sin_family = AF_INET;
- data_.v4.sin_port =
- asio::detail::socket_ops::host_to_network_short(port_num);
- data_.v4.sin_addr.s_addr = INADDR_ANY;
- }
- else
- {
- data_.v6.sin6_family = AF_INET6;
- data_.v6.sin6_port =
- asio::detail::socket_ops::host_to_network_short(port_num);
- data_.v6.sin6_flowinfo = 0;
- asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
- data_.v6.sin6_addr = tmp_addr;
- data_.v6.sin6_scope_id = 0;
- }
}
/// Construct an endpoint using a port number and an IP address. This
/// constructor may be used for accepting connections on a specific interface
/// or for making a connection to a remote endpoint.
basic_endpoint(const asio::ip::address& addr, unsigned short port_num)
- : data_()
+ : impl_(addr, port_num)
{
- using namespace std; // For memcpy.
- if (addr.is_v4())
- {
- data_.v4.sin_family = AF_INET;
- data_.v4.sin_port =
- asio::detail::socket_ops::host_to_network_short(port_num);
- data_.v4.sin_addr.s_addr =
- asio::detail::socket_ops::host_to_network_long(
- addr.to_v4().to_ulong());
- }
- else
- {
- data_.v6.sin6_family = AF_INET6;
- data_.v6.sin6_port =
- asio::detail::socket_ops::host_to_network_short(port_num);
- data_.v6.sin6_flowinfo = 0;
- asio::ip::address_v6 v6_addr = addr.to_v6();
- asio::ip::address_v6::bytes_type bytes = v6_addr.to_bytes();
- memcpy(data_.v6.sin6_addr.s6_addr, bytes.elems, 16);
- data_.v6.sin6_scope_id = v6_addr.scope_id();
- }
}
/// Copy constructor.
basic_endpoint(const basic_endpoint& other)
- : data_(other.data_)
+ : impl_(other.impl_)
{
}
/// Assign from another endpoint.
basic_endpoint& operator=(const basic_endpoint& other)
{
- data_ = other.data_;
+ impl_ = other.impl_;
return *this;
}
/// The protocol associated with the endpoint.
protocol_type protocol() const
{
- if (is_v4())
+ if (impl_.is_v4())
return InternetProtocol::v4();
return InternetProtocol::v6();
}
@@ -166,137 +114,104 @@ public:
/// Get the underlying endpoint in the native type.
data_type* data()
{
- return &data_.base;
+ return impl_.data();
}
/// Get the underlying endpoint in the native type.
const data_type* data() const
{
- return &data_.base;
+ return impl_.data();
}
/// Get the underlying size of the endpoint in the native type.
std::size_t size() const
{
- if (is_v4())
- return sizeof(asio::detail::sockaddr_in4_type);
- else
- return sizeof(asio::detail::sockaddr_in6_type);
+ return impl_.size();
}
/// Set the underlying size of the endpoint in the native type.
void resize(std::size_t size)
{
- if (size > sizeof(asio::detail::sockaddr_storage_type))
- {
- asio::system_error e(asio::error::invalid_argument);
- boost::throw_exception(e);
- }
+ impl_.resize(size);
}
/// Get the capacity of the endpoint in the native type.
std::size_t capacity() const
{
- return sizeof(asio::detail::sockaddr_storage_type);
+ return impl_.capacity();
}
/// Get the port associated with the endpoint. The port number is always in
/// the host's byte order.
unsigned short port() const
{
- if (is_v4())
- {
- return asio::detail::socket_ops::network_to_host_short(
- data_.v4.sin_port);
- }
- else
- {
- return asio::detail::socket_ops::network_to_host_short(
- data_.v6.sin6_port);
- }
+ return impl_.port();
}
/// Set the port associated with the endpoint. The port number is always in
/// the host's byte order.
void port(unsigned short port_num)
{
- if (is_v4())
- {
- data_.v4.sin_port
- = asio::detail::socket_ops::host_to_network_short(port_num);
- }
- else
- {
- data_.v6.sin6_port
- = asio::detail::socket_ops::host_to_network_short(port_num);
- }
+ impl_.port(port_num);
}
/// Get the IP address associated with the endpoint.
asio::ip::address address() const
{
- using namespace std; // For memcpy.
- if (is_v4())
- {
- return asio::ip::address_v4(
- asio::detail::socket_ops::network_to_host_long(
- data_.v4.sin_addr.s_addr));
- }
- else
- {
- asio::ip::address_v6::bytes_type bytes;
- memcpy(bytes.elems, data_.v6.sin6_addr.s6_addr, 16);
- return asio::ip::address_v6(bytes, data_.v6.sin6_scope_id);
- }
+ return impl_.address();
}
/// Set the IP address associated with the endpoint.
void address(const asio::ip::address& addr)
{
- basic_endpoint<InternetProtocol> tmp_endpoint(addr, port());
- data_ = tmp_endpoint.data_;
+ impl_.address(addr);
}
/// Compare two endpoints for equality.
friend bool operator==(const basic_endpoint<InternetProtocol>& e1,
const basic_endpoint<InternetProtocol>& e2)
{
- return e1.address() == e2.address() && e1.port() == e2.port();
+ return e1.impl_ == e2.impl_;
}
/// Compare two endpoints for inequality.
friend bool operator!=(const basic_endpoint<InternetProtocol>& e1,
const basic_endpoint<InternetProtocol>& e2)
{
- return e1.address() != e2.address() || e1.port() != e2.port();
+ return !(e1 == e2);
}
/// Compare endpoints for ordering.
friend bool operator<(const basic_endpoint<InternetProtocol>& e1,
const basic_endpoint<InternetProtocol>& e2)
{
- if (e1.address() < e2.address())
- return true;
- if (e1.address() != e2.address())
- return false;
- return e1.port() < e2.port();
+ return e1.impl_ < e2.impl_;
}
-private:
- // Helper function to determine whether the endpoint is IPv4.
- bool is_v4() const
+ /// Compare endpoints for ordering.
+ friend bool operator>(const basic_endpoint<InternetProtocol>& e1,
+ const basic_endpoint<InternetProtocol>& e2)
+ {
+ return e2.impl_ < e1.impl_;
+ }
+
+ /// Compare endpoints for ordering.
+ friend bool operator<=(const basic_endpoint<InternetProtocol>& e1,
+ const basic_endpoint<InternetProtocol>& e2)
{
- return data_.base.sa_family == AF_INET;
+ return !(e2 < e1);
}
- // The underlying IP socket address.
- union data_union
+ /// Compare endpoints for ordering.
+ friend bool operator>=(const basic_endpoint<InternetProtocol>& e1,
+ const basic_endpoint<InternetProtocol>& e2)
{
- asio::detail::socket_addr_type base;
- asio::detail::sockaddr_storage_type storage;
- asio::detail::sockaddr_in4_type v4;
- asio::detail::sockaddr_in6_type v6;
- } data_;
+ return !(e1 < e2);
+ }
+
+private:
+ // The underlying IP endpoint.
+ asio::ip::detail::endpoint impl_;
};
#if !defined(BOOST_NO_IOSTREAM)
@@ -313,64 +228,10 @@ private:
*
* @relates asio::ip::basic_endpoint
*/
-#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-template <typename InternetProtocol>
-std::ostream& operator<<(std::ostream& os,
- const basic_endpoint<InternetProtocol>& endpoint)
-{
- const address& addr = endpoint.address();
- asio::error_code ec;
- std::string a = addr.to_string(ec);
- if (ec)
- {
- if (os.exceptions() & std::ios::failbit)
- asio::detail::throw_error(ec);
- else
- os.setstate(std::ios_base::failbit);
- }
- else
- {
- std::ostringstream tmp_os;
- tmp_os.imbue(std::locale::classic());
- if (addr.is_v4())
- tmp_os << a;
- else
- tmp_os << '[' << a << ']';
- tmp_os << ':' << endpoint.port();
- os << tmp_os.str();
- }
- return os;
-}
-#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
template <typename Elem, typename Traits, typename InternetProtocol>
std::basic_ostream<Elem, Traits>& operator<<(
std::basic_ostream<Elem, Traits>& os,
- const basic_endpoint<InternetProtocol>& endpoint)
-{
- const address& addr = endpoint.address();
- asio::error_code ec;
- std::string a = addr.to_string(ec);
- if (ec)
- {
- if (os.exceptions() & std::ios::failbit)
- asio::detail::throw_error(ec);
- else
- os.setstate(std::ios_base::failbit);
- }
- else
- {
- std::ostringstream tmp_os;
- tmp_os.imbue(std::locale::classic());
- if (addr.is_v4())
- tmp_os << a;
- else
- tmp_os << '[' << a << ']';
- tmp_os << ':' << endpoint.port();
- os << tmp_os.str();
- }
- return os;
-}
-#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ const basic_endpoint<InternetProtocol>& endpoint);
#endif // !defined(BOOST_NO_IOSTREAM)
@@ -379,4 +240,6 @@ std::basic_ostream<Elem, Traits>& operator<<(
#include "asio/detail/pop_options.hpp"
+#include "asio/ip/impl/basic_endpoint.hpp"
+
#endif // ASIO_IP_BASIC_ENDPOINT_HPP
diff --git a/ext/asio/asio/ip/basic_resolver.hpp b/ext/asio/asio/ip/basic_resolver.hpp
index 43a37af392..c8847e15e6 100644
--- a/ext/asio/asio/ip/basic_resolver.hpp
+++ b/ext/asio/asio/ip/basic_resolver.hpp
@@ -1,8 +1,8 @@
//
-// basic_resolver.hpp
-// ~~~~~~~~~~~~~~~~~~
+// ip/basic_resolver.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/detail/throw_error.hpp"
#include "asio/error.hpp"
#include "asio/ip/basic_resolver_iterator.hpp"
#include "asio/ip/basic_resolver_query.hpp"
#include "asio/ip/resolver_service.hpp"
-#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace ip {
diff --git a/ext/asio/asio/ip/basic_resolver_entry.hpp b/ext/asio/asio/ip/basic_resolver_entry.hpp
index 09b144b117..4117b7bc65 100644
--- a/ext/asio/asio/ip/basic_resolver_entry.hpp
+++ b/ext/asio/asio/ip/basic_resolver_entry.hpp
@@ -1,8 +1,8 @@
//
-// basic_resolver_entry.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~
+// ip/basic_resolver_entry.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,10 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include <string>
#include "asio/detail/push_options.hpp"
-#include <string>
-#include "asio/detail/pop_options.hpp"
namespace asio {
namespace ip {
diff --git a/ext/asio/asio/ip/basic_resolver_iterator.hpp b/ext/asio/asio/ip/basic_resolver_iterator.hpp
index 1982d62512..033b7e0b7d 100644
--- a/ext/asio/asio/ip/basic_resolver_iterator.hpp
+++ b/ext/asio/asio/ip/basic_resolver_iterator.hpp
@@ -1,8 +1,8 @@
//
-// basic_resolver_iterator.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// ip/basic_resolver_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,18 @@
# 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/iterator.hpp>
-#include <boost/shared_ptr.hpp>
#include <cstring>
#include <string>
#include <vector>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/shared_ptr.hpp"
#include "asio/detail/socket_ops.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/ip/basic_resolver_entry.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace ip {
@@ -176,7 +174,7 @@ private:
}
typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type;
- boost::shared_ptr<values_type> values_;
+ asio::detail::shared_ptr<values_type> values_;
std::size_t index_;
};
diff --git a/ext/asio/asio/ip/basic_resolver_query.hpp b/ext/asio/asio/ip/basic_resolver_query.hpp
index 3cbb335ca5..22ab643bb4 100644
--- a/ext/asio/asio/ip/basic_resolver_query.hpp
+++ b/ext/asio/asio/ip/basic_resolver_query.hpp
@@ -1,8 +1,8 @@
//
-// basic_resolver_query.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~
+// ip/basic_resolver_query.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/config.hpp"
#include <string>
-#include "asio/detail/pop_options.hpp"
-
#include "asio/detail/socket_ops.hpp"
#include "asio/ip/resolver_query_base.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace ip {
diff --git a/ext/asio/asio/ip/detail/endpoint.hpp b/ext/asio/asio/ip/detail/endpoint.hpp
new file mode 100644
index 0000000000..fbea71e01b
--- /dev/null
+++ b/ext/asio/asio/ip/detail/endpoint.hpp
@@ -0,0 +1,140 @@
+//
+// ip/detail/endpoint.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_IP_DETAIL_ENDPOINT_HPP
+#define ASIO_IP_DETAIL_ENDPOINT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <string>
+#include "asio/detail/socket_types.hpp"
+#include "asio/detail/winsock_init.hpp"
+#include "asio/error_code.hpp"
+#include "asio/ip/address.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+namespace detail {
+
+// Helper class for implementating an IP endpoint.
+class endpoint
+{
+public:
+ // Default constructor.
+ ASIO_DECL endpoint();
+
+ // Construct an endpoint using a family and port number.
+ ASIO_DECL endpoint(int family, unsigned short port_num);
+
+ // Construct an endpoint using an address and port number.
+ ASIO_DECL endpoint(const asio::ip::address& addr,
+ unsigned short port_num);
+
+ // Copy constructor.
+ endpoint(const endpoint& other)
+ : data_(other.data_)
+ {
+ }
+
+ // Assign from another endpoint.
+ endpoint& operator=(const endpoint& other)
+ {
+ data_ = other.data_;
+ return *this;
+ }
+
+ // Get the underlying endpoint in the native type.
+ asio::detail::socket_addr_type* data()
+ {
+ return &data_.base;
+ }
+
+ // Get the underlying endpoint in the native type.
+ const asio::detail::socket_addr_type* data() const
+ {
+ return &data_.base;
+ }
+
+ // Get the underlying size of the endpoint in the native type.
+ std::size_t size() const
+ {
+ if (is_v4())
+ return sizeof(asio::detail::sockaddr_in4_type);
+ else
+ return sizeof(asio::detail::sockaddr_in6_type);
+ }
+
+ // Set the underlying size of the endpoint in the native type.
+ ASIO_DECL void resize(std::size_t size);
+
+ // Get the capacity of the endpoint in the native type.
+ std::size_t capacity() const
+ {
+ return sizeof(asio::detail::sockaddr_storage_type);
+ }
+
+ // Get the port associated with the endpoint.
+ ASIO_DECL unsigned short port() const;
+
+ // Set the port associated with the endpoint.
+ ASIO_DECL void port(unsigned short port_num);
+
+ // Get the IP address associated with the endpoint.
+ ASIO_DECL asio::ip::address address() const;
+
+ // Set the IP address associated with the endpoint.
+ ASIO_DECL void address(const asio::ip::address& addr);
+
+ // Compare two endpoints for equality.
+ ASIO_DECL friend bool operator==(
+ const endpoint& e1, const endpoint& e2);
+
+ // Compare endpoints for ordering.
+ ASIO_DECL friend bool operator<(
+ const endpoint& e1, const endpoint& e2);
+
+ // Determine whether the endpoint is IPv4.
+ bool is_v4() const
+ {
+ return data_.base.sa_family == AF_INET;
+ }
+
+#if !defined(BOOST_NO_IOSTREAM)
+ // Convert to a string.
+ ASIO_DECL std::string to_string(asio::error_code& ec) const;
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+private:
+ // The underlying IP socket address.
+ union data_union
+ {
+ asio::detail::socket_addr_type base;
+ asio::detail::sockaddr_storage_type storage;
+ asio::detail::sockaddr_in4_type v4;
+ asio::detail::sockaddr_in6_type v6;
+ } data_;
+};
+
+} // namespace detail
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/ip/detail/impl/endpoint.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // ASIO_IP_DETAIL_ENDPOINT_HPP
diff --git a/ext/asio/asio/ip/detail/impl/endpoint.ipp b/ext/asio/asio/ip/detail/impl/endpoint.ipp
new file mode 100644
index 0000000000..17efb5cc19
--- /dev/null
+++ b/ext/asio/asio/ip/detail/impl/endpoint.ipp
@@ -0,0 +1,191 @@
+//
+// ip/detail/impl/endpoint.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_IP_DETAIL_IMPL_ENDPOINT_IPP
+#define ASIO_IP_DETAIL_IMPL_ENDPOINT_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <cstring>
+#if !defined(BOOST_NO_IOSTREAM)
+# include <sstream>
+#endif // !defined(BOOST_NO_IOSTREAM)
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+#include "asio/ip/detail/endpoint.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+namespace detail {
+
+endpoint::endpoint()
+ : data_()
+{
+ data_.v4.sin_family = AF_INET;
+ data_.v4.sin_port = 0;
+ data_.v4.sin_addr.s_addr = INADDR_ANY;
+}
+
+endpoint::endpoint(int family, unsigned short port_num)
+ : data_()
+{
+ using namespace std; // For memcpy.
+ if (family == PF_INET)
+ {
+ data_.v4.sin_family = AF_INET;
+ data_.v4.sin_port =
+ asio::detail::socket_ops::host_to_network_short(port_num);
+ data_.v4.sin_addr.s_addr = INADDR_ANY;
+ }
+ else
+ {
+ data_.v6.sin6_family = AF_INET6;
+ data_.v6.sin6_port =
+ asio::detail::socket_ops::host_to_network_short(port_num);
+ data_.v6.sin6_flowinfo = 0;
+ asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
+ data_.v6.sin6_addr = tmp_addr;
+ data_.v6.sin6_scope_id = 0;
+ }
+}
+
+endpoint::endpoint(const asio::ip::address& addr,
+ unsigned short port_num)
+ : data_()
+{
+ using namespace std; // For memcpy.
+ if (addr.is_v4())
+ {
+ data_.v4.sin_family = AF_INET;
+ data_.v4.sin_port =
+ asio::detail::socket_ops::host_to_network_short(port_num);
+ data_.v4.sin_addr.s_addr =
+ asio::detail::socket_ops::host_to_network_long(
+ addr.to_v4().to_ulong());
+ }
+ else
+ {
+ data_.v6.sin6_family = AF_INET6;
+ data_.v6.sin6_port =
+ asio::detail::socket_ops::host_to_network_short(port_num);
+ data_.v6.sin6_flowinfo = 0;
+ asio::ip::address_v6 v6_addr = addr.to_v6();
+ asio::ip::address_v6::bytes_type bytes = v6_addr.to_bytes();
+ memcpy(data_.v6.sin6_addr.s6_addr, bytes.elems, 16);
+ data_.v6.sin6_scope_id = v6_addr.scope_id();
+ }
+}
+
+void endpoint::resize(std::size_t size)
+{
+ if (size > sizeof(asio::detail::sockaddr_storage_type))
+ {
+ asio::error_code ec(asio::error::invalid_argument);
+ asio::detail::throw_error(ec);
+ }
+}
+
+unsigned short endpoint::port() const
+{
+ if (is_v4())
+ {
+ return asio::detail::socket_ops::network_to_host_short(
+ data_.v4.sin_port);
+ }
+ else
+ {
+ return asio::detail::socket_ops::network_to_host_short(
+ data_.v6.sin6_port);
+ }
+}
+
+void endpoint::port(unsigned short port_num)
+{
+ if (is_v4())
+ {
+ data_.v4.sin_port
+ = asio::detail::socket_ops::host_to_network_short(port_num);
+ }
+ else
+ {
+ data_.v6.sin6_port
+ = asio::detail::socket_ops::host_to_network_short(port_num);
+ }
+}
+
+asio::ip::address endpoint::address() const
+{
+ using namespace std; // For memcpy.
+ if (is_v4())
+ {
+ return asio::ip::address_v4(
+ asio::detail::socket_ops::network_to_host_long(
+ data_.v4.sin_addr.s_addr));
+ }
+ else
+ {
+ asio::ip::address_v6::bytes_type bytes;
+ memcpy(bytes.elems, data_.v6.sin6_addr.s6_addr, 16);
+ return asio::ip::address_v6(bytes, data_.v6.sin6_scope_id);
+ }
+}
+
+void endpoint::address(const asio::ip::address& addr)
+{
+ endpoint tmp_endpoint(addr, port());
+ data_ = tmp_endpoint.data_;
+}
+
+bool operator==(const endpoint& e1, const endpoint& e2)
+{
+ return e1.address() == e2.address() && e1.port() == e2.port();
+}
+
+bool operator<(const endpoint& e1, const endpoint& e2)
+{
+ if (e1.address() < e2.address())
+ return true;
+ if (e1.address() != e2.address())
+ return false;
+ return e1.port() < e2.port();
+}
+
+#if !defined(BOOST_NO_IOSTREAM)
+std::string endpoint::to_string(asio::error_code& ec) const
+{
+ std::string a = address().to_string(ec);
+ if (ec)
+ return std::string();
+
+ std::ostringstream tmp_os;
+ tmp_os.imbue(std::locale::classic());
+ if (is_v4())
+ tmp_os << a;
+ else
+ tmp_os << '[' << a << ']';
+ tmp_os << ':' << port();
+
+ return tmp_os.str();
+}
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+} // namespace detail
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IP_DETAIL_IMPL_ENDPOINT_IPP
diff --git a/ext/asio/asio/ip/detail/socket_option.hpp b/ext/asio/asio/ip/detail/socket_option.hpp
index 00045f86d5..e370b113b2 100644
--- a/ext/asio/asio/ip/detail/socket_option.hpp
+++ b/ext/asio/asio/ip/detail/socket_option.hpp
@@ -1,8 +1,8 @@
//
-// socket_option.hpp
-// ~~~~~~~~~~~~~~~~~
+// detail/socket_option.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,15 @@
# 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/throw_exception.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/ip/address.hpp"
#include "asio/detail/socket_ops.hpp"
#include "asio/detail/socket_types.hpp"
+#include "asio/ip/address.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace ip {
diff --git a/ext/asio/asio/ip/host_name.hpp b/ext/asio/asio/ip/host_name.hpp
index f24ce1a223..8bfaae94c1 100644
--- a/ext/asio/asio/ip/host_name.hpp
+++ b/ext/asio/asio/ip/host_name.hpp
@@ -1,8 +1,8 @@
//
-// host_name.hpp
-// ~~~~~~~~~~~~~
+// ip/host_name.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,48 +15,28 @@
# 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 <string>
-#include "asio/detail/pop_options.hpp"
+#include "asio/error_code.hpp"
-#include "asio/error.hpp"
-#include "asio/detail/socket_ops.hpp"
-#include "asio/detail/throw_error.hpp"
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace ip {
/// Get the current host name.
-std::string host_name();
+ASIO_DECL std::string host_name();
/// Get the current host name.
-std::string host_name(asio::error_code& ec);
-
-inline std::string host_name()
-{
- char name[1024];
- asio::error_code ec;
- if (asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0)
- {
- asio::detail::throw_error(ec);
- return std::string();
- }
- return std::string(name);
-}
-
-inline std::string host_name(asio::error_code& ec)
-{
- char name[1024];
- if (asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0)
- return std::string();
- return std::string(name);
-}
+ASIO_DECL std::string host_name(asio::error_code& ec);
} // namespace ip
} // namespace asio
#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/ip/impl/host_name.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
#endif // ASIO_IP_HOST_NAME_HPP
diff --git a/ext/asio/asio/ip/icmp.hpp b/ext/asio/asio/ip/icmp.hpp
index d76b4d1a6d..59df5b027f 100644
--- a/ext/asio/asio/ip/icmp.hpp
+++ b/ext/asio/asio/ip/icmp.hpp
@@ -1,8 +1,8 @@
//
-// icmp.hpp
-// ~~~~~~~~
+// ip/icmp.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/detail/socket_types.hpp"
#include "asio/basic_raw_socket.hpp"
#include "asio/ip/basic_endpoint.hpp"
#include "asio/ip/basic_resolver.hpp"
#include "asio/ip/basic_resolver_iterator.hpp"
#include "asio/ip/basic_resolver_query.hpp"
-#include "asio/detail/socket_types.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace ip {
diff --git a/ext/asio/asio/ip/impl/address.hpp b/ext/asio/asio/ip/impl/address.hpp
new file mode 100644
index 0000000000..0983d24684
--- /dev/null
+++ b/ext/asio/asio/ip/impl/address.hpp
@@ -0,0 +1,53 @@
+//
+// ip/impl/address.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_IP_IMPL_ADDRESS_HPP
+#define ASIO_IP_IMPL_ADDRESS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+
+template <typename Elem, typename Traits>
+std::basic_ostream<Elem, Traits>& operator<<(
+ std::basic_ostream<Elem, Traits>& os, const address& addr)
+{
+ asio::error_code ec;
+ std::string s = addr.to_string(ec);
+ if (ec)
+ {
+ if (os.exceptions() & std::basic_ostream<Elem, Traits>::failbit)
+ asio::detail::throw_error(ec);
+ else
+ os.setstate(std::basic_ostream<Elem, Traits>::failbit);
+ }
+ else
+ for (std::string::iterator i = s.begin(); i != s.end(); ++i)
+ os << os.widen(*i);
+ return os;
+}
+
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+#endif // ASIO_IP_IMPL_ADDRESS_HPP
diff --git a/ext/asio/asio/ip/impl/address.ipp b/ext/asio/asio/ip/impl/address.ipp
new file mode 100644
index 0000000000..d51fa1a44e
--- /dev/null
+++ b/ext/asio/asio/ip/impl/address.ipp
@@ -0,0 +1,186 @@
+//
+// ip/impl/address.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_IP_IMPL_ADDRESS_IPP
+#define ASIO_IP_IMPL_ADDRESS_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <typeinfo>
+#include <boost/throw_exception.hpp>
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+#include "asio/ip/address.hpp"
+#include "asio/system_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+
+address::address()
+ : type_(ipv4),
+ ipv4_address_(),
+ ipv6_address_()
+{
+}
+
+address::address(const asio::ip::address_v4& ipv4_address)
+ : type_(ipv4),
+ ipv4_address_(ipv4_address),
+ ipv6_address_()
+{
+}
+
+address::address(const asio::ip::address_v6& ipv6_address)
+ : type_(ipv6),
+ ipv4_address_(),
+ ipv6_address_(ipv6_address)
+{
+}
+
+address::address(const address& other)
+ : type_(other.type_),
+ ipv4_address_(other.ipv4_address_),
+ ipv6_address_(other.ipv6_address_)
+{
+}
+
+address& address::operator=(const address& other)
+{
+ type_ = other.type_;
+ ipv4_address_ = other.ipv4_address_;
+ ipv6_address_ = other.ipv6_address_;
+ return *this;
+}
+
+address& address::operator=(const asio::ip::address_v4& ipv4_address)
+{
+ type_ = ipv4;
+ ipv4_address_ = ipv4_address;
+ ipv6_address_ = asio::ip::address_v6();
+ return *this;
+}
+
+address& address::operator=(const asio::ip::address_v6& ipv6_address)
+{
+ type_ = ipv6;
+ ipv4_address_ = asio::ip::address_v4();
+ ipv6_address_ = ipv6_address;
+ return *this;
+}
+
+asio::ip::address_v4 address::to_v4() const
+{
+ if (type_ != ipv4)
+ {
+ std::bad_cast ex;
+ boost::throw_exception(ex);
+ }
+ return ipv4_address_;
+}
+
+asio::ip::address_v6 address::to_v6() const
+{
+ if (type_ != ipv6)
+ {
+ std::bad_cast ex;
+ boost::throw_exception(ex);
+ }
+ return ipv6_address_;
+}
+
+std::string address::to_string() const
+{
+ if (type_ == ipv6)
+ return ipv6_address_.to_string();
+ return ipv4_address_.to_string();
+}
+
+std::string address::to_string(asio::error_code& ec) const
+{
+ if (type_ == ipv6)
+ return ipv6_address_.to_string(ec);
+ return ipv4_address_.to_string(ec);
+}
+
+address address::from_string(const char* str)
+{
+ asio::error_code ec;
+ address addr = from_string(str, ec);
+ asio::detail::throw_error(ec);
+ return addr;
+}
+
+address address::from_string(const char* str, asio::error_code& ec)
+{
+ asio::ip::address_v6 ipv6_address =
+ asio::ip::address_v6::from_string(str, ec);
+ if (!ec)
+ {
+ address tmp;
+ tmp.type_ = ipv6;
+ tmp.ipv6_address_ = ipv6_address;
+ return tmp;
+ }
+
+ asio::ip::address_v4 ipv4_address =
+ asio::ip::address_v4::from_string(str, ec);
+ if (!ec)
+ {
+ address tmp;
+ tmp.type_ = ipv4;
+ tmp.ipv4_address_ = ipv4_address;
+ return tmp;
+ }
+
+ return address();
+}
+
+address address::from_string(const std::string& str)
+{
+ return from_string(str.c_str());
+}
+
+address address::from_string(const std::string& str,
+ asio::error_code& ec)
+{
+ return from_string(str.c_str(), ec);
+}
+
+bool operator==(const address& a1, const address& a2)
+{
+ if (a1.type_ != a2.type_)
+ return false;
+ if (a1.type_ == address::ipv6)
+ return a1.ipv6_address_ == a2.ipv6_address_;
+ return a1.ipv4_address_ == a2.ipv4_address_;
+}
+
+bool operator<(const address& a1, const address& a2)
+{
+ if (a1.type_ < a2.type_)
+ return true;
+ if (a1.type_ > a2.type_)
+ return false;
+ if (a1.type_ == address::ipv6)
+ return a1.ipv6_address_ < a2.ipv6_address_;
+ return a1.ipv4_address_ < a2.ipv4_address_;
+}
+
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IP_IMPL_ADDRESS_IPP
diff --git a/ext/asio/asio/ip/impl/address_v4.hpp b/ext/asio/asio/ip/impl/address_v4.hpp
new file mode 100644
index 0000000000..bbe088211b
--- /dev/null
+++ b/ext/asio/asio/ip/impl/address_v4.hpp
@@ -0,0 +1,53 @@
+//
+// ip/impl/address_v4.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_IP_IMPL_ADDRESS_V4_HPP
+#define ASIO_IP_IMPL_ADDRESS_V4_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+
+template <typename Elem, typename Traits>
+std::basic_ostream<Elem, Traits>& operator<<(
+ std::basic_ostream<Elem, Traits>& os, const address_v4& addr)
+{
+ asio::error_code ec;
+ std::string s = addr.to_string(ec);
+ if (ec)
+ {
+ if (os.exceptions() & std::basic_ostream<Elem, Traits>::failbit)
+ asio::detail::throw_error(ec);
+ else
+ os.setstate(std::basic_ostream<Elem, Traits>::failbit);
+ }
+ else
+ for (std::string::iterator i = s.begin(); i != s.end(); ++i)
+ os << os.widen(*i);
+ return os;
+}
+
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+#endif // ASIO_IP_IMPL_ADDRESS_V4_HPP
diff --git a/ext/asio/asio/ip/impl/address_v4.ipp b/ext/asio/asio/ip/impl/address_v4.ipp
new file mode 100644
index 0000000000..b0e1c31546
--- /dev/null
+++ b/ext/asio/asio/ip/impl/address_v4.ipp
@@ -0,0 +1,162 @@
+//
+// ip/impl/address_v4.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_IP_IMPL_ADDRESS_V4_IPP
+#define ASIO_IP_IMPL_ADDRESS_V4_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <climits>
+#include <stdexcept>
+#include <boost/throw_exception.hpp>
+#include "asio/error.hpp"
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/ip/address_v4.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+
+address_v4::address_v4(const address_v4::bytes_type& bytes)
+{
+#if UCHAR_MAX > 0xFF
+ if (bytes[0] > 0xFF || bytes[1] > 0xFF
+ || bytes[2] > 0xFF || bytes[3] > 0xFF)
+ {
+ std::out_of_range ex("address_v4 from bytes_type");
+ boost::throw_exception(ex);
+ }
+#endif // UCHAR_MAX > 0xFF
+
+ using namespace std; // For memcpy.
+ memcpy(&addr_.s_addr, bytes.elems, 4);
+}
+
+address_v4::address_v4(unsigned long addr)
+{
+#if ULONG_MAX > 0xFFFFFFFF
+ if (addr > 0xFFFFFFFF)
+ {
+ std::out_of_range ex("address_v4 from unsigned long");
+ boost::throw_exception(ex);
+ }
+#endif // ULONG_MAX > 0xFFFFFFFF
+
+ addr_.s_addr = asio::detail::socket_ops::host_to_network_long(addr);
+}
+
+address_v4::bytes_type address_v4::to_bytes() const
+{
+ using namespace std; // For memcpy.
+ bytes_type bytes;
+ memcpy(bytes.elems, &addr_.s_addr, 4);
+ return bytes;
+}
+
+unsigned long address_v4::to_ulong() const
+{
+ return asio::detail::socket_ops::network_to_host_long(addr_.s_addr);
+}
+
+std::string address_v4::to_string() const
+{
+ asio::error_code ec;
+ std::string addr = to_string(ec);
+ asio::detail::throw_error(ec);
+ return addr;
+}
+
+std::string address_v4::to_string(asio::error_code& ec) const
+{
+ char addr_str[asio::detail::max_addr_v4_str_len];
+ const char* addr =
+ asio::detail::socket_ops::inet_ntop(AF_INET, &addr_, addr_str,
+ asio::detail::max_addr_v4_str_len, 0, ec);
+ if (addr == 0)
+ return std::string();
+ return addr;
+}
+
+address_v4 address_v4::from_string(const char* str)
+{
+ asio::error_code ec;
+ address_v4 addr = from_string(str, ec);
+ asio::detail::throw_error(ec);
+ return addr;
+}
+
+address_v4 address_v4::from_string(
+ const char* str, asio::error_code& ec)
+{
+ address_v4 tmp;
+ if (asio::detail::socket_ops::inet_pton(
+ AF_INET, str, &tmp.addr_, 0, ec) <= 0)
+ return address_v4();
+ return tmp;
+}
+
+address_v4 address_v4::from_string(const std::string& str)
+{
+ return from_string(str.c_str());
+}
+
+address_v4 address_v4::from_string(
+ const std::string& str, asio::error_code& ec)
+{
+ return from_string(str.c_str(), ec);
+}
+
+bool address_v4::is_class_a() const
+{
+ return IN_CLASSA(to_ulong());
+}
+
+bool address_v4::is_class_b() const
+{
+ return IN_CLASSB(to_ulong());
+}
+
+bool address_v4::is_class_c() const
+{
+ return IN_CLASSC(to_ulong());
+}
+
+bool address_v4::is_multicast() const
+{
+ return IN_MULTICAST(to_ulong());
+}
+
+address_v4 address_v4::broadcast(const address_v4& addr, const address_v4& mask)
+{
+ return address_v4(addr.to_ulong() | (mask.to_ulong() ^ 0xFFFFFFFF));
+}
+
+address_v4 address_v4::netmask(const address_v4& addr)
+{
+ if (addr.is_class_a())
+ return address_v4(0xFF000000);
+ if (addr.is_class_b())
+ return address_v4(0xFFFF0000);
+ if (addr.is_class_c())
+ return address_v4(0xFFFFFF00);
+ return address_v4(0xFFFFFFFF);
+}
+
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IP_IMPL_ADDRESS_V4_IPP
diff --git a/ext/asio/asio/ip/impl/address_v6.hpp b/ext/asio/asio/ip/impl/address_v6.hpp
new file mode 100644
index 0000000000..796a505c0a
--- /dev/null
+++ b/ext/asio/asio/ip/impl/address_v6.hpp
@@ -0,0 +1,53 @@
+//
+// ip/impl/address_v6.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_IP_IMPL_ADDRESS_V6_HPP
+#define ASIO_IP_IMPL_ADDRESS_V6_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+
+template <typename Elem, typename Traits>
+std::basic_ostream<Elem, Traits>& operator<<(
+ std::basic_ostream<Elem, Traits>& os, const address_v6& addr)
+{
+ asio::error_code ec;
+ std::string s = addr.to_string(ec);
+ if (ec)
+ {
+ if (os.exceptions() & std::basic_ostream<Elem, Traits>::failbit)
+ asio::detail::throw_error(ec);
+ else
+ os.setstate(std::basic_ostream<Elem, Traits>::failbit);
+ }
+ else
+ for (std::string::iterator i = s.begin(); i != s.end(); ++i)
+ os << os.widen(*i);
+ return os;
+}
+
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+#endif // ASIO_IP_IMPL_ADDRESS_V6_HPP
diff --git a/ext/asio/asio/ip/impl/address_v6.ipp b/ext/asio/asio/ip/impl/address_v6.ipp
new file mode 100644
index 0000000000..c49e7ab7bf
--- /dev/null
+++ b/ext/asio/asio/ip/impl/address_v6.ipp
@@ -0,0 +1,284 @@
+//
+// ip/impl/address_v6.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_IP_IMPL_ADDRESS_V6_IPP
+#define ASIO_IP_IMPL_ADDRESS_V6_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include <cstring>
+#include <stdexcept>
+#include <typeinfo>
+#include <boost/throw_exception.hpp>
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+#include "asio/ip/address_v6.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+
+address_v6::address_v6()
+ : scope_id_(0)
+{
+ asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
+ addr_ = tmp_addr;
+}
+
+address_v6::address_v6(const address_v6::bytes_type& bytes,
+ unsigned long scope_id)
+ : scope_id_(scope_id)
+{
+#if UCHAR_MAX > 0xFF
+ for (std::size_t i = 0; i < bytes.size(); ++i)
+ {
+ if (bytes[i] > 0xFF)
+ {
+ std::out_of_range ex("address_v6 from bytes_type");
+ boost::throw_exception(ex);
+ }
+ }
+#endif // UCHAR_MAX > 0xFF
+
+ using namespace std; // For memcpy.
+ memcpy(addr_.s6_addr, bytes.elems, 16);
+}
+
+address_v6::address_v6(const address_v6& other)
+ : addr_(other.addr_),
+ scope_id_(other.scope_id_)
+{
+}
+
+address_v6& address_v6::operator=(const address_v6& other)
+{
+ addr_ = other.addr_;
+ scope_id_ = other.scope_id_;
+ return *this;
+}
+
+address_v6::bytes_type address_v6::to_bytes() const
+{
+ using namespace std; // For memcpy.
+ bytes_type bytes;
+ memcpy(bytes.elems, addr_.s6_addr, 16);
+ return bytes;
+}
+
+std::string address_v6::to_string() const
+{
+ asio::error_code ec;
+ std::string addr = to_string(ec);
+ asio::detail::throw_error(ec);
+ return addr;
+}
+
+std::string address_v6::to_string(asio::error_code& ec) const
+{
+ char addr_str[asio::detail::max_addr_v6_str_len];
+ const char* addr =
+ asio::detail::socket_ops::inet_ntop(AF_INET6, &addr_, addr_str,
+ asio::detail::max_addr_v6_str_len, scope_id_, ec);
+ if (addr == 0)
+ return std::string();
+ return addr;
+}
+
+address_v6 address_v6::from_string(const char* str)
+{
+ asio::error_code ec;
+ address_v6 addr = from_string(str, ec);
+ asio::detail::throw_error(ec);
+ return addr;
+}
+
+address_v6 address_v6::from_string(
+ const char* str, asio::error_code& ec)
+{
+ address_v6 tmp;
+ if (asio::detail::socket_ops::inet_pton(
+ AF_INET6, str, &tmp.addr_, &tmp.scope_id_, ec) <= 0)
+ return address_v6();
+ return tmp;
+}
+
+address_v6 address_v6::from_string(const std::string& str)
+{
+ return from_string(str.c_str());
+}
+
+address_v6 address_v6::from_string(
+ const std::string& str, asio::error_code& ec)
+{
+ return from_string(str.c_str(), ec);
+}
+
+address_v4 address_v6::to_v4() const
+{
+ if (!is_v4_mapped() && !is_v4_compatible())
+ {
+ std::bad_cast ex;
+ boost::throw_exception(ex);
+ }
+
+ address_v4::bytes_type v4_bytes = { { addr_.s6_addr[12],
+ addr_.s6_addr[13], addr_.s6_addr[14], addr_.s6_addr[15] } };
+ return address_v4(v4_bytes);
+}
+
+bool address_v6::is_loopback() const
+{
+#if defined(__BORLANDC__)
+ return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)
+ && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)
+ && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)
+ && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)
+ && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)
+ && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0)
+ && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0)
+ && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 1));
+#else
+ using namespace asio::detail;
+ return IN6_IS_ADDR_LOOPBACK(&addr_) != 0;
+#endif
+}
+
+bool address_v6::is_unspecified() const
+{
+#if defined(__BORLANDC__)
+ return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)
+ && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)
+ && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)
+ && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)
+ && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)
+ && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0)
+ && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0)
+ && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 0));
+#else
+ using namespace asio::detail;
+ return IN6_IS_ADDR_UNSPECIFIED(&addr_) != 0;
+#endif
+}
+
+bool address_v6::is_link_local() const
+{
+ using namespace asio::detail;
+ return IN6_IS_ADDR_LINKLOCAL(&addr_) != 0;
+}
+
+bool address_v6::is_site_local() const
+{
+ using namespace asio::detail;
+ return IN6_IS_ADDR_SITELOCAL(&addr_) != 0;
+}
+
+bool address_v6::is_v4_mapped() const
+{
+ using namespace asio::detail;
+ return IN6_IS_ADDR_V4MAPPED(&addr_) != 0;
+}
+
+bool address_v6::is_v4_compatible() const
+{
+ using namespace asio::detail;
+ return IN6_IS_ADDR_V4COMPAT(&addr_) != 0;
+}
+
+bool address_v6::is_multicast() const
+{
+ using namespace asio::detail;
+ return IN6_IS_ADDR_MULTICAST(&addr_) != 0;
+}
+
+bool address_v6::is_multicast_global() const
+{
+ using namespace asio::detail;
+ return IN6_IS_ADDR_MC_GLOBAL(&addr_) != 0;
+}
+
+bool address_v6::is_multicast_link_local() const
+{
+ using namespace asio::detail;
+ return IN6_IS_ADDR_MC_LINKLOCAL(&addr_) != 0;
+}
+
+bool address_v6::is_multicast_node_local() const
+{
+ using namespace asio::detail;
+ return IN6_IS_ADDR_MC_NODELOCAL(&addr_) != 0;
+}
+
+bool address_v6::is_multicast_org_local() const
+{
+ using namespace asio::detail;
+ return IN6_IS_ADDR_MC_ORGLOCAL(&addr_) != 0;
+}
+
+bool address_v6::is_multicast_site_local() const
+{
+ using namespace asio::detail;
+ return IN6_IS_ADDR_MC_SITELOCAL(&addr_) != 0;
+}
+
+bool operator==(const address_v6& a1, const address_v6& a2)
+{
+ using namespace std; // For memcmp.
+ return memcmp(&a1.addr_, &a2.addr_,
+ sizeof(asio::detail::in6_addr_type)) == 0
+ && a1.scope_id_ == a2.scope_id_;
+}
+
+bool operator<(const address_v6& a1, const address_v6& a2)
+{
+ using namespace std; // For memcmp.
+ int memcmp_result = memcmp(&a1.addr_, &a2.addr_,
+ sizeof(asio::detail::in6_addr_type));
+ if (memcmp_result < 0)
+ return true;
+ if (memcmp_result > 0)
+ return false;
+ return a1.scope_id_ < a2.scope_id_;
+}
+
+address_v6 address_v6::loopback()
+{
+ address_v6 tmp;
+ asio::detail::in6_addr_type tmp_addr = IN6ADDR_LOOPBACK_INIT;
+ tmp.addr_ = tmp_addr;
+ return tmp;
+}
+
+address_v6 address_v6::v4_mapped(const address_v4& addr)
+{
+ address_v4::bytes_type v4_bytes = addr.to_bytes();
+ bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF,
+ v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };
+ return address_v6(v6_bytes);
+}
+
+address_v6 address_v6::v4_compatible(const address_v4& addr)
+{
+ address_v4::bytes_type v4_bytes = addr.to_bytes();
+ bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };
+ return address_v6(v6_bytes);
+}
+
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IP_IMPL_ADDRESS_V6_IPP
diff --git a/ext/asio/asio/ip/impl/basic_endpoint.hpp b/ext/asio/asio/ip/impl/basic_endpoint.hpp
new file mode 100644
index 0000000000..db7d5fb27e
--- /dev/null
+++ b/ext/asio/asio/ip/impl/basic_endpoint.hpp
@@ -0,0 +1,55 @@
+//
+// ip/impl/basic_endpoint.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_IP_IMPL_BASIC_ENDPOINT_HPP
+#define ASIO_IP_IMPL_BASIC_ENDPOINT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#if !defined(BOOST_NO_IOSTREAM)
+
+#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+
+template <typename Elem, typename Traits, typename InternetProtocol>
+std::basic_ostream<Elem, Traits>& operator<<(
+ std::basic_ostream<Elem, Traits>& os,
+ const basic_endpoint<InternetProtocol>& endpoint)
+{
+ asio::ip::detail::endpoint tmp_ep(endpoint.address(), endpoint.port());
+ asio::error_code ec;
+ std::string s = tmp_ep.to_string(ec);
+ if (ec)
+ {
+ if (os.exceptions() & std::basic_ostream<Elem, Traits>::failbit)
+ asio::detail::throw_error(ec);
+ else
+ os.setstate(std::basic_ostream<Elem, Traits>::failbit);
+ }
+ else
+ for (std::string::iterator i = s.begin(); i != s.end(); ++i)
+ os << os.widen(*i);
+ return os;
+}
+
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+#endif // ASIO_IP_IMPL_BASIC_ENDPOINT_HPP
diff --git a/ext/asio/asio/ip/impl/host_name.ipp b/ext/asio/asio/ip/impl/host_name.ipp
new file mode 100644
index 0000000000..46b3f1bd94
--- /dev/null
+++ b/ext/asio/asio/ip/impl/host_name.ipp
@@ -0,0 +1,54 @@
+//
+// ip/impl/host_name.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_IP_IMPL_HOST_NAME_IPP
+#define ASIO_IP_IMPL_HOST_NAME_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/socket_ops.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/detail/winsock_init.hpp"
+#include "asio/ip/host_name.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace ip {
+
+std::string host_name()
+{
+ char name[1024];
+ asio::error_code ec;
+ if (asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0)
+ {
+ asio::detail::throw_error(ec);
+ return std::string();
+ }
+ return std::string(name);
+}
+
+std::string host_name(asio::error_code& ec)
+{
+ char name[1024];
+ if (asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0)
+ return std::string();
+ return std::string(name);
+}
+
+} // namespace ip
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IP_IMPL_HOST_NAME_IPP
diff --git a/ext/asio/asio/ip/multicast.hpp b/ext/asio/asio/ip/multicast.hpp
index eeedc6ce19..f2193c0817 100644
--- a/ext/asio/asio/ip/multicast.hpp
+++ b/ext/asio/asio/ip/multicast.hpp
@@ -1,8 +1,8 @@
//
-// multicast.hpp
-// ~~~~~~~~~~~~~
+// ip/multicast.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,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 "asio/detail/pop_options.hpp"
-
#include "asio/ip/detail/socket_option.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace ip {
namespace multicast {
diff --git a/ext/asio/asio/ip/resolver_query_base.hpp b/ext/asio/asio/ip/resolver_query_base.hpp
index 5a0acea8f3..8963f41dd8 100644
--- a/ext/asio/asio/ip/resolver_query_base.hpp
+++ b/ext/asio/asio/ip/resolver_query_base.hpp
@@ -1,8 +1,8 @@
//
-// resolver_query_base.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~
+// ip/resolver_query_base.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,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/config.hpp"
#include <boost/detail/workaround.hpp>
-#include "asio/detail/pop_options.hpp"
-
#include "asio/detail/socket_types.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace ip {
diff --git a/ext/asio/asio/ip/resolver_service.hpp b/ext/asio/asio/ip/resolver_service.hpp
index 75f6b2c3af..0d866d6610 100644
--- a/ext/asio/asio/ip/resolver_service.hpp
+++ b/ext/asio/asio/ip/resolver_service.hpp
@@ -1,8 +1,8 @@
//
-// resolver_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~
+// ip/resolver_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,14 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/error.hpp"
+#include "asio/detail/config.hpp"
+#include "asio/error_code.hpp"
+#include "asio/detail/resolver_service.hpp"
#include "asio/io_service.hpp"
#include "asio/ip/basic_resolver_iterator.hpp"
#include "asio/ip/basic_resolver_query.hpp"
-#include "asio/detail/resolver_service.hpp"
-#include "asio/detail/service_base.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace ip {
@@ -72,13 +72,14 @@ public:
explicit resolver_service(asio::io_service& io_service)
: asio::detail::service_base<
resolver_service<InternetProtocol> >(io_service),
- service_impl_(asio::use_service<service_impl_type>(io_service))
+ service_impl_(io_service)
{
}
/// Destroy all user-defined handler objects owned by the service.
void shutdown_service()
{
+ service_impl_.shutdown_service();
}
/// Construct a new resolver implementation.
@@ -130,8 +131,8 @@ public:
}
private:
- // The service that provides the platform-specific implementation.
- service_impl_type& service_impl_;
+ // The platform-specific implementation.
+ service_impl_type service_impl_;
};
} // namespace ip
diff --git a/ext/asio/asio/ip/tcp.hpp b/ext/asio/asio/ip/tcp.hpp
index a2e9ac9c52..67fb09f122 100644
--- a/ext/asio/asio/ip/tcp.hpp
+++ b/ext/asio/asio/ip/tcp.hpp
@@ -1,8 +1,8 @@
//
-// tcp.hpp
-// ~~~~~~~
+// ip/tcp.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,18 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
#include "asio/basic_socket_acceptor.hpp"
#include "asio/basic_socket_iostream.hpp"
#include "asio/basic_stream_socket.hpp"
+#include "asio/detail/socket_option.hpp"
+#include "asio/detail/socket_types.hpp"
#include "asio/ip/basic_endpoint.hpp"
#include "asio/ip/basic_resolver.hpp"
#include "asio/ip/basic_resolver_iterator.hpp"
#include "asio/ip/basic_resolver_query.hpp"
-#include "asio/detail/socket_option.hpp"
-#include "asio/detail/socket_types.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace ip {
diff --git a/ext/asio/asio/ip/udp.hpp b/ext/asio/asio/ip/udp.hpp
index fb261187a8..ca3ac785f5 100644
--- a/ext/asio/asio/ip/udp.hpp
+++ b/ext/asio/asio/ip/udp.hpp
@@ -1,8 +1,8 @@
//
-// udp.hpp
-// ~~~~~~~
+// ip/udp.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_datagram_socket.hpp"
+#include "asio/detail/socket_types.hpp"
#include "asio/ip/basic_endpoint.hpp"
#include "asio/ip/basic_resolver.hpp"
#include "asio/ip/basic_resolver_iterator.hpp"
#include "asio/ip/basic_resolver_query.hpp"
-#include "asio/detail/socket_types.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace ip {
diff --git a/ext/asio/asio/ip/unicast.hpp b/ext/asio/asio/ip/unicast.hpp
index 46d7239c8e..e3d04e5899 100644
--- a/ext/asio/asio/ip/unicast.hpp
+++ b/ext/asio/asio/ip/unicast.hpp
@@ -1,8 +1,8 @@
//
-// unicast.hpp
-// ~~~~~~~~~~~
+// ip/unicast.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,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 "asio/detail/pop_options.hpp"
-
#include "asio/ip/detail/socket_option.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace ip {
namespace unicast {
diff --git a/ext/asio/asio/ip/v6_only.hpp b/ext/asio/asio/ip/v6_only.hpp
index 928caff0df..5ac6a37f7f 100644
--- a/ext/asio/asio/ip/v6_only.hpp
+++ b/ext/asio/asio/ip/v6_only.hpp
@@ -1,8 +1,8 @@
//
-// v6_only.hpp
-// ~~~~~~~~~~~
+// ip/v6_only.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/detail/socket_option.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace ip {
diff --git a/ext/asio/asio/is_read_buffered.hpp b/ext/asio/asio/is_read_buffered.hpp
index 8d971747a3..e48de55227 100644
--- a/ext/asio/asio/is_read_buffered.hpp
+++ b/ext/asio/asio/is_read_buffered.hpp
@@ -2,7 +2,7 @@
// is_read_buffered.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,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"
#include "asio/buffered_read_stream_fwd.hpp"
#include "asio/buffered_stream_fwd.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
diff --git a/ext/asio/asio/is_write_buffered.hpp b/ext/asio/asio/is_write_buffered.hpp
index 5d16b1c542..c681a2bb92 100644
--- a/ext/asio/asio/is_write_buffered.hpp
+++ b/ext/asio/asio/is_write_buffered.hpp
@@ -2,7 +2,7 @@
// is_write_buffered.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,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"
#include "asio/buffered_stream_fwd.hpp"
#include "asio/buffered_write_stream_fwd.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail {
diff --git a/ext/asio/asio/local/basic_endpoint.hpp b/ext/asio/asio/local/basic_endpoint.hpp
index 81e6a7ed57..d2d0a023e7 100644
--- a/ext/asio/asio/local/basic_endpoint.hpp
+++ b/ext/asio/asio/local/basic_endpoint.hpp
@@ -1,8 +1,8 @@
//
-// basic_endpoint.hpp
-// ~~~~~~~~~~~~~~~~~~
+// local/basic_endpoint.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)
// Derived from a public domain implementation written by Daniel Casimiro.
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
@@ -16,30 +16,18 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <boost/throw_exception.hpp>
-#include <cstddef>
-#include <cstring>
-#include <ostream>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/error.hpp"
-#include "asio/system_error.hpp"
-#include "asio/detail/socket_ops.hpp"
-#include "asio/detail/socket_types.hpp"
-#include "asio/detail/throw_error.hpp"
-
-#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)
+#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_LOCAL_SOCKETS) \
|| defined(GENERATING_DOCUMENTATION)
+#include "asio/local/detail/endpoint.hpp"
+
+#if !defined(BOOST_NO_IOSTREAM)
+# include <iosfwd>
+#endif // !defined(BOOST_NO_IOSTREAM)
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace local {
@@ -74,34 +62,30 @@ public:
/// Default constructor.
basic_endpoint()
{
- init("", 0);
}
/// Construct an endpoint using the specified path name.
basic_endpoint(const char* path)
+ : impl_(path)
{
- using namespace std; // For strlen.
- init(path, strlen(path));
}
/// Construct an endpoint using the specified path name.
basic_endpoint(const std::string& path)
+ : impl_(path)
{
- init(path.data(), path.length());
}
/// Copy constructor.
basic_endpoint(const basic_endpoint& other)
- : data_(other.data_),
- path_length_(other.path_length_)
+ : impl_(other.impl_)
{
}
/// Assign from another endpoint.
basic_endpoint& operator=(const basic_endpoint& other)
{
- data_ = other.data_;
- path_length_ = other.path_length_;
+ impl_ = other.impl_;
return *this;
}
@@ -114,123 +98,96 @@ public:
/// Get the underlying endpoint in the native type.
data_type* data()
{
- return &data_.base;
+ return impl_.data();
}
/// Get the underlying endpoint in the native type.
const data_type* data() const
{
- return &data_.base;
+ return impl_.data();
}
/// Get the underlying size of the endpoint in the native type.
std::size_t size() const
{
- return path_length_
- + offsetof(asio::detail::sockaddr_un_type, sun_path);
+ return impl_.size();
}
/// Set the underlying size of the endpoint in the native type.
void resize(std::size_t size)
{
- if (size > sizeof(asio::detail::sockaddr_un_type))
- {
- asio::system_error e(asio::error::invalid_argument);
- boost::throw_exception(e);
- }
- else if (size == 0)
- {
- path_length_ = 0;
- }
- else
- {
- path_length_ = size
- - offsetof(asio::detail::sockaddr_un_type, sun_path);
-
- // The path returned by the operating system may be NUL-terminated.
- if (path_length_ > 0 && data_.local.sun_path[path_length_ - 1] == 0)
- --path_length_;
- }
+ impl_.resize(size);
}
/// Get the capacity of the endpoint in the native type.
std::size_t capacity() const
{
- return sizeof(asio::detail::sockaddr_un_type);
+ return impl_.capacity();
}
/// Get the path associated with the endpoint.
std::string path() const
{
- return std::string(data_.local.sun_path, path_length_);
+ return impl_.path();
}
/// Set the path associated with the endpoint.
void path(const char* p)
{
- using namespace std; // For strlen.
- init(p, strlen(p));
+ impl_.path(p);
}
/// Set the path associated with the endpoint.
void path(const std::string& p)
{
- init(p.data(), p.length());
+ impl_.path(p);
}
/// Compare two endpoints for equality.
friend bool operator==(const basic_endpoint<Protocol>& e1,
const basic_endpoint<Protocol>& e2)
{
- return e1.path() == e2.path();
+ return e1.impl_ == e2.impl_;
}
/// Compare two endpoints for inequality.
friend bool operator!=(const basic_endpoint<Protocol>& e1,
const basic_endpoint<Protocol>& e2)
{
- return e1.path() != e2.path();
+ return !(e1.impl_ == e2.impl_);
}
/// Compare endpoints for ordering.
friend bool operator<(const basic_endpoint<Protocol>& e1,
const basic_endpoint<Protocol>& e2)
{
- return e1.path() < e2.path();
+ return e1.impl_ < e2.impl_;
}
-private:
- // The underlying UNIX socket address.
- union data_union
+ /// Compare endpoints for ordering.
+ friend bool operator>(const basic_endpoint<Protocol>& e1,
+ const basic_endpoint<Protocol>& e2)
{
- asio::detail::socket_addr_type base;
- asio::detail::sockaddr_un_type local;
- } data_;
+ return e2.impl_ < e1.impl_;
+ }
- // The length of the path associated with the endpoint.
- std::size_t path_length_;
+ /// Compare endpoints for ordering.
+ friend bool operator<=(const basic_endpoint<Protocol>& e1,
+ const basic_endpoint<Protocol>& e2)
+ {
+ return !(e2 < e1);
+ }
- // Initialise with a specified path.
- void init(const char* path, std::size_t path_length)
+ /// Compare endpoints for ordering.
+ friend bool operator>=(const basic_endpoint<Protocol>& e1,
+ const basic_endpoint<Protocol>& e2)
{
- if (path_length > sizeof(data_.local.sun_path) - 1)
- {
- // The buffer is not large enough to store this address.
- asio::error_code ec(asio::error::name_too_long);
- asio::detail::throw_error(ec);
- }
-
- using namespace std; // For memcpy.
- data_.local = asio::detail::sockaddr_un_type();
- data_.local.sun_family = AF_UNIX;
- memcpy(data_.local.sun_path, path, path_length);
- path_length_ = path_length;
-
- // NUL-terminate normal path names. Names that start with a NUL are in the
- // UNIX domain protocol's "abstract namespace" and are not NUL-terminated.
- if (path_length > 0 && data_.local.sun_path[0] == 0)
- data_.local.sun_path[path_length] = 0;
+ return !(e1 < e2);
}
+
+private:
+ // The underlying UNIX domain endpoint.
+ asio::local::detail::endpoint impl_;
};
/// Output an endpoint as a string.
@@ -257,9 +214,9 @@ std::basic_ostream<Elem, Traits>& operator<<(
} // namespace local
} // namespace asio
+#include "asio/detail/pop_options.hpp"
+
#endif // defined(ASIO_HAS_LOCAL_SOCKETS)
// || defined(GENERATING_DOCUMENTATION)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_LOCAL_BASIC_ENDPOINT_HPP
diff --git a/ext/asio/asio/local/connect_pair.hpp b/ext/asio/asio/local/connect_pair.hpp
index da1d4fc5bd..4a582477e3 100644
--- a/ext/asio/asio/local/connect_pair.hpp
+++ b/ext/asio/asio/local/connect_pair.hpp
@@ -1,8 +1,8 @@
//
-// connect_pair.hpp
-// ~~~~~~~~~~~~~~~~
+// local/connect_pair.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,18 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_LOCAL_SOCKETS) \
+ || defined(GENERATING_DOCUMENTATION)
#include "asio/basic_socket.hpp"
-#include "asio/error.hpp"
-#include "asio/local/basic_endpoint.hpp"
#include "asio/detail/socket_ops.hpp"
#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+#include "asio/local/basic_endpoint.hpp"
-#if defined(ASIO_HAS_LOCAL_SOCKETS) \
- || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace local {
@@ -73,8 +75,9 @@ inline asio::error_code connect_pair(
if (socket1.assign(protocol, sv[0], ec))
{
asio::error_code temp_ec;
- asio::detail::socket_ops::close(sv[0], temp_ec);
- asio::detail::socket_ops::close(sv[1], temp_ec);
+ asio::detail::socket_ops::state_type state[2] = { 0, 0 };
+ asio::detail::socket_ops::close(sv[0], state[0], true, temp_ec);
+ asio::detail::socket_ops::close(sv[1], state[1], true, temp_ec);
return ec;
}
@@ -82,7 +85,8 @@ inline asio::error_code connect_pair(
{
asio::error_code temp_ec;
socket1.close(temp_ec);
- asio::detail::socket_ops::close(sv[1], temp_ec);
+ asio::detail::socket_ops::state_type state = 0;
+ asio::detail::socket_ops::close(sv[1], state, true, temp_ec);
return ec;
}
@@ -92,9 +96,9 @@ inline asio::error_code connect_pair(
} // namespace local
} // namespace asio
+#include "asio/detail/pop_options.hpp"
+
#endif // defined(ASIO_HAS_LOCAL_SOCKETS)
// || defined(GENERATING_DOCUMENTATION)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_LOCAL_CONNECT_PAIR_HPP
diff --git a/ext/asio/asio/local/datagram_protocol.hpp b/ext/asio/asio/local/datagram_protocol.hpp
index 0340180545..39f47ce7d5 100644
--- a/ext/asio/asio/local/datagram_protocol.hpp
+++ b/ext/asio/asio/local/datagram_protocol.hpp
@@ -1,8 +1,8 @@
//
-// datagram_protocol.hpp
-// ~~~~~~~~~~~~~~~~~~~~~
+// local/datagram_protocol.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,16 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_LOCAL_SOCKETS) \
+ || defined(GENERATING_DOCUMENTATION)
#include "asio/basic_datagram_socket.hpp"
-#include "asio/local/basic_endpoint.hpp"
#include "asio/detail/socket_types.hpp"
+#include "asio/local/basic_endpoint.hpp"
-#if defined(ASIO_HAS_LOCAL_SOCKETS) \
- || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace local {
@@ -70,9 +72,9 @@ public:
} // namespace local
} // namespace asio
+#include "asio/detail/pop_options.hpp"
+
#endif // defined(ASIO_HAS_LOCAL_SOCKETS)
// || defined(GENERATING_DOCUMENTATION)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_LOCAL_DATAGRAM_PROTOCOL_HPP
diff --git a/ext/asio/asio/local/detail/endpoint.hpp b/ext/asio/asio/local/detail/endpoint.hpp
new file mode 100644
index 0000000000..05fc992383
--- /dev/null
+++ b/ext/asio/asio/local/detail/endpoint.hpp
@@ -0,0 +1,133 @@
+//
+// local/detail/endpoint.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Derived from a public domain implementation written by Daniel Casimiro.
+//
+// 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_LOCAL_DETAIL_ENDPOINT_HPP
+#define ASIO_LOCAL_DETAIL_ENDPOINT_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_LOCAL_SOCKETS)
+
+#include <cstddef>
+#include <string>
+#include "asio/detail/socket_types.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace local {
+namespace detail {
+
+// Helper class for implementing a UNIX domain endpoint.
+class endpoint
+{
+public:
+ // Default constructor.
+ ASIO_DECL endpoint();
+
+ // Construct an endpoint using the specified path name.
+ ASIO_DECL endpoint(const char* path);
+
+ // Construct an endpoint using the specified path name.
+ ASIO_DECL endpoint(const std::string& path);
+
+ // Copy constructor.
+ endpoint(const endpoint& other)
+ : data_(other.data_),
+ path_length_(other.path_length_)
+ {
+ }
+
+ // Assign from another endpoint.
+ endpoint& operator=(const endpoint& other)
+ {
+ data_ = other.data_;
+ path_length_ = other.path_length_;
+ return *this;
+ }
+
+ // Get the underlying endpoint in the native type.
+ asio::detail::socket_addr_type* data()
+ {
+ return &data_.base;
+ }
+
+ // Get the underlying endpoint in the native type.
+ const asio::detail::socket_addr_type* data() const
+ {
+ return &data_.base;
+ }
+
+ // Get the underlying size of the endpoint in the native type.
+ std::size_t size() const
+ {
+ return path_length_
+ + offsetof(asio::detail::sockaddr_un_type, sun_path);
+ }
+
+ // Set the underlying size of the endpoint in the native type.
+ ASIO_DECL void resize(std::size_t size);
+
+ // Get the capacity of the endpoint in the native type.
+ std::size_t capacity() const
+ {
+ return sizeof(asio::detail::sockaddr_un_type);
+ }
+
+ // Get the path associated with the endpoint.
+ ASIO_DECL std::string path() const;
+
+ // Set the path associated with the endpoint.
+ ASIO_DECL void path(const char* p);
+
+ // Set the path associated with the endpoint.
+ ASIO_DECL void path(const std::string& p);
+
+ // Compare two endpoints for equality.
+ ASIO_DECL friend bool operator==(
+ const endpoint& e1, const endpoint& e2);
+
+ // Compare endpoints for ordering.
+ ASIO_DECL friend bool operator<(
+ const endpoint& e1, const endpoint& e2);
+
+private:
+ // The underlying UNIX socket address.
+ union data_union
+ {
+ asio::detail::socket_addr_type base;
+ asio::detail::sockaddr_un_type local;
+ } data_;
+
+ // The length of the path associated with the endpoint.
+ std::size_t path_length_;
+
+ // Initialise with a specified path.
+ ASIO_DECL void init(const char* path, std::size_t path_length);
+};
+
+} // namespace detail
+} // namespace local
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/local/detail/impl/endpoint.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
+#endif // defined(ASIO_HAS_LOCAL_SOCKETS)
+
+#endif // ASIO_LOCAL_DETAIL_ENDPOINT_HPP
diff --git a/ext/asio/asio/local/detail/impl/endpoint.ipp b/ext/asio/asio/local/detail/impl/endpoint.ipp
new file mode 100644
index 0000000000..e1bb53fea9
--- /dev/null
+++ b/ext/asio/asio/local/detail/impl/endpoint.ipp
@@ -0,0 +1,128 @@
+//
+// local/detail/impl/endpoint.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Derived from a public domain implementation written by Daniel Casimiro.
+//
+// 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_LOCAL_DETAIL_IMPL_ENDPOINT_IPP
+#define ASIO_LOCAL_DETAIL_IMPL_ENDPOINT_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_LOCAL_SOCKETS)
+
+#include <cstring>
+#include "asio/detail/socket_ops.hpp"
+#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+#include "asio/local/detail/endpoint.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+namespace local {
+namespace detail {
+
+endpoint::endpoint()
+{
+ init("", 0);
+}
+
+endpoint::endpoint(const char* path)
+{
+ using namespace std; // For strlen.
+ init(path, strlen(path));
+}
+
+endpoint::endpoint(const std::string& path)
+{
+ init(path.data(), path.length());
+}
+
+void endpoint::resize(std::size_t size)
+{
+ if (size > sizeof(asio::detail::sockaddr_un_type))
+ {
+ asio::error_code ec(asio::error::invalid_argument);
+ asio::detail::throw_error(ec);
+ }
+ else if (size == 0)
+ {
+ path_length_ = 0;
+ }
+ else
+ {
+ path_length_ = size
+ - offsetof(asio::detail::sockaddr_un_type, sun_path);
+
+ // The path returned by the operating system may be NUL-terminated.
+ if (path_length_ > 0 && data_.local.sun_path[path_length_ - 1] == 0)
+ --path_length_;
+ }
+}
+
+std::string endpoint::path() const
+{
+ return std::string(data_.local.sun_path, path_length_);
+}
+
+void endpoint::path(const char* p)
+{
+ using namespace std; // For strlen.
+ init(p, strlen(p));
+}
+
+void endpoint::path(const std::string& p)
+{
+ init(p.data(), p.length());
+}
+
+bool operator==(const endpoint& e1, const endpoint& e2)
+{
+ return e1.path() == e2.path();
+}
+
+bool operator<(const endpoint& e1, const endpoint& e2)
+{
+ return e1.path() < e2.path();
+}
+
+void endpoint::init(const char* path, std::size_t path_length)
+{
+ if (path_length > sizeof(data_.local.sun_path) - 1)
+ {
+ // The buffer is not large enough to store this address.
+ asio::error_code ec(asio::error::name_too_long);
+ asio::detail::throw_error(ec);
+ }
+
+ using namespace std; // For memcpy.
+ data_.local = asio::detail::sockaddr_un_type();
+ data_.local.sun_family = AF_UNIX;
+ memcpy(data_.local.sun_path, path, path_length);
+ path_length_ = path_length;
+
+ // NUL-terminate normal path names. Names that start with a NUL are in the
+ // UNIX domain protocol's "abstract namespace" and are not NUL-terminated.
+ if (path_length > 0 && data_.local.sun_path[0] == 0)
+ data_.local.sun_path[path_length] = 0;
+}
+
+} // namespace detail
+} // namespace local
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // defined(ASIO_HAS_LOCAL_SOCKETS)
+
+#endif // ASIO_LOCAL_DETAIL_IMPL_ENDPOINT_IPP
diff --git a/ext/asio/asio/local/stream_protocol.hpp b/ext/asio/asio/local/stream_protocol.hpp
index 47fe42f132..e65a2f6dfb 100644
--- a/ext/asio/asio/local/stream_protocol.hpp
+++ b/ext/asio/asio/local/stream_protocol.hpp
@@ -1,8 +1,8 @@
//
-// stream_protocol.hpp
-// ~~~~~~~~~~~~~~~~~~~
+// local/stream_protocol.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,18 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_LOCAL_SOCKETS) \
+ || defined(GENERATING_DOCUMENTATION)
#include "asio/basic_socket_acceptor.hpp"
#include "asio/basic_socket_iostream.hpp"
#include "asio/basic_stream_socket.hpp"
-#include "asio/local/basic_endpoint.hpp"
#include "asio/detail/socket_types.hpp"
+#include "asio/local/basic_endpoint.hpp"
-#if defined(ASIO_HAS_LOCAL_SOCKETS) \
- || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace local {
@@ -80,9 +82,9 @@ public:
} // namespace local
} // namespace asio
+#include "asio/detail/pop_options.hpp"
+
#endif // defined(ASIO_HAS_LOCAL_SOCKETS)
// || defined(GENERATING_DOCUMENTATION)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_LOCAL_STREAM_PROTOCOL_HPP
diff --git a/ext/asio/asio/placeholders.hpp b/ext/asio/asio/placeholders.hpp
index 70e69fca53..6fda487d7f 100644
--- a/ext/asio/asio/placeholders.hpp
+++ b/ext/asio/asio/placeholders.hpp
@@ -2,7 +2,7 @@
// placeholders.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,11 @@
# 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/bind/arg.hpp>
#include <boost/detail/workaround.hpp>
-#include "asio/detail/pop_options.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace placeholders {
diff --git a/ext/asio/asio/posix/basic_descriptor.hpp b/ext/asio/asio/posix/basic_descriptor.hpp
index 37bcc94dfc..591e65a6d9 100644
--- a/ext/asio/asio/posix/basic_descriptor.hpp
+++ b/ext/asio/asio/posix/basic_descriptor.hpp
@@ -1,8 +1,8 @@
//
-// basic_descriptor.hpp
-// ~~~~~~~~~~~~~~~~~~~~
+// posix/basic_descriptor.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,17 @@
# 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(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
+ || defined(GENERATING_DOCUMENTATION)
#include "asio/basic_io_object.hpp"
+#include "asio/detail/throw_error.hpp"
#include "asio/error.hpp"
#include "asio/posix/descriptor_base.hpp"
-#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace posix {
@@ -291,4 +292,7 @@ protected:
#include "asio/detail/pop_options.hpp"
+#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+ // || defined(GENERATING_DOCUMENTATION)
+
#endif // ASIO_POSIX_BASIC_DESCRIPTOR_HPP
diff --git a/ext/asio/asio/posix/basic_stream_descriptor.hpp b/ext/asio/asio/posix/basic_stream_descriptor.hpp
index 21e2287dbf..8211c58d06 100644
--- a/ext/asio/asio/posix/basic_stream_descriptor.hpp
+++ b/ext/asio/asio/posix/basic_stream_descriptor.hpp
@@ -1,8 +1,8 @@
//
-// basic_stream_descriptor.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// posix/basic_stream_descriptor.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,18 @@
# 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 <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
+ || defined(GENERATING_DOCUMENTATION)
+#include <cstddef>
+#include "asio/detail/throw_error.hpp"
#include "asio/error.hpp"
#include "asio/posix/basic_descriptor.hpp"
#include "asio/posix/stream_descriptor_service.hpp"
-#include "asio/detail/throw_error.hpp"
-#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
- || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace posix {
@@ -296,9 +294,9 @@ public:
} // namespace posix
} // namespace asio
+#include "asio/detail/pop_options.hpp"
+
#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
// || defined(GENERATING_DOCUMENTATION)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP
diff --git a/ext/asio/asio/posix/descriptor_base.hpp b/ext/asio/asio/posix/descriptor_base.hpp
index 29e17469df..2222915678 100644
--- a/ext/asio/asio/posix/descriptor_base.hpp
+++ b/ext/asio/asio/posix/descriptor_base.hpp
@@ -1,8 +1,8 @@
//
-// descriptor_base.hpp
-// ~~~~~~~~~~~~~~~~~~~
+// posix/descriptor_base.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,16 @@
# 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 <boost/detail/workaround.hpp>
-#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
+ || defined(GENERATING_DOCUMENTATION)
#include "asio/detail/io_control.hpp"
#include "asio/detail/socket_option.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace posix {
@@ -90,4 +90,7 @@ protected:
#include "asio/detail/pop_options.hpp"
+#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+ // || defined(GENERATING_DOCUMENTATION)
+
#endif // ASIO_POSIX_DESCRIPTOR_BASE_HPP
diff --git a/ext/asio/asio/posix/stream_descriptor.hpp b/ext/asio/asio/posix/stream_descriptor.hpp
index 72fbbed23c..48c20a3686 100644
--- a/ext/asio/asio/posix/stream_descriptor.hpp
+++ b/ext/asio/asio/posix/stream_descriptor.hpp
@@ -1,8 +1,8 @@
//
-// stream_descriptor.hpp
-// ~~~~~~~~~~~~~~~~~~~~~
+// posix/stream_descriptor.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,13 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/posix/basic_stream_descriptor.hpp"
+#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
|| defined(GENERATING_DOCUMENTATION)
+#include "asio/posix/basic_stream_descriptor.hpp"
+
namespace asio {
namespace posix {
@@ -34,6 +34,4 @@ typedef basic_stream_descriptor<> stream_descriptor;
#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
// || defined(GENERATING_DOCUMENTATION)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_POSIX_STREAM_DESCRIPTOR_HPP
diff --git a/ext/asio/asio/posix/stream_descriptor_service.hpp b/ext/asio/asio/posix/stream_descriptor_service.hpp
index 61cee1b54d..4660e79dab 100644
--- a/ext/asio/asio/posix/stream_descriptor_service.hpp
+++ b/ext/asio/asio/posix/stream_descriptor_service.hpp
@@ -1,8 +1,8 @@
//
-// stream_descriptor_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// posix/stream_descriptor_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,28 +15,18 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.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_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)
+#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
|| defined(GENERATING_DOCUMENTATION)
+#include <cstddef>
+#include "asio/error.hpp"
+#include "asio/io_service.hpp"
#include "asio/detail/reactive_descriptor_service.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace posix {
@@ -179,9 +169,9 @@ private:
} // namespace posix
} // namespace asio
+#include "asio/detail/pop_options.hpp"
+
#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
// || defined(GENERATING_DOCUMENTATION)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP
diff --git a/ext/asio/asio/raw_socket_service.hpp b/ext/asio/asio/raw_socket_service.hpp
index a8973d3445..3d0016d328 100644
--- a/ext/asio/asio/raw_socket_service.hpp
+++ b/ext/asio/asio/raw_socket_service.hpp
@@ -2,7 +2,7 @@
// raw_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 raw socket.
diff --git a/ext/asio/asio/read.hpp b/ext/asio/asio/read.hpp
index 859c05a003..7f04b07dbd 100644
--- a/ext/asio/asio/read.hpp
+++ b/ext/asio/asio/read.hpp
@@ -2,7 +2,7 @@
// read.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 "asio/detail/config.hpp"
#include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/basic_streambuf.hpp"
+#include "asio/basic_streambuf_fwd.hpp"
#include "asio/error.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
/**
@@ -536,8 +533,8 @@ void async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
} // namespace asio
-#include "asio/impl/read.ipp"
-
#include "asio/detail/pop_options.hpp"
+#include "asio/impl/read.hpp"
+
#endif // ASIO_READ_HPP
diff --git a/ext/asio/asio/read_at.hpp b/ext/asio/asio/read_at.hpp
index 6bb3fe125a..4be1f96f2b 100644
--- a/ext/asio/asio/read_at.hpp
+++ b/ext/asio/asio/read_at.hpp
@@ -2,7 +2,7 @@
// read_at.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 <boost/cstdint.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/basic_streambuf.hpp"
+#include "asio/basic_streambuf_fwd.hpp"
#include "asio/error.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
/**
@@ -569,8 +566,8 @@ void async_read_at(AsyncRandomAccessReadDevice& d,
} // namespace asio
-#include "asio/impl/read_at.ipp"
-
#include "asio/detail/pop_options.hpp"
+#include "asio/impl/read_at.hpp"
+
#endif // ASIO_READ_AT_HPP
diff --git a/ext/asio/asio/read_until.hpp b/ext/asio/asio/read_until.hpp
index 5df71ce29c..67fa066de1 100644
--- a/ext/asio/asio/read_until.hpp
+++ b/ext/asio/asio/read_until.hpp
@@ -2,7 +2,7 @@
// read_until.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,22 @@
# 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 <cstddef>
-#include <boost/regex.hpp>
#include <boost/type_traits/is_function.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/detail/workaround.hpp>
#include <string>
-#include "asio/detail/pop_options.hpp"
-
#include "asio/basic_streambuf.hpp"
+#include "asio/detail/regex_fwd.hpp"
#include "asio/error.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace detail
@@ -914,10 +909,10 @@ void async_read_until(AsyncReadStream& s,
} // namespace asio
-#include "asio/impl/read_until.ipp"
+#include "asio/detail/pop_options.hpp"
+
+#include "asio/impl/read_until.hpp"
#endif // !defined(BOOST_NO_IOSTREAM)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_READ_UNTIL_HPP
diff --git a/ext/asio/asio/serial_port.hpp b/ext/asio/asio/serial_port.hpp
index a55a03aa07..4cc6fd443b 100644
--- a/ext/asio/asio/serial_port.hpp
+++ b/ext/asio/asio/serial_port.hpp
@@ -2,7 +2,7 @@
// 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,13 +16,13 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/basic_serial_port.hpp"
+#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_SERIAL_PORT) \
|| defined(GENERATING_DOCUMENTATION)
+#include "asio/basic_serial_port.hpp"
+
namespace asio {
/// Typedef for the typical usage of a serial port.
@@ -33,6 +33,4 @@ typedef basic_serial_port<> serial_port;
#endif // defined(ASIO_HAS_SERIAL_PORT)
// || defined(GENERATING_DOCUMENTATION)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_SERIAL_PORT_HPP
diff --git a/ext/asio/asio/serial_port_base.hpp b/ext/asio/asio/serial_port_base.hpp
index 28e51a08a0..9c7a773954 100644
--- a/ext/asio/asio/serial_port_base.hpp
+++ b/ext/asio/asio/serial_port_base.hpp
@@ -2,7 +2,7 @@
// serial_port_base.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,32 +16,18 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/push_options.hpp"
-#include <stdexcept>
-#include <boost/config.hpp>
-#include <boost/detail/workaround.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#if !defined(ASIO_DISABLE_SERIAL_PORT)
-# if defined(ASIO_HAS_IOCP) \
- || !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-# define ASIO_HAS_SERIAL_PORT 1
-# endif // defined(ASIO_HAS_IOCP)
-#endif // !defined(ASIO_DISABLE_STREAM_HANDLE)
+#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_SERIAL_PORT) \
|| defined(GENERATING_DOCUMENTATION)
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-# include "asio/detail/push_options.hpp"
# include <termios.h>
-# include "asio/detail/pop_options.hpp"
#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
-#include "asio/error_code.hpp"
+#include <boost/detail/workaround.hpp>
#include "asio/detail/socket_types.hpp"
+#include "asio/error_code.hpp"
#if defined(GENERATING_DOCUMENTATION)
# define ASIO_OPTION_STORAGE implementation_defined
@@ -51,6 +37,8 @@
# define ASIO_OPTION_STORAGE termios
#endif
+#include "asio/detail/push_options.hpp"
+
namespace asio {
/// The serial_port_base class is used as a base for the basic_serial_port class
@@ -67,9 +55,11 @@ public:
public:
explicit baud_rate(unsigned int rate = 0);
unsigned int value() const;
- asio::error_code store(ASIO_OPTION_STORAGE& storage,
+ ASIO_DECL asio::error_code store(
+ ASIO_OPTION_STORAGE& storage,
asio::error_code& ec) const;
- asio::error_code load(const ASIO_OPTION_STORAGE& storage,
+ ASIO_DECL asio::error_code load(
+ const ASIO_OPTION_STORAGE& storage,
asio::error_code& ec);
private:
unsigned int value_;
@@ -83,11 +73,13 @@ public:
{
public:
enum type { none, software, hardware };
- explicit flow_control(type t = none);
+ ASIO_DECL explicit flow_control(type t = none);
type value() const;
- asio::error_code store(ASIO_OPTION_STORAGE& storage,
+ ASIO_DECL asio::error_code store(
+ ASIO_OPTION_STORAGE& storage,
asio::error_code& ec) const;
- asio::error_code load(const ASIO_OPTION_STORAGE& storage,
+ ASIO_DECL asio::error_code load(
+ const ASIO_OPTION_STORAGE& storage,
asio::error_code& ec);
private:
type value_;
@@ -101,11 +93,13 @@ public:
{
public:
enum type { none, odd, even };
- explicit parity(type t = none);
+ ASIO_DECL explicit parity(type t = none);
type value() const;
- asio::error_code store(ASIO_OPTION_STORAGE& storage,
+ ASIO_DECL asio::error_code store(
+ ASIO_OPTION_STORAGE& storage,
asio::error_code& ec) const;
- asio::error_code load(const ASIO_OPTION_STORAGE& storage,
+ ASIO_DECL asio::error_code load(
+ const ASIO_OPTION_STORAGE& storage,
asio::error_code& ec);
private:
type value_;
@@ -119,11 +113,13 @@ public:
{
public:
enum type { one, onepointfive, two };
- explicit stop_bits(type t = one);
+ ASIO_DECL explicit stop_bits(type t = one);
type value() const;
- asio::error_code store(ASIO_OPTION_STORAGE& storage,
+ ASIO_DECL asio::error_code store(
+ ASIO_OPTION_STORAGE& storage,
asio::error_code& ec) const;
- asio::error_code load(const ASIO_OPTION_STORAGE& storage,
+ ASIO_DECL asio::error_code load(
+ const ASIO_OPTION_STORAGE& storage,
asio::error_code& ec);
private:
type value_;
@@ -136,11 +132,13 @@ public:
class character_size
{
public:
- explicit character_size(unsigned int t = 8);
+ ASIO_DECL explicit character_size(unsigned int t = 8);
unsigned int value() const;
- asio::error_code store(ASIO_OPTION_STORAGE& storage,
+ ASIO_DECL asio::error_code store(
+ ASIO_OPTION_STORAGE& storage,
asio::error_code& ec) const;
- asio::error_code load(const ASIO_OPTION_STORAGE& storage,
+ ASIO_DECL asio::error_code load(
+ const ASIO_OPTION_STORAGE& storage,
asio::error_code& ec);
private:
unsigned int value_;
@@ -161,13 +159,16 @@ private:
} // namespace asio
-#include "asio/impl/serial_port_base.ipp"
+#include "asio/detail/pop_options.hpp"
#undef ASIO_OPTION_STORAGE
+#include "asio/impl/serial_port_base.hpp"
+#if defined(ASIO_HEADER_ONLY)
+# include "asio/impl/serial_port_base.ipp"
+#endif // defined(ASIO_HEADER_ONLY)
+
#endif // defined(ASIO_HAS_SERIAL_PORT)
// || defined(GENERATING_DOCUMENTATION)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_SERIAL_PORT_BASE_HPP
diff --git a/ext/asio/asio/serial_port_service.hpp b/ext/asio/asio/serial_port_service.hpp
index 5847c293f5..37142d5b56 100644
--- a/ext/asio/asio/serial_port_service.hpp
+++ b/ext/asio/asio/serial_port_service.hpp
@@ -2,7 +2,7 @@
// serial_port_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,23 +15,20 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_SERIAL_PORT) \
+ || defined(GENERATING_DOCUMENTATION)
-#include "asio/detail/push_options.hpp"
#include <cstddef>
-#include <boost/config.hpp>
#include <string>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/reactive_serial_port_service.hpp"
+#include "asio/detail/win_iocp_serial_port_service.hpp"
#include "asio/error.hpp"
#include "asio/io_service.hpp"
#include "asio/serial_port_base.hpp"
-#include "asio/detail/service_base.hpp"
-#include "asio/detail/reactive_serial_port_service.hpp"
-#include "asio/detail/win_iocp_serial_port_service.hpp"
-#if defined(ASIO_HAS_SERIAL_PORT) \
- || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
namespace asio {
@@ -199,9 +196,9 @@ private:
} // 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_SERIAL_PORT_SERVICE_HPP
diff --git a/ext/asio/asio/socket_acceptor_service.hpp b/ext/asio/asio/socket_acceptor_service.hpp
index b2e2c6d2ec..a1e4874ebf 100644
--- a/ext/asio/asio/socket_acceptor_service.hpp
+++ b/ext/asio/asio/socket_acceptor_service.hpp
@@ -2,7 +2,7 @@
// socket_acceptor_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,12 +15,10 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
#include "asio/basic_socket.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"
@@ -28,6 +26,8 @@
# include "asio/detail/reactive_socket_service.hpp"
#endif
+#include "asio/detail/push_options.hpp"
+
namespace asio {
/// Default service implementation for a socket acceptor.
diff --git a/ext/asio/asio/socket_base.hpp b/ext/asio/asio/socket_base.hpp
index d82cd22e8e..56585e18f4 100644
--- a/ext/asio/asio/socket_base.hpp
+++ b/ext/asio/asio/socket_base.hpp
@@ -2,7 +2,7 @@
// socket_base.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 <boost/config.hpp>
+#include "asio/detail/config.hpp"
#include <boost/detail/workaround.hpp>
-#include "asio/detail/pop_options.hpp"
-
#include "asio/detail/io_control.hpp"
#include "asio/detail/socket_option.hpp"
#include "asio/detail/socket_types.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
/// The socket_base class is used as a base for the basic_stream_socket and
diff --git a/ext/asio/asio/ssl.hpp b/ext/asio/asio/ssl.hpp
index a9fff5e6ed..48aff5a9b9 100644
--- a/ext/asio/asio/ssl.hpp
+++ b/ext/asio/asio/ssl.hpp
@@ -2,7 +2,7 @@
// ssl.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)
diff --git a/ext/asio/asio/ssl/basic_context.hpp b/ext/asio/asio/ssl/basic_context.hpp
index ea3893ed5a..20ed57dc2e 100755
--- a/ext/asio/asio/ssl/basic_context.hpp
+++ b/ext/asio/asio/ssl/basic_context.hpp
@@ -1,9 +1,9 @@
//
-// basic_context.hpp
-// ~~~~~~~~~~~~~~~~~
+// ssl/basic_context.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-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)
@@ -16,17 +16,15 @@
# 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 <string>
#include <boost/noncopyable.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/throw_error.hpp"
#include "asio/error.hpp"
#include "asio/io_service.hpp"
#include "asio/ssl/context_base.hpp"
-#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace ssl {
diff --git a/ext/asio/asio/ssl/context.hpp b/ext/asio/asio/ssl/context.hpp
index d53882afa9..7aedc4dbd8 100644
--- a/ext/asio/asio/ssl/context.hpp
+++ b/ext/asio/asio/ssl/context.hpp
@@ -1,9 +1,9 @@
//
-// context.hpp
-// ~~~~~~~~~~~
+// ssl/context.hpp
+// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-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)
@@ -16,8 +16,7 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
+#include "asio/detail/config.hpp"
#include "asio/ssl/basic_context.hpp"
#include "asio/ssl/context_service.hpp"
@@ -30,6 +29,4 @@ typedef basic_context<context_service> context;
} // namespace ssl
} // namespace asio
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_SSL_CONTEXT_HPP
diff --git a/ext/asio/asio/ssl/context_base.hpp b/ext/asio/asio/ssl/context_base.hpp
index a0700ca27a..7636bedebb 100755
--- a/ext/asio/asio/ssl/context_base.hpp
+++ b/ext/asio/asio/ssl/context_base.hpp
@@ -1,8 +1,8 @@
//
-// context_base.hpp
-// ~~~~~~~~~~~~~~~~
+// ssl/context_base.hpp
+// ~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-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,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/config.hpp"
#include <boost/detail/workaround.hpp>
-#include "asio/detail/pop_options.hpp"
-
#include "asio/ssl/detail/openssl_types.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace ssl {
diff --git a/ext/asio/asio/ssl/context_service.hpp b/ext/asio/asio/ssl/context_service.hpp
index e9cfef7ef2..766bbdee24 100755
--- a/ext/asio/asio/ssl/context_service.hpp
+++ b/ext/asio/asio/ssl/context_service.hpp
@@ -1,9 +1,9 @@
//
-// context_service.hpp
-// ~~~~~~~~~~~~~~~~~~~
+// ssl/context_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-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)
@@ -16,19 +16,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 <string>
#include <boost/noncopyable.hpp>
-#include "asio/detail/pop_options.hpp"
-
#include "asio/error.hpp"
#include "asio/io_service.hpp"
-#include "asio/detail/service_base.hpp"
#include "asio/ssl/context_base.hpp"
#include "asio/ssl/detail/openssl_context_service.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace ssl {
diff --git a/ext/asio/asio/ssl/detail/openssl_context_service.hpp b/ext/asio/asio/ssl/detail/openssl_context_service.hpp
index a3d4fdb54c..7019542ee2 100755
--- a/ext/asio/asio/ssl/detail/openssl_context_service.hpp
+++ b/ext/asio/asio/ssl/detail/openssl_context_service.hpp
@@ -1,9 +1,9 @@
//
-// openssl_context_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// ssl/detail/openssl_context_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-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)
@@ -16,21 +16,18 @@
# 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 <cstring>
#include <string>
#include <boost/function.hpp>
-#include "asio/detail/pop_options.hpp"
-
#include "asio/error.hpp"
#include "asio/io_service.hpp"
-#include "asio/detail/service_base.hpp"
#include "asio/ssl/context_base.hpp"
#include "asio/ssl/detail/openssl_init.hpp"
#include "asio/ssl/detail/openssl_types.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace ssl {
namespace detail {
diff --git a/ext/asio/asio/ssl/detail/openssl_init.hpp b/ext/asio/asio/ssl/detail/openssl_init.hpp
index 9ecbb78ffd..dcda50f32c 100755
--- a/ext/asio/asio/ssl/detail/openssl_init.hpp
+++ b/ext/asio/asio/ssl/detail/openssl_init.hpp
@@ -1,9 +1,9 @@
//
-// openssl_init.hpp
-// ~~~~~~~~~~~~~~~~
+// ssl/detail/openssl_init.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-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)
@@ -16,20 +16,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 <cstring>
#include <vector>
#include <boost/assert.hpp>
-#include <boost/config.hpp>
#include <boost/shared_ptr.hpp>
-#include "asio/detail/pop_options.hpp"
-
#include "asio/detail/mutex.hpp"
#include "asio/detail/tss_ptr.hpp"
#include "asio/ssl/detail/openssl_types.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
namespace ssl {
namespace detail {
diff --git a/ext/asio/asio/ssl/detail/openssl_operation.hpp b/ext/asio/asio/ssl/detail/openssl_operation.hpp
index 8d237e3616..c5119a5915 100755
--- a/ext/asio/asio/ssl/detail/openssl_operation.hpp
+++ b/ext/asio/asio/ssl/detail/openssl_operation.hpp
@@ -1,6 +1,6 @@
//
-// openssl_operation.hpp
-// ~~~~~~~~~~~~~~~~~~~~~
+// ssl/detail/openssl_operation.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
//
@@ -15,19 +15,19 @@
# 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/function.hpp>
#include <boost/assert.hpp>
#include <boost/bind.hpp>
-#include "asio/detail/pop_options.hpp"
-
#include "asio/buffer.hpp"
-#include "asio/placeholders.hpp"
-#include "asio/write.hpp"
#include "asio/detail/socket_ops.hpp"
+#include "asio/placeholders.hpp"
#include "asio/ssl/detail/openssl_types.hpp"
+#include "asio/strand.hpp"
+#include "asio/system_error.hpp"
+#include "asio/write.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace ssl {
@@ -160,7 +160,7 @@ public:
if (error_code == SSL_ERROR_SSL)
return handler_(asio::error_code(
- error_code, asio::error::get_ssl_category()), rc);
+ sys_error_code, asio::error::get_ssl_category()), rc);
bool is_read_needed = (error_code == SSL_ERROR_WANT_READ);
bool is_write_needed = (error_code == SSL_ERROR_WANT_WRITE ||
@@ -195,7 +195,7 @@ public:
else
{
return handler_(asio::error_code(
- error_code, asio::error::get_ssl_category()), rc);
+ sys_error_code, asio::error::get_ssl_category()), rc);
}
}
diff --git a/ext/asio/asio/ssl/detail/openssl_stream_service.hpp b/ext/asio/asio/ssl/detail/openssl_stream_service.hpp
index d7bb457a9e..aef9e7e955 100644
--- a/ext/asio/asio/ssl/detail/openssl_stream_service.hpp
+++ b/ext/asio/asio/ssl/detail/openssl_stream_service.hpp
@@ -1,9 +1,9 @@
//
-// stream_service.hpp
-// ~~~~~~~~~~~~~~~~~~
+// ssl/detail/stream_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-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)
@@ -16,9 +16,7 @@
# 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 <climits>
#include <memory>
@@ -26,17 +24,17 @@
#include <boost/noncopyable.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/buffer_sequence_adapter.hpp"
#include "asio/error.hpp"
#include "asio/io_service.hpp"
-#include "asio/strand.hpp"
-#include "asio/detail/buffer_sequence_adapter.hpp"
-#include "asio/detail/service_base.hpp"
#include "asio/ssl/basic_context.hpp"
#include "asio/ssl/stream_base.hpp"
#include "asio/ssl/detail/openssl_operation.hpp"
#include "asio/ssl/detail/openssl_types.hpp"
+#include "asio/strand.hpp"
+#include "asio/system_error.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace ssl {
@@ -92,7 +90,7 @@ private:
: base_handler<Stream>(io_service)
, handler_(handler)
{
- set_func(boost::bind(
+ this->set_func(boost::bind(
&io_handler<Stream, Handler>::handler_impl,
this, boost::arg<1>(), boost::arg<2>() ));
}
@@ -116,7 +114,7 @@ private:
: base_handler<Stream>(io_service)
, handler_(handler)
{
- set_func(boost::bind(
+ this->set_func(boost::bind(
&handshake_handler<Stream, Handler>::handler_impl,
this, boost::arg<1>(), boost::arg<2>() ));
}
@@ -141,7 +139,7 @@ private:
: base_handler<Stream>(io_service),
handler_(handler)
{
- set_func(boost::bind(
+ this->set_func(boost::bind(
&shutdown_handler<Stream, Handler>::handler_impl,
this, boost::arg<1>(), boost::arg<2>() ));
}
diff --git a/ext/asio/asio/ssl/detail/openssl_types.hpp b/ext/asio/asio/ssl/detail/openssl_types.hpp
index c697d7400c..fbe1b74370 100755
--- a/ext/asio/asio/ssl/detail/openssl_types.hpp
+++ b/ext/asio/asio/ssl/detail/openssl_types.hpp
@@ -1,8 +1,8 @@
//
-// openssl_types.hpp
-// ~~~~~~~~~~~~~~~~~
+// ssl/detail/openssl_types.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-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,11 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/detail/socket_types.hpp"
-
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
#include <openssl/conf.h>
#include <openssl/ssl.h>
#include <openssl/engine.h>
#include <openssl/err.h>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/detail/pop_options.hpp"
+#include "asio/detail/socket_types.hpp"
#endif // ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP
diff --git a/ext/asio/asio/ssl/stream.hpp b/ext/asio/asio/ssl/stream.hpp
index e800e626ab..e16cd9a35e 100644
--- a/ext/asio/asio/ssl/stream.hpp
+++ b/ext/asio/asio/ssl/stream.hpp
@@ -1,9 +1,9 @@
//
-// stream.hpp
-// ~~~~~~~~~~
+// ssl/stream.hpp
+// ~~~~~~~~~~~~~~
//
// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-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)
@@ -16,20 +16,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/config.hpp>
#include <boost/noncopyable.hpp>
#include <boost/type_traits/remove_reference.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/throw_error.hpp"
#include "asio/error.hpp"
#include "asio/ssl/basic_context.hpp"
#include "asio/ssl/stream_base.hpp"
#include "asio/ssl/stream_service.hpp"
-#include "asio/detail/throw_error.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace ssl {
diff --git a/ext/asio/asio/ssl/stream_base.hpp b/ext/asio/asio/ssl/stream_base.hpp
index d62d386ae5..e1cc0d72c5 100755
--- a/ext/asio/asio/ssl/stream_base.hpp
+++ b/ext/asio/asio/ssl/stream_base.hpp
@@ -1,8 +1,8 @@
//
-// stream_base.hpp
-// ~~~~~~~~~~~~~~~
+// ssl/stream_base.hpp
+// ~~~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-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,10 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+#include <boost/detail/workaround.hpp>
#include "asio/detail/push_options.hpp"
-#include <boost/detail/workaround.hpp>
-#include "asio/detail/pop_options.hpp"
namespace asio {
namespace ssl {
diff --git a/ext/asio/asio/ssl/stream_service.hpp b/ext/asio/asio/ssl/stream_service.hpp
index 1f1e6ad96d..d99548e333 100644
--- a/ext/asio/asio/ssl/stream_service.hpp
+++ b/ext/asio/asio/ssl/stream_service.hpp
@@ -1,9 +1,9 @@
//
-// stream_service.hpp
-// ~~~~~~~~~~~~~~~~~~
+// ssl/stream_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2005-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)
@@ -16,19 +16,15 @@
# 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/noncopyable.hpp>
-#include "asio/detail/pop_options.hpp"
-
#include "asio/io_service.hpp"
-#include "asio/detail/service_base.hpp"
#include "asio/ssl/basic_context.hpp"
-#include "asio/ssl/stream_base.hpp"
#include "asio/ssl/detail/openssl_stream_service.hpp"
+#include "asio/ssl/stream_base.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace ssl {
diff --git a/ext/asio/asio/strand.hpp b/ext/asio/asio/strand.hpp
index 6b321513dd..5a526f24a3 100644
--- a/ext/asio/asio/strand.hpp
+++ b/ext/asio/asio/strand.hpp
@@ -2,7 +2,7 @@
// strand.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/io_service.hpp"
+#include "asio/detail/config.hpp"
#include "asio/detail/strand_service.hpp"
#include "asio/detail/wrapped_handler.hpp"
+#include "asio/io_service.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
diff --git a/ext/asio/asio/stream_socket_service.hpp b/ext/asio/asio/stream_socket_service.hpp
index 1c4935c123..553719ecec 100644
--- a/ext/asio/asio/stream_socket_service.hpp
+++ b/ext/asio/asio/stream_socket_service.hpp
@@ -2,7 +2,7 @@
// stream_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 stream socket.
diff --git a/ext/asio/asio/streambuf.hpp b/ext/asio/asio/streambuf.hpp
index 665155be84..553da3e56b 100644
--- a/ext/asio/asio/streambuf.hpp
+++ b/ext/asio/asio/streambuf.hpp
@@ -2,7 +2,7 @@
// 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,12 +15,12 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/basic_streambuf.hpp"
+#include "asio/detail/config.hpp"
#if !defined(BOOST_NO_IOSTREAM)
+#include "asio/basic_streambuf.hpp"
+
namespace asio {
/// Typedef for the typical usage of basic_streambuf.
@@ -30,6 +30,4 @@ typedef basic_streambuf<> streambuf;
#endif // !defined(BOOST_NO_IOSTREAM)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_STREAMBUF_HPP
diff --git a/ext/asio/asio/system_error.hpp b/ext/asio/asio/system_error.hpp
index e704b3fb90..60580a11aa 100644
--- a/ext/asio/asio/system_error.hpp
+++ b/ext/asio/asio/system_error.hpp
@@ -2,7 +2,7 @@
// system_error.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,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/config.hpp"
#include <boost/scoped_ptr.hpp>
#include <cerrno>
#include <exception>
#include <string>
-#include "asio/detail/pop_options.hpp"
-
#include "asio/error_code.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
/// The system_error class is used to represent system conditions that
diff --git a/ext/asio/asio/thread.hpp b/ext/asio/asio/thread.hpp
index 9e578bc598..070483ef55 100644
--- a/ext/asio/asio/thread.hpp
+++ b/ext/asio/asio/thread.hpp
@@ -2,7 +2,7 @@
// thread.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/thread.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
/// A simple abstraction for starting threads.
diff --git a/ext/asio/asio/time_traits.hpp b/ext/asio/asio/time_traits.hpp
index 0371373689..3b2899b166 100644
--- a/ext/asio/asio/time_traits.hpp
+++ b/ext/asio/asio/time_traits.hpp
@@ -2,7 +2,7 @@
// time_traits.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,14 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
#include "asio/detail/socket_types.hpp" // Must come before posix_time.
#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 {
/// Time traits suitable for use with the deadline timer.
diff --git a/ext/asio/asio/version.hpp b/ext/asio/asio/version.hpp
index 198f5086fa..0402d0eb38 100644
--- a/ext/asio/asio/version.hpp
+++ b/ext/asio/asio/version.hpp
@@ -2,7 +2,7 @@
// version.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)
@@ -18,6 +18,6 @@
// ASIO_VERSION % 100 is the sub-minor version
// ASIO_VERSION / 100 % 1000 is the minor version
// ASIO_VERSION / 100000 is the major version
-#define ASIO_VERSION 100405 // 1.4.5
+#define ASIO_VERSION 100408 // 1.4.8
#endif // ASIO_VERSION_HPP
diff --git a/ext/asio/asio/windows/basic_handle.hpp b/ext/asio/asio/windows/basic_handle.hpp
index 8c2ee60ebb..f87b3db8e2 100644
--- a/ext/asio/asio/windows/basic_handle.hpp
+++ b/ext/asio/asio/windows/basic_handle.hpp
@@ -1,8 +1,8 @@
//
-// basic_handle.hpp
-// ~~~~~~~~~~~~~~~~
+// windows/basic_handle.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,17 @@
# 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(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
+ || defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \
+ || defined(GENERATING_DOCUMENTATION)
#include "asio/basic_io_object.hpp"
-#include "asio/error.hpp"
#include "asio/detail/throw_error.hpp"
+#include "asio/error.hpp"
+
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace windows {
@@ -222,4 +224,8 @@ protected:
#include "asio/detail/pop_options.hpp"
+#endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
+ // || defined(ASIO_HAS_WINDOWS_STREAM_HANDLE)
+ // || defined(GENERATING_DOCUMENTATION)
+
#endif // ASIO_WINDOWS_BASIC_HANDLE_HPP
diff --git a/ext/asio/asio/windows/basic_random_access_handle.hpp b/ext/asio/asio/windows/basic_random_access_handle.hpp
index 2e6b994e0b..056b175794 100644
--- a/ext/asio/asio/windows/basic_random_access_handle.hpp
+++ b/ext/asio/asio/windows/basic_random_access_handle.hpp
@@ -1,8 +1,8 @@
//
-// basic_random_access_handle.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// windows/basic_random_access_handle.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,18 @@
# 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 <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
+ || defined(GENERATING_DOCUMENTATION)
+#include <cstddef>
+#include "asio/detail/throw_error.hpp"
#include "asio/error.hpp"
#include "asio/windows/basic_handle.hpp"
#include "asio/windows/random_access_handle_service.hpp"
-#include "asio/detail/throw_error.hpp"
-#if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
- || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace windows {
@@ -312,9 +310,9 @@ public:
} // namespace windows
} // namespace asio
+#include "asio/detail/pop_options.hpp"
+
#endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
// || defined(GENERATING_DOCUMENTATION)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP
diff --git a/ext/asio/asio/windows/basic_stream_handle.hpp b/ext/asio/asio/windows/basic_stream_handle.hpp
index 48e7153da6..28149f4cca 100644
--- a/ext/asio/asio/windows/basic_stream_handle.hpp
+++ b/ext/asio/asio/windows/basic_stream_handle.hpp
@@ -1,8 +1,8 @@
//
-// basic_stream_handle.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~
+// windows/basic_stream_handle.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,18 @@
# 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 <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \
+ || defined(GENERATING_DOCUMENTATION)
+#include <cstddef>
#include "asio/error.hpp"
#include "asio/windows/basic_handle.hpp"
#include "asio/windows/stream_handle_service.hpp"
#include "asio/detail/throw_error.hpp"
-#if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \
- || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace windows {
@@ -294,9 +292,9 @@ public:
} // namespace windows
} // namespace asio
+#include "asio/detail/pop_options.hpp"
+
#endif // defined(ASIO_HAS_WINDOWS_STREAM_HANDLE)
// || defined(GENERATING_DOCUMENTATION)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP
diff --git a/ext/asio/asio/windows/overlapped_ptr.hpp b/ext/asio/asio/windows/overlapped_ptr.hpp
index 087170b5a0..8f4d628e0c 100644
--- a/ext/asio/asio/windows/overlapped_ptr.hpp
+++ b/ext/asio/asio/windows/overlapped_ptr.hpp
@@ -1,8 +1,8 @@
//
-// overlapped_ptr.hpp
-// ~~~~~~~~~~~~~~~~~~
+// windows/overlapped_ptr.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,16 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_WINDOWS_OVERLAPPED_PTR) \
+ || defined(GENERATING_DOCUMENTATION)
-#include "asio/io_service.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/win_iocp_overlapped_ptr.hpp"
+#include "asio/io_service.hpp"
-#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)
-
-#if defined(ASIO_HAS_WINDOWS_OVERLAPPED_PTR) \
- || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace windows {
@@ -110,9 +106,9 @@ private:
} // namespace windows
} // namespace asio
+#include "asio/detail/pop_options.hpp"
+
#endif // defined(ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
// || defined(GENERATING_DOCUMENTATION)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_WINDOWS_OVERLAPPED_PTR_HPP
diff --git a/ext/asio/asio/windows/random_access_handle.hpp b/ext/asio/asio/windows/random_access_handle.hpp
index 6e5dd7b6fc..727b084cab 100644
--- a/ext/asio/asio/windows/random_access_handle.hpp
+++ b/ext/asio/asio/windows/random_access_handle.hpp
@@ -1,8 +1,8 @@
//
-// random_access_handle.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~
+// windows/random_access_handle.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,13 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/windows/basic_random_access_handle.hpp"
+#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
|| defined(GENERATING_DOCUMENTATION)
+#include "asio/windows/basic_random_access_handle.hpp"
+
namespace asio {
namespace windows {
@@ -34,6 +34,4 @@ typedef basic_random_access_handle<> random_access_handle;
#endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
// || defined(GENERATING_DOCUMENTATION)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_HPP
diff --git a/ext/asio/asio/windows/random_access_handle_service.hpp b/ext/asio/asio/windows/random_access_handle_service.hpp
index 2e579f82e6..b2c05efc31 100644
--- a/ext/asio/asio/windows/random_access_handle_service.hpp
+++ b/ext/asio/asio/windows/random_access_handle_service.hpp
@@ -1,8 +1,8 @@
//
-// random_access_handle_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// windows/random_access_handle_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,27 +15,19 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
+#include "asio/detail/config.hpp"
+
+#if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
+ || defined(GENERATING_DOCUMENTATION)
-#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include <boost/cstdint.hpp>
-#include "asio/detail/pop_options.hpp"
-
+#include "asio/detail/win_iocp_handle_service.hpp"
#include "asio/error.hpp"
#include "asio/io_service.hpp"
-#include "asio/detail/service_base.hpp"
-#include "asio/detail/win_iocp_handle_service.hpp"
-#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)
-
-#if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
- || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace windows {
@@ -172,9 +164,9 @@ private:
} // namespace windows
} // namespace asio
+#include "asio/detail/pop_options.hpp"
+
#endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
// || defined(GENERATING_DOCUMENTATION)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP
diff --git a/ext/asio/asio/windows/stream_handle.hpp b/ext/asio/asio/windows/stream_handle.hpp
index d55dc3174a..802d157614 100644
--- a/ext/asio/asio/windows/stream_handle.hpp
+++ b/ext/asio/asio/windows/stream_handle.hpp
@@ -1,8 +1,8 @@
//
-// stream_handle.hpp
-// ~~~~~~~~~~~~~~~~~~
+// windows/stream_handle.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,13 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include "asio/detail/push_options.hpp"
-
-#include "asio/windows/basic_stream_handle.hpp"
+#include "asio/detail/config.hpp"
#if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \
|| defined(GENERATING_DOCUMENTATION)
+#include "asio/windows/basic_stream_handle.hpp"
+
namespace asio {
namespace windows {
@@ -34,6 +34,4 @@ typedef basic_stream_handle<> stream_handle;
#endif // defined(ASIO_HAS_WINDOWS_STREAM_HANDLE)
// || defined(GENERATING_DOCUMENTATION)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_WINDOWS_STREAM_HANDLE_HPP
diff --git a/ext/asio/asio/windows/stream_handle_service.hpp b/ext/asio/asio/windows/stream_handle_service.hpp
index 75eff60a6e..816cfe556b 100644
--- a/ext/asio/asio/windows/stream_handle_service.hpp
+++ b/ext/asio/asio/windows/stream_handle_service.hpp
@@ -1,8 +1,8 @@
//
-// stream_handle_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~
+// windows/stream_handle_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,26 +15,17 @@
# 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 <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
+#if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \
+ || defined(GENERATING_DOCUMENTATION)
+#include <cstddef>
+#include "asio/detail/win_iocp_handle_service.hpp"
#include "asio/error.hpp"
#include "asio/io_service.hpp"
-#include "asio/detail/service_base.hpp"
-#include "asio/detail/win_iocp_handle_service.hpp"
-#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)
-
-#if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \
- || defined(GENERATING_DOCUMENTATION)
+#include "asio/detail/push_options.hpp"
namespace asio {
namespace windows {
@@ -170,9 +161,9 @@ private:
} // namespace windows
} // namespace asio
+#include "asio/detail/pop_options.hpp"
+
#endif // defined(ASIO_HAS_WINDOWS_STREAM_HANDLE)
// || defined(GENERATING_DOCUMENTATION)
-#include "asio/detail/pop_options.hpp"
-
#endif // ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP
diff --git a/ext/asio/asio/write.hpp b/ext/asio/asio/write.hpp
index 2b188cde4c..bd90ecb069 100644
--- a/ext/asio/asio/write.hpp
+++ b/ext/asio/asio/write.hpp
@@ -2,7 +2,7 @@
// write.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 "asio/detail/config.hpp"
#include <cstddef>
-#include <boost/config.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/basic_streambuf.hpp"
+#include "asio/basic_streambuf_fwd.hpp"
#include "asio/error.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
/**
@@ -533,8 +530,8 @@ void async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b,
} // namespace asio
-#include "asio/impl/write.ipp"
-
#include "asio/detail/pop_options.hpp"
+#include "asio/impl/write.hpp"
+
#endif // ASIO_WRITE_HPP
diff --git a/ext/asio/asio/write_at.hpp b/ext/asio/asio/write_at.hpp
index 5690bcfda1..37d0cbb2ea 100644
--- a/ext/asio/asio/write_at.hpp
+++ b/ext/asio/asio/write_at.hpp
@@ -2,7 +2,7 @@
// write_at.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 <boost/cstdint.hpp>
-#include "asio/detail/pop_options.hpp"
-
-#include "asio/basic_streambuf.hpp"
+#include "asio/basic_streambuf_fwd.hpp"
#include "asio/error.hpp"
+#include "asio/detail/push_options.hpp"
+
namespace asio {
/**
@@ -556,8 +553,8 @@ void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset,
} // namespace asio
-#include "asio/impl/write_at.ipp"
-
#include "asio/detail/pop_options.hpp"
+#include "asio/impl/write_at.hpp"
+
#endif // ASIO_WRITE_AT_HPP