mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 05:55:28 +00:00
Merge branch 'master' into trac684
This commit is contained in:
134
ChangeLog
134
ChangeLog
@@ -1,4 +1,126 @@
|
||||
222. [bug] jerry
|
||||
238. [func] zhang likun
|
||||
Implement the simplest forwarder, which pass everything throught
|
||||
except QID, port number. The response will not be cached.
|
||||
(Trac #598_new, git 8e28187a582820857ef2dae9b13637a3881f13ba)
|
||||
|
||||
237. [bug] naokikambe
|
||||
Resolved that the stats module wasn't configurable in bindctl in
|
||||
spite of its having configuration items. The configuration part
|
||||
was removed from the original spec file "stats.spec" and was
|
||||
placed in a new spec file "stats-schema.spec". Because it means
|
||||
definitions of statistics items. The command part is still
|
||||
there. Thus stats module currently has no its own configuration,
|
||||
and the items in "stats-schema.spec" are neither visible nor
|
||||
configurable through bindctl. "stats-schema.spec" is shared with
|
||||
stats module and stats-httpd module, and maybe with other
|
||||
statistical modules in future. "stats.spec" has own configuration
|
||||
and commands of stats module, if it requires.
|
||||
(Trac#719, git a234b20dc6617392deb8a1e00eb0eed0ff353c0a)
|
||||
|
||||
236. [func] jelte
|
||||
C++ client side of configuration now uses BIND10 logging system.
|
||||
It also has improved error handling when communicating with the
|
||||
rest of the system.
|
||||
(Trac #743, git 86632c12308c3ed099d75eb828f740c526dd7ec0)
|
||||
|
||||
235. [func] jinmei
|
||||
libdns++: added support for TSIG signing and verification. It can
|
||||
be done using a newly introduced TSIGContext class.
|
||||
Note: we temporarily disabled support for truncated signature
|
||||
and modified some part of the code introduced in #226 accordingly.
|
||||
We plan to fix this pretty soon.
|
||||
(Trac #812, git ebe0c4b1e66d359227bdd1bd47395fee7b957f14)
|
||||
(Trac #871, git 7c54055c0e47c7a0e36fcfab4b47ff180c0ca8c8)
|
||||
(Trac #813, git ffa2f0672084c1f16e5784cdcdd55822f119feaa)
|
||||
(Trac #893, git 5aaa6c0f628ed7c2093ecdbac93a2c8cf6c94349)
|
||||
|
||||
234. [func] jerry
|
||||
src/bin/xfrin: update xfrin to use TSIG. Currently it only supports
|
||||
sending a signed TSIG request or SOA request.
|
||||
(Trac #815, git a892818fb13a1839c82104523cb6cb359c970e88)
|
||||
|
||||
233. [func] stephen
|
||||
Added new-style logging statements to the NSAS code.
|
||||
(Trac #745, git ceef68cd1223ae14d8412adbe18af2812ade8c2d)
|
||||
|
||||
232. [func] stephen
|
||||
To facilitate the writing of extended descriptions in
|
||||
message files, altered the message file format. The message
|
||||
is now flagged with a "%" as the first non-blank character
|
||||
in the line and the lines in the extended description are
|
||||
no longer preceded by a "+".
|
||||
(Trac #900, git b395258c708b49a5da8d0cffcb48d83294354ba3)
|
||||
|
||||
231. [func]* vorner
|
||||
The logging interface changed slightly. We use
|
||||
logger.foo(MESSAGE_ID).arg(bar); instead of logger.foo(MESSAGE_ID,
|
||||
bar); internally. The message definitions use '%1,%2,...'
|
||||
instead of '%s,%d', which allows us to cope better with
|
||||
mismatched placeholders and allows reordering of them in
|
||||
case of translation.
|
||||
(Trac901, git 4903410e45670b30d7283f5d69dc28c2069237d6)
|
||||
|
||||
230. [bug] naokikambe
|
||||
Removed too repeated verbose messages in two cases of:
|
||||
- when auth sends statistics data to stats
|
||||
- when stats receives statistics data from other modules
|
||||
(Trac#620, git 0ecb807011196eac01f281d40bc7c9d44565b364)
|
||||
|
||||
229. [doc] jreed
|
||||
Add manual page for b10-host.
|
||||
(git a437d4e26b81bb07181ff35a625c540703eee845)
|
||||
|
||||
228. [func]* jreed
|
||||
The host tool is renamed to b10-host. While the utility is
|
||||
a work in progress, it is expected to now be shipped with
|
||||
tarballs. Its initial goal was to be a host(1) clone,
|
||||
rewritten in C++ from scratch and using BIND 10's libdns++.
|
||||
It now supports the -a (any), -c class, -d (verbose) switches
|
||||
and has improved output.
|
||||
(Trac #872, git d846851699d5c76937533adf9ff9d948dfd593ca)
|
||||
|
||||
227. [build] jreed
|
||||
Add missing libdns++ rdata files for the distribution (this
|
||||
fixes distcheck error). Change three generated libdns++
|
||||
headers to "nodist" so they aren't included in the distribution
|
||||
(they were mistakenly included in last tarball).
|
||||
|
||||
226. [func]* jelte
|
||||
Introduced an API for cryptographic operations. Currently it only
|
||||
supports HMAC, intended for use with TSIG. The current
|
||||
implementation uses Botan as the backend library.
|
||||
This introduces a new dependency, on Botan. Currently only Botan
|
||||
1.8.x works; older or newer versions don't.
|
||||
(Trac #781, git 9df42279a47eb617f586144dce8cce680598558a)
|
||||
|
||||
225. [func] naokikambe
|
||||
Added the HTTP/XML interface(b10-stats-httpd) to the
|
||||
statistics feature in BIND 10. b10-stats-httpd is a standalone
|
||||
HTTP server and it requests statistics data to the stats
|
||||
daemon(b10-stats) and sends it to HTTP clients in XML
|
||||
format. Items of the data collected via b10-stats-httpd
|
||||
are almost equivalent to ones which are collected via
|
||||
bindctl. Since it also can send XSL(Extensible Stylessheet
|
||||
Language) document and XSD(XML Schema definition) document,
|
||||
XML document is human-friendly to view through web browsers
|
||||
and its data types are strictly defined.
|
||||
(Trac #547, git 1cbd51919237a6e65983be46e4f5a63d1877b1d3)
|
||||
|
||||
224. [bug] jinmei
|
||||
b10-auth, src/lib/datasrc: inconsistency between the hot spot
|
||||
cache and actual data source could cause a crash while query
|
||||
processing. The crash could happen, e.g., when an sqlite3 DB file
|
||||
is being updated after a zone transfer while b10-auth handles a
|
||||
query using the corresponding sqlite3 data source.
|
||||
(Trac #851, git 2463b96680bb3e9a76e50c38a4d7f1d38d810643)
|
||||
|
||||
223. [bug] feng
|
||||
If ip address or port isn't usable for name server, name
|
||||
server process won't exist and give end user chance to
|
||||
reconfigure them.
|
||||
(Trac #775, git 572ac2cf62e18f7eb69d670b890e2a3443bfd6e7)
|
||||
|
||||
222. [bug] jerry
|
||||
src/lib/zonemgr: Fix a bug that xfrin not checking for new copy of
|
||||
zone on startup. Imposes some random jitters to avoid many zones
|
||||
need to do refresh at the same time.
|
||||
@@ -13,7 +135,7 @@
|
||||
(potentially) bad packets to a nameserver and prints the responses.
|
||||
(Trac #703, git 1b666838b6c0fe265522b30971e878d9f0d21fde)
|
||||
|
||||
219. [func] ocean
|
||||
219. [func] ocean
|
||||
src/lib: move some dns related code out of asiolink library to
|
||||
asiodns library
|
||||
(Trac #751, git 262ac6c6fc61224d54705ed4c700dadb606fcb1c)
|
||||
@@ -23,9 +145,9 @@
|
||||
(Trac #806, git 4e47d5f6b692c63c907af6681a75024450884a88)
|
||||
|
||||
217. [bug] jerry
|
||||
src/lib/dns/python: Use a signed version of larger size of integer and
|
||||
perform more strict range checks with PyArg_ParseTuple() in case of
|
||||
overflows.
|
||||
src/lib/dns/python: Use a signed version of larger size of
|
||||
integer and perform more strict range checks with
|
||||
PyArg_ParseTuple() in case of overflows.
|
||||
(Trac #363, git ce281e646be9f0f273229d94ccd75bf7e08d17cf)
|
||||
|
||||
216. [func] vorner
|
||||
@@ -1047,7 +1169,7 @@ bind10-devel-20100701 released on July 1, 2010
|
||||
55. [bug] shane
|
||||
bin/xfrout: xfrout exception on Ctrl-C now no longer generates
|
||||
exception for 'Interrupted system call'
|
||||
(Track #136, svn r2147)
|
||||
(Trac #136, svn r2147)
|
||||
|
||||
54. [bug] zhanglikun
|
||||
bin/xfrout: Enable b10-xfrout can be launched in source
|
||||
|
472
Makefile.am
472
Makefile.am
@@ -84,214 +84,310 @@ systest:
|
||||
|
||||
#### include external sources in the distributed tarball:
|
||||
EXTRA_DIST = ext/asio/README
|
||||
EXTRA_DIST += ext/asio/asio/local/stream_protocol.hpp
|
||||
EXTRA_DIST += ext/asio/asio/local/basic_endpoint.hpp
|
||||
EXTRA_DIST += ext/asio/asio/local/datagram_protocol.hpp
|
||||
EXTRA_DIST += ext/asio/asio/local/connect_pair.hpp
|
||||
EXTRA_DIST += ext/asio/asio/windows/basic_handle.hpp
|
||||
EXTRA_DIST += ext/asio/asio/windows/random_access_handle.hpp
|
||||
EXTRA_DIST += ext/asio/asio/windows/random_access_handle_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/windows/basic_random_access_handle.hpp
|
||||
EXTRA_DIST += ext/asio/asio/windows/overlapped_ptr.hpp
|
||||
EXTRA_DIST += ext/asio/asio/windows/stream_handle.hpp
|
||||
EXTRA_DIST += ext/asio/asio/windows/stream_handle_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/windows/basic_stream_handle.hpp
|
||||
EXTRA_DIST += ext/asio/asio/impl/write.ipp
|
||||
EXTRA_DIST += ext/asio/asio/impl/read.ipp
|
||||
EXTRA_DIST += ext/asio/asio/impl/serial_port_base.ipp
|
||||
EXTRA_DIST += ext/asio/asio/impl/write_at.ipp
|
||||
EXTRA_DIST += ext/asio/asio/impl/read_at.ipp
|
||||
EXTRA_DIST += ext/asio/asio/impl/error_code.ipp
|
||||
EXTRA_DIST += ext/asio/asio/impl/read_until.ipp
|
||||
EXTRA_DIST += ext/asio/asio/impl/io_service.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_serial_port_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactive_socket_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/wince_thread.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_event.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/descriptor_ops.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/pipe_select_interrupter.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/task_io_service_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/handler_alloc_helpers.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/pop_options.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/strand_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/buffer_resize_guard.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_io_service_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/timer_scheduler.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/kqueue_reactor_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/hash_map.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/event.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/buffered_stream_storage.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/posix_mutex.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/timer_queue_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/deadline_timer_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/posix_fd_set_adapter.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/service_registry.hpp
|
||||
EXTRA_DIST += ext/asio/README
|
||||
EXTRA_DIST += ext/asio/asio.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_socket.hpp
|
||||
EXTRA_DIST += ext/asio/asio/streambuf.hpp
|
||||
EXTRA_DIST += ext/asio/asio/thread.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/wait_handler.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/resolve_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/gcc_hppa_fenced_block.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/null_fenced_block.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/task_io_service_operation.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/epoll_reactor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/local_free_on_block_exit.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/socket_select_interrupter.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/null_mutex.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactor_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/fenced_block.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/tss_ptr.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/timer_queue_set.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/winsock_init.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/signal_init.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/call_stack.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/operation.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/posix_signal_blocker.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_handle_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/fd_set_adapter.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/io_control.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/null_signal_blocker.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/socket_ops.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/bind_handler.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_overlapped_ptr.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/timer_scheduler_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/signal_blocker.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/consuming_buffers.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/socket_option.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_fd_set_adapter.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/select_interrupter.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/null_buffers_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/socket_holder.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/scoped_lock.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/service_registry_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/base_from_completion_cond.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/posix_thread.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/solaris_fenced_block.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/epoll_reactor_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/push_options.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_signal_blocker.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/eventfd_select_interrupter.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/select_reactor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/old_win_sdk_compat.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactor_op_queue.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/null_thread.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/buffer_sequence_adapter.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/posix_event.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/thread.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/handler_invoke_helpers.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/null_event.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/service_id.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/socket_types.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/throw_error.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/timer_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_mutex.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactive_descriptor_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/resolver_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/op_queue.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/dev_poll_reactor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_thread.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_operation.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/service_base.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/select_reactor_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactor_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/wrapped_handler.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/mutex.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/completion_handler.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/noncopyable.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/task_io_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/gcc_fenced_block.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_fenced_block.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_tss_ptr.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/kqueue_reactor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/timer_queue_base.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_io_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/gcc_x86_fenced_block.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/posix_tss_ptr.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/eventfd_select_interrupter.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/task_io_service_operation.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/service_base.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/task_io_service_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/null_buffers_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_handle_write_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/thread.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/select_reactor_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/event.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactive_descriptor_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_overlapped_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactive_socket_recv_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/macos_fenced_block.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/dev_poll_reactor_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/timer_queue.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactive_socket_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/posix_tss_ptr.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/local_free_on_block_exit.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/timer_scheduler.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/signal_blocker.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/resolver_service_base.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/socket_holder.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/dev_poll_reactor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/select_reactor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/gcc_arm_fenced_block.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/consuming_buffers.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactor_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/base_from_completion_cond.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/epoll_reactor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/bind_handler.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/strand_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/op_queue.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_mutex.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_operation.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/pipe_select_interrupter.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/wince_thread.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/buffered_stream_storage.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/mutex.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/posix_mutex.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactor_op_queue.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_event.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/select_interrupter.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/io_control.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/buffer_sequence_adapter.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_io_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_handle_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_send_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/epoll_reactor_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/operation.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/descriptor_ops.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/shared_ptr.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/winsock_init.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/timer_queue_set.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/completion_handler.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactive_serial_port_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/fenced_block.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/null_event.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/hash_map.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/gcc_sync_fenced_block.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_tss_ptr.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_fd_set_adapter.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_null_buffers_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/timer_queue_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/old_win_sdk_compat.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/call_stack.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/weak_ptr.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_accept_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/gcc_x86_fenced_block.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/gcc_fenced_block.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/null_mutex.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactive_socket_recvfrom_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/posix_event.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/service_id.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/kqueue_reactor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/regex_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactive_socket_sendto_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/push_options.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/null_thread.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/socket_select_interrupter.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_service_base.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/throw_error.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/null_signal_blocker.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactive_socket_accept_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/wrapped_handler.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/object_pool.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/timer_scheduler_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/resolve_endpoint_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/array_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/config.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/socket_option.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_overlapped_ptr.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_fenced_block.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/socket_types.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/null_tss_ptr.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_stream_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_operation.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_init.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_context_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_types.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/stream.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/stream_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/handler_invoke_helpers.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactive_socket_send_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactive_null_buffers_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/pop_options.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/resolver_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactive_socket_service_base.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/descriptor_read_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactive_socket_connect_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/timer_queue_base.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/reactor_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_recvfrom_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_serial_port_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/tss_ptr.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/buffer_resize_guard.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/kqueue_reactor_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_thread.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/deadline_timer_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_socket_recv_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/timer_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/posix_thread.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/signal_init.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/descriptor_write_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_signal_blocker.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/reactive_socket_service_base.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/win_mutex.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/posix_event.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/win_iocp_io_service.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/select_reactor.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/posix_tss_ptr.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/task_io_service.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/dev_poll_reactor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/select_reactor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/eventfd_select_interrupter.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/epoll_reactor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/strand_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/winsock_init.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/pipe_select_interrupter.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/win_iocp_serial_port_service.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/dev_poll_reactor.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/win_iocp_io_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/strand_service.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/win_iocp_socket_service_base.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/timer_queue.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/posix_mutex.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/reactive_serial_port_service.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/socket_ops.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/socket_select_interrupter.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/posix_thread.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/reactive_descriptor_service.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/kqueue_reactor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/kqueue_reactor.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/win_event.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/timer_queue_set.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/win_tss_ptr.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/win_iocp_handle_service.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/resolver_service_base.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/win_thread.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/task_io_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/throw_error.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/epoll_reactor.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/service_registry.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/descriptor_ops.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/impl/service_registry.ipp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_io_service_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/fd_set_adapter.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/task_io_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/solaris_fenced_block.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/timer_queue.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/handler_alloc_helpers.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/scoped_lock.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/win_iocp_handle_read_op.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/service_registry_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/service_registry.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/posix_fd_set_adapter.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/socket_ops.hpp
|
||||
EXTRA_DIST += ext/asio/asio/detail/posix_signal_blocker.hpp
|
||||
EXTRA_DIST += ext/asio/asio/serial_port_base.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/context_base.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/context.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/context_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_types.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_context_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_stream_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_operation.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/detail/openssl_init.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/basic_context.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/stream_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/stream.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl/stream_base.hpp
|
||||
EXTRA_DIST += ext/asio/asio/posix/stream_descriptor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/posix/stream_descriptor_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_streambuf.hpp
|
||||
EXTRA_DIST += ext/asio/asio/serial_port_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/error.hpp
|
||||
EXTRA_DIST += ext/asio/asio/handler_alloc_hook.hpp
|
||||
EXTRA_DIST += ext/asio/asio/buffers_iterator.hpp
|
||||
EXTRA_DIST += ext/asio/asio/is_read_buffered.hpp
|
||||
EXTRA_DIST += ext/asio/asio/buffered_stream_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/placeholders.hpp
|
||||
EXTRA_DIST += ext/asio/asio/local/stream_protocol.hpp
|
||||
EXTRA_DIST += ext/asio/asio/local/detail/impl/endpoint.ipp
|
||||
EXTRA_DIST += ext/asio/asio/local/detail/endpoint.hpp
|
||||
EXTRA_DIST += ext/asio/asio/local/datagram_protocol.hpp
|
||||
EXTRA_DIST += ext/asio/asio/local/connect_pair.hpp
|
||||
EXTRA_DIST += ext/asio/asio/local/basic_endpoint.hpp
|
||||
EXTRA_DIST += ext/asio/asio/buffered_stream.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_serial_port.hpp
|
||||
EXTRA_DIST += ext/asio/asio/datagram_socket_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/socket_base.hpp
|
||||
EXTRA_DIST += ext/asio/asio/io_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_socket_iostream.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_io_object.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_socket_streambuf.hpp
|
||||
EXTRA_DIST += ext/asio/asio/error_code.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_stream_socket.hpp
|
||||
EXTRA_DIST += ext/asio/asio/read_until.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_streambuf_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/is_write_buffered.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_datagram_socket.hpp
|
||||
EXTRA_DIST += ext/asio/asio/buffered_write_stream_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_deadline_timer.hpp
|
||||
EXTRA_DIST += ext/asio/asio/socket_acceptor_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/raw_socket_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/buffered_read_stream.hpp
|
||||
EXTRA_DIST += ext/asio/asio/time_traits.hpp
|
||||
EXTRA_DIST += ext/asio/asio/completion_condition.hpp
|
||||
EXTRA_DIST += ext/asio/asio/posix/basic_stream_descriptor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/posix/basic_descriptor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/posix/descriptor_base.hpp
|
||||
EXTRA_DIST += ext/asio/asio/posix/stream_descriptor_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/posix/stream_descriptor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/write.hpp
|
||||
EXTRA_DIST += ext/asio/asio/write_at.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_raw_socket.hpp
|
||||
EXTRA_DIST += ext/asio/asio/serial_port.hpp
|
||||
EXTRA_DIST += ext/asio/asio/windows/basic_stream_handle.hpp
|
||||
EXTRA_DIST += ext/asio/asio/windows/basic_handle.hpp
|
||||
EXTRA_DIST += ext/asio/asio/windows/random_access_handle.hpp
|
||||
EXTRA_DIST += ext/asio/asio/windows/overlapped_ptr.hpp
|
||||
EXTRA_DIST += ext/asio/asio/windows/stream_handle.hpp
|
||||
EXTRA_DIST += ext/asio/asio/windows/random_access_handle_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/windows/stream_handle_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/windows/basic_random_access_handle.hpp
|
||||
EXTRA_DIST += ext/asio/asio/read.hpp
|
||||
EXTRA_DIST += ext/asio/asio/deadline_timer_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/buffered_write_stream.hpp
|
||||
EXTRA_DIST += ext/asio/asio/buffer.hpp
|
||||
EXTRA_DIST += ext/asio/asio/impl/read_until.ipp
|
||||
EXTRA_DIST += ext/asio/asio/impl/serial_port_base.hpp
|
||||
EXTRA_DIST += ext/asio/asio/impl/read_at.ipp
|
||||
EXTRA_DIST += ext/asio/asio/impl/read.ipp
|
||||
EXTRA_DIST += ext/asio/asio/impl/error.ipp
|
||||
EXTRA_DIST += ext/asio/asio/impl/io_service.ipp
|
||||
EXTRA_DIST += ext/asio/asio/impl/io_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/impl/src.hpp
|
||||
EXTRA_DIST += ext/asio/asio/impl/src.cpp
|
||||
EXTRA_DIST += ext/asio/asio/impl/read_until.hpp
|
||||
EXTRA_DIST += ext/asio/asio/impl/serial_port_base.ipp
|
||||
EXTRA_DIST += ext/asio/asio/impl/write.hpp
|
||||
EXTRA_DIST += ext/asio/asio/impl/write_at.hpp
|
||||
EXTRA_DIST += ext/asio/asio/impl/write.ipp
|
||||
EXTRA_DIST += ext/asio/asio/impl/read.hpp
|
||||
EXTRA_DIST += ext/asio/asio/impl/write_at.ipp
|
||||
EXTRA_DIST += ext/asio/asio/impl/error_code.ipp
|
||||
EXTRA_DIST += ext/asio/asio/impl/read_at.hpp
|
||||
EXTRA_DIST += ext/asio/asio/strand.hpp
|
||||
EXTRA_DIST += ext/asio/asio/version.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_socket_acceptor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/basic_resolver_query.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/address.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/host_name.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/detail/socket_option.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/detail/impl/endpoint.ipp
|
||||
EXTRA_DIST += ext/asio/asio/ip/detail/endpoint.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/udp.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/basic_resolver_iterator.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/v6_only.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/address_v4.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/address_v6.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/basic_resolver.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/multicast.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/unicast.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/basic_resolver_iterator.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/host_name.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/resolver_query_base.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/basic_endpoint.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/resolver_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/basic_resolver_entry.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/address.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/multicast.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/address_v6.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/tcp.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/basic_resolver_query.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/udp.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/basic_resolver_entry.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/unicast.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/resolver_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/icmp.hpp
|
||||
EXTRA_DIST += ext/asio/asio/error.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_socket.hpp
|
||||
EXTRA_DIST += ext/asio/asio/buffered_stream.hpp
|
||||
EXTRA_DIST += ext/asio/asio/system_error.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_io_object.hpp
|
||||
EXTRA_DIST += ext/asio/asio/read_at.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_raw_socket.hpp
|
||||
EXTRA_DIST += ext/asio/asio/serial_port_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_stream_socket.hpp
|
||||
EXTRA_DIST += ext/asio/asio/placeholders.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_deadline_timer.hpp
|
||||
EXTRA_DIST += ext/asio/asio/thread.hpp
|
||||
EXTRA_DIST += ext/asio/asio/buffered_write_stream_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/datagram_socket_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/basic_endpoint.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/basic_resolver.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/impl/address.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/impl/address_v4.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/impl/address_v4.ipp
|
||||
EXTRA_DIST += ext/asio/asio/ip/impl/address_v6.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/impl/address.ipp
|
||||
EXTRA_DIST += ext/asio/asio/ip/impl/host_name.ipp
|
||||
EXTRA_DIST += ext/asio/asio/ip/impl/basic_endpoint.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ip/impl/address_v6.ipp
|
||||
EXTRA_DIST += ext/asio/asio/handler_invoke_hook.hpp
|
||||
EXTRA_DIST += ext/asio/asio/is_read_buffered.hpp
|
||||
EXTRA_DIST += ext/asio/asio/buffer.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_socket_acceptor.hpp
|
||||
EXTRA_DIST += ext/asio/asio/write_at.hpp
|
||||
EXTRA_DIST += ext/asio/asio/completion_condition.hpp
|
||||
EXTRA_DIST += ext/asio/asio/raw_socket_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/socket_base.hpp
|
||||
EXTRA_DIST += ext/asio/asio/serial_port.hpp
|
||||
EXTRA_DIST += ext/asio/asio/error_code.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_serial_port.hpp
|
||||
EXTRA_DIST += ext/asio/asio/version.hpp
|
||||
EXTRA_DIST += ext/asio/asio/deadline_timer_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/io_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/buffered_read_stream.hpp
|
||||
EXTRA_DIST += ext/asio/asio/streambuf.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_datagram_socket.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_streambuf.hpp
|
||||
EXTRA_DIST += ext/asio/asio/write.hpp
|
||||
EXTRA_DIST += ext/asio/asio/strand.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_socket_iostream.hpp
|
||||
EXTRA_DIST += ext/asio/asio/buffered_stream_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/basic_socket_streambuf.hpp
|
||||
EXTRA_DIST += ext/asio/asio/ssl.hpp
|
||||
EXTRA_DIST += ext/asio/asio/deadline_timer.hpp
|
||||
EXTRA_DIST += ext/asio/asio/buffers_iterator.hpp
|
||||
EXTRA_DIST += ext/asio/asio/handler_alloc_hook.hpp
|
||||
EXTRA_DIST += ext/asio/asio/buffered_write_stream.hpp
|
||||
EXTRA_DIST += ext/asio/asio/read.hpp
|
||||
EXTRA_DIST += ext/asio/asio/serial_port_base.hpp
|
||||
EXTRA_DIST += ext/asio/asio/stream_socket_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio/time_traits.hpp
|
||||
EXTRA_DIST += ext/asio/asio/read_until.hpp
|
||||
EXTRA_DIST += ext/asio/asio/is_write_buffered.hpp
|
||||
EXTRA_DIST += ext/asio/asio/read_at.hpp
|
||||
EXTRA_DIST += ext/asio/asio/buffered_read_stream_fwd.hpp
|
||||
EXTRA_DIST += ext/asio/asio/socket_acceptor_service.hpp
|
||||
EXTRA_DIST += ext/asio/asio.hpp
|
||||
EXTRA_DIST += ext/asio/asio/system_error.hpp
|
||||
EXTRA_DIST += ext/asio/asio/deadline_timer.hpp
|
||||
EXTRA_DIST += ext/asio/asio/stream_socket_service.hpp
|
||||
EXTRA_DIST += ext/coroutine/coroutine.h
|
||||
|
107
configure.ac
107
configure.ac
@@ -374,6 +374,79 @@ if test "$lcov" != "no"; then
|
||||
fi
|
||||
AC_SUBST(USE_LCOV)
|
||||
|
||||
# Check for Botan
|
||||
botan_path="yes"
|
||||
AC_ARG_WITH([botan],
|
||||
AC_HELP_STRING([--with-botan=PATH],
|
||||
[specify exact directory of Botan library]),
|
||||
[botan_path="$withval"])
|
||||
if test "${botan_path}" == "no" ; then
|
||||
AC_MSG_ERROR([Need botan for libcryptolink])
|
||||
fi
|
||||
if test "${botan_path}" != "yes" ; then
|
||||
if test -x "${botan_path}/bin/botan-config" ; then
|
||||
BOTAN_CONFIG="${botan_path}/bin/botan-config"
|
||||
else
|
||||
AC_MSG_ERROR([${botan_path}/bin/botan-config not found])
|
||||
fi
|
||||
else
|
||||
AC_PATH_PROG([BOTAN_CONFIG], [botan-config])
|
||||
fi
|
||||
|
||||
if test -x "${BOTAN_CONFIG}" ; then
|
||||
BOTAN_LDFLAGS=`${BOTAN_CONFIG} --libs`
|
||||
# We expect botan-config --libs to contain -L<path_to_libbotan>, but
|
||||
# this is not always the case. As a heuristics workaround we add
|
||||
# -L`botan-config --prefix/lib` in this case. Same for BOTAN_INCLUDES
|
||||
# (but using include instead of lib) below.
|
||||
echo ${BOTAN_LDFLAGS} | grep -- -L > /dev/null || \
|
||||
BOTAN_LDFLAGS="-L`${BOTAN_CONFIG} --prefix`/lib ${BOTAN_LDFLAGS}"
|
||||
BOTAN_INCLUDES=`${BOTAN_CONFIG} --cflags`
|
||||
echo ${BOTAN_INCLUDES} | grep -- -I > /dev/null || \
|
||||
BOTAN_INCLUDES="-I`${BOTAN_CONFIG} --prefix`/include ${BOTAN_INCLUDES}"
|
||||
# See python_rpath for some info on why we do this
|
||||
if test $rpath_available = yes; then
|
||||
BOTAN_RPATH=
|
||||
for flag in ${BOTAN_LDFLAGS}; do
|
||||
BOTAN_RPATH="${BOTAN_RPATH} `echo $flag | sed -ne 's/^\(\-L\)/-R/p'`"
|
||||
done
|
||||
AC_SUBST(BOTAN_RPATH)
|
||||
|
||||
# According to the libtool manual, it should be sufficient if we
|
||||
# specify the "-R libdir" in our wrapper library of botan (no other
|
||||
# programs will need libbotan directly); "libdir" should be added to
|
||||
# the program's binary image. But we've seen in our build environments
|
||||
# that (some versions of?) libtool doesn't propagate -R as documented,
|
||||
# and it caused a linker error at run time. To work around this, we
|
||||
# also add the rpath to the global LDFLAGS.
|
||||
LDFLAGS="$BOTAN_RPATH $LDFLAGS"
|
||||
fi
|
||||
|
||||
AC_SUBST(BOTAN_LDFLAGS)
|
||||
AC_SUBST(BOTAN_INCLUDES)
|
||||
fi
|
||||
|
||||
CPPFLAGS_SAVED=$CPPFLAGS
|
||||
CPPFLAGS="$BOTAN_INCLUDES $CPPFLAGS"
|
||||
LDFLAGS_SAVED="$LDFLAGS"
|
||||
LDFLAGS="$BOTAN_LDFLAGS $LDFLAGS"
|
||||
|
||||
AC_CHECK_HEADERS([botan/botan.h],,AC_MSG_ERROR([Missing required header files.]))
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([#include <botan/botan.h>
|
||||
#include <botan/hash.h>
|
||||
],
|
||||
[using namespace Botan;
|
||||
LibraryInitializer::initialize();
|
||||
HashFunction *h = get_hash("MD5");
|
||||
])],
|
||||
[AC_MSG_RESULT([checking for Botan library... yes])],
|
||||
[AC_MSG_RESULT([checking for Botan library... no])
|
||||
AC_MSG_ERROR([Needs Botan library 1.8 or higher])]
|
||||
)
|
||||
CPPFLAGS=$CPPFLAGS_SAVED
|
||||
LDFLAGS=$LDFLAGS_SAVED
|
||||
|
||||
#
|
||||
# Configure Boost header path
|
||||
#
|
||||
@@ -613,6 +686,7 @@ AC_CONFIG_FILES([Makefile
|
||||
src/bin/bindctl/tests/Makefile
|
||||
src/bin/cfgmgr/Makefile
|
||||
src/bin/cfgmgr/plugins/Makefile
|
||||
src/bin/cfgmgr/plugins/tests/Makefile
|
||||
src/bin/cfgmgr/tests/Makefile
|
||||
src/bin/host/Makefile
|
||||
src/bin/loadzone/Makefile
|
||||
@@ -640,6 +714,7 @@ AC_CONFIG_FILES([Makefile
|
||||
src/bin/stats/tests/isc/config/Makefile
|
||||
src/bin/stats/tests/isc/util/Makefile
|
||||
src/bin/stats/tests/testdata/Makefile
|
||||
src/bin/stats/tests/http/Makefile
|
||||
src/bin/usermgr/Makefile
|
||||
src/bin/tests/Makefile
|
||||
src/lib/Makefile
|
||||
@@ -672,11 +747,8 @@ AC_CONFIG_FILES([Makefile
|
||||
src/lib/config/Makefile
|
||||
src/lib/config/tests/Makefile
|
||||
src/lib/config/tests/testdata/Makefile
|
||||
src/lib/util/Makefile
|
||||
src/lib/util/io/Makefile
|
||||
src/lib/util/io/tests/Makefile
|
||||
src/lib/util/unittests/Makefile
|
||||
src/lib/util/tests/Makefile
|
||||
src/lib/cryptolink/Makefile
|
||||
src/lib/cryptolink/tests/Makefile
|
||||
src/lib/dns/Makefile
|
||||
src/lib/dns/tests/Makefile
|
||||
src/lib/dns/tests/testdata/Makefile
|
||||
@@ -701,6 +773,11 @@ AC_CONFIG_FILES([Makefile
|
||||
src/lib/cache/tests/Makefile
|
||||
src/lib/server_common/Makefile
|
||||
src/lib/server_common/tests/Makefile
|
||||
src/lib/util/Makefile
|
||||
src/lib/util/io/Makefile
|
||||
src/lib/util/io/tests/Makefile
|
||||
src/lib/util/unittests/Makefile
|
||||
src/lib/util/tests/Makefile
|
||||
tests/Makefile
|
||||
tests/system/Makefile
|
||||
tests/tools/Makefile
|
||||
@@ -729,11 +806,13 @@ AC_OUTPUT([doc/version.ent
|
||||
src/bin/zonemgr/tests/zonemgr_test
|
||||
src/bin/zonemgr/run_b10-zonemgr.sh
|
||||
src/bin/stats/stats.py
|
||||
src/bin/stats/stats_stub.py
|
||||
src/bin/stats/stats.spec.pre
|
||||
src/bin/stats/run_b10-stats.sh
|
||||
src/bin/stats/run_b10-stats_stub.sh
|
||||
src/bin/stats/tests/stats_test
|
||||
src/bin/stats/stats_httpd.py
|
||||
src/bin/stats/stats.spec
|
||||
src/bin/stats/stats-schema.spec
|
||||
src/bin/stats/stats-httpd.spec
|
||||
src/bin/stats/stats-httpd-xml.tpl
|
||||
src/bin/stats/stats-httpd-xsd.tpl
|
||||
src/bin/stats/stats-httpd-xsl.tpl
|
||||
src/bin/bind10/bind10.py
|
||||
src/bin/bind10/run_bind10.sh
|
||||
src/bin/bind10/tests/bind10_test.py
|
||||
@@ -763,6 +842,7 @@ AC_OUTPUT([doc/version.ent
|
||||
src/lib/cc/session_config.h.pre
|
||||
src/lib/cc/tests/session_unittests_config.h
|
||||
src/lib/log/tests/run_time_init_test.sh
|
||||
src/lib/util/python/mkpywrapper.py
|
||||
tests/system/conf.sh
|
||||
tests/system/glue/setup.sh
|
||||
tests/system/glue/nsx1/b10-config.db
|
||||
@@ -772,9 +852,6 @@ AC_OUTPUT([doc/version.ent
|
||||
chmod +x src/bin/xfrin/run_b10-xfrin.sh
|
||||
chmod +x src/bin/xfrout/run_b10-xfrout.sh
|
||||
chmod +x src/bin/zonemgr/run_b10-zonemgr.sh
|
||||
chmod +x src/bin/stats/tests/stats_test
|
||||
chmod +x src/bin/stats/run_b10-stats.sh
|
||||
chmod +x src/bin/stats/run_b10-stats_stub.sh
|
||||
chmod +x src/bin/bind10/run_bind10.sh
|
||||
chmod +x src/bin/cmdctl/tests/cmdctl_test
|
||||
chmod +x src/bin/xfrin/tests/xfrin_test
|
||||
@@ -791,6 +868,7 @@ AC_OUTPUT([doc/version.ent
|
||||
chmod +x src/lib/dns/gen-rdatacode.py
|
||||
chmod +x src/lib/dns/tests/testdata/gen-wiredata.py
|
||||
chmod +x src/lib/log/tests/run_time_init_test.sh
|
||||
chmod +x src/lib/util/python/mkpywrapper.py
|
||||
chmod +x tests/system/conf.sh
|
||||
])
|
||||
AC_OUTPUT
|
||||
@@ -813,12 +891,15 @@ Flags:
|
||||
DEFS: $DEFS
|
||||
CPPFLAGS: $CPPFLAGS
|
||||
CXXFLAGS: $CXXFLAGS
|
||||
LDFLAGS: $LDFLAGS
|
||||
B10_CXXFLAGS: $B10_CXXFLAGS
|
||||
dnl includes too
|
||||
Python: ${PYTHON_INCLUDES}
|
||||
${PYTHON_LDFLAGS}
|
||||
${PYTHON_LIB}
|
||||
Boost: ${BOOST_INCLUDES}
|
||||
Botan: ${BOTAN_INCLUDES}
|
||||
${BOTAN_LDFLAGS}
|
||||
SQLite: $SQLITE_CFLAGS
|
||||
$SQLITE_LIBS
|
||||
|
||||
|
14
doc/Doxyfile
14
doc/Doxyfile
@@ -568,11 +568,13 @@ WARN_LOGFILE =
|
||||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = ../src/lib/cc ../src/lib/config ../src/lib/dns \
|
||||
../src/lib/exceptions ../src/lib/datasrc ../src/bin/auth \
|
||||
../src/bin/resolver ../src/lib/bench ../src/lib/log ../src/lib/asiolink/ \
|
||||
../src/lib/nsas ../src/lib/testutils ../src/lib/cache \
|
||||
../src/lib/server_common/ ../src/bin/sockcreator/ ../src/lib/util/
|
||||
INPUT = ../src/lib/cc ../src/lib/config \
|
||||
../src/lib/cryptolink ../src/lib/dns ../src/lib/datasrc \
|
||||
../src/bin/auth ../src/bin/resolver ../src/lib/bench \
|
||||
../src/lib/log ../src/lib/asiolink/ ../src/lib/nsas \
|
||||
../src/lib/testutils ../src/lib/cache ../src/lib/server_common/ \
|
||||
../src/bin/sockcreator/ ../src/lib/util/
|
||||
../src/lib/resolve
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
|
||||
@@ -1163,7 +1165,7 @@ XML_DTD =
|
||||
# and cross-referencing information) to the XML output. Note that
|
||||
# enabling this will significantly increase the size of the XML output.
|
||||
|
||||
XML_PROGRAMLISTING = YES
|
||||
XML_PROGRAMLISTING = NO
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options for the AutoGen Definitions output
|
||||
|
@@ -1,5 +1,10 @@
|
||||
ASIO library header files
|
||||
Version 1.4.5 (2010-05-12)
|
||||
Version 1.4.8 (2011-04-19)
|
||||
Downloaded from http://sourceforge.net/projects/asio/files
|
||||
Project page: http://think-async.com/Asio
|
||||
No local modifications.
|
||||
|
||||
Local modifications:
|
||||
Added ASIO_DECL to a number of function definitions
|
||||
git commit c32718be9f5409b6f72d98ddcd0b1ccd4c5c2293
|
||||
See also the bug report at:
|
||||
http://sourceforge.net/tracker/?func=detail&aid=3291113&group_id=122478&atid=694037
|
||||
|
@@ -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)
|
||||
|
@@ -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 {
|
||||
|
||||
|
@@ -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 {
|
||||
|
||||
|
@@ -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 {
|
||||
|
||||
|
@@ -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 {
|
||||
|
||||
|
@@ -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,22 +16,20 @@
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <string>
|
||||
#include <boost/config.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/basic_io_object.hpp"
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/serial_port_base.hpp"
|
||||
#include "asio/serial_port_service.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/detail/config.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/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
/// Provides serial port functionality.
|
||||
@@ -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
|
||||
|
@@ -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 {
|
||||
|
||||
|
@@ -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 {
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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 {
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
// basic_streambuf.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -15,28 +15,23 @@
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/config.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if !defined(BOOST_NO_IOSTREAM)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <streambuf>
|
||||
#include <vector>
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/basic_streambuf_fwd.hpp"
|
||||
#include "asio/buffer.hpp"
|
||||
#include "asio/detail/noncopyable.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
/// Automatically resizable buffer class based on std::streambuf.
|
||||
@@ -107,7 +102,11 @@ namespace asio {
|
||||
* is >> s;
|
||||
* @endcode
|
||||
*/
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
template <typename Allocator = std::allocator<char> >
|
||||
#else
|
||||
template <typename Allocator>
|
||||
#endif
|
||||
class basic_streambuf
|
||||
: public std::streambuf,
|
||||
private noncopyable
|
||||
@@ -337,8 +336,27 @@ protected:
|
||||
private:
|
||||
std::size_t max_size_;
|
||||
std::vector<char_type, Allocator> buffer_;
|
||||
|
||||
// Helper function to get the preferred size for reading data.
|
||||
friend std::size_t read_size_helper(
|
||||
basic_streambuf& sb, std::size_t max_size)
|
||||
{
|
||||
return std::min<std::size_t>(
|
||||
std::max<std::size_t>(512, sb.buffer_.capacity() - sb.size()),
|
||||
std::min<std::size_t>(max_size, sb.max_size() - sb.size()));
|
||||
}
|
||||
};
|
||||
|
||||
// Helper function to get the preferred size for reading data. Used for any
|
||||
// user-provided specialisations of basic_streambuf.
|
||||
template <typename Allocator>
|
||||
inline std::size_t read_size_helper(
|
||||
basic_streambuf<Allocator>& sb, std::size_t max_size)
|
||||
{
|
||||
return std::min<std::size_t>(512,
|
||||
std::min<std::size_t>(max_size, sb.max_size() - sb.size()));
|
||||
}
|
||||
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
33
ext/asio/asio/basic_streambuf_fwd.hpp
Normal file
33
ext/asio/asio/basic_streambuf_fwd.hpp
Normal file
@@ -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
|
@@ -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;
|
||||
|
@@ -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 {
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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 {
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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 {
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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 {
|
||||
|
||||
|
@@ -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.
|
||||
|
@@ -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
|
||||
|
@@ -2,7 +2,7 @@
|
||||
// deadline_timer_service.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -15,17 +15,13 @@
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include "asio/detail/config.hpp"
|
||||
#include <cstddef>
|
||||
#include <boost/config.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/detail/deadline_timer_service.hpp"
|
||||
#include "asio/io_service.hpp"
|
||||
#include "asio/time_traits.hpp"
|
||||
#include "asio/detail/deadline_timer_service.hpp"
|
||||
#include "asio/detail/service_base.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
|
25
ext/asio/asio/detail/array_fwd.hpp
Normal file
25
ext/asio/asio/detail/array_fwd.hpp
Normal file
@@ -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
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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 {
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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 {
|
||||
|
@@ -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 {
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
//
|
||||
// completion_handler.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~
|
||||
// detail/completion_handler.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -15,13 +15,14 @@
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "asio/detail/fenced_block.hpp"
|
||||
#include "asio/detail/handler_alloc_helpers.hpp"
|
||||
#include "asio/detail/handler_invoke_helpers.hpp"
|
||||
#include "asio/detail/operation.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
@@ -29,6 +30,8 @@ template <typename Handler>
|
||||
class completion_handler : public operation
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(completion_handler);
|
||||
|
||||
completion_handler(Handler h)
|
||||
: operation(&completion_handler::do_complete),
|
||||
handler_(h)
|
||||
@@ -40,20 +43,21 @@ public:
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
completion_handler* h(static_cast<completion_handler*>(base));
|
||||
typedef handler_alloc_traits<Handler, completion_handler> alloc_traits;
|
||||
handler_ptr<alloc_traits> ptr(h->handler_, h);
|
||||
ptr p = { boost::addressof(h->handler_), h, h };
|
||||
|
||||
// Make a copy of the handler so that the memory can be deallocated before
|
||||
// the upcall is made. Even if we're not about to make an upcall, a
|
||||
// sub-object of the handler may be the true owner of the memory associated
|
||||
// with the handler. Consequently, a local copy of the handler is required
|
||||
// to ensure that any owning sub-object remains valid until after we have
|
||||
// deallocated the memory here.
|
||||
Handler handler(h->handler_);
|
||||
p.h = boost::addressof(handler);
|
||||
p.reset();
|
||||
|
||||
// Make the upcall if required.
|
||||
if (owner)
|
||||
{
|
||||
// Make a copy of the handler so that the memory can be deallocated
|
||||
// before the upcall is made. Even if we're not about to make an
|
||||
// upcall, a sub-object of the handler may be the true owner of the
|
||||
// memory associated with the handler. Consequently, a local copy of
|
||||
// the handler is required to ensure that any owning sub-object remains
|
||||
// valid until after we have deallocated the memory here.
|
||||
Handler handler(h->handler_);
|
||||
ptr.reset();
|
||||
asio::detail::fenced_block b;
|
||||
asio_handler_invoke_helpers::invoke(handler, handler);
|
||||
}
|
||||
|
205
ext/asio/asio/detail/config.hpp
Normal file
205
ext/asio/asio/detail/config.hpp
Normal file
@@ -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
|
@@ -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.
|
||||
|
@@ -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:
|
||||
|
@@ -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/push_options.hpp"
|
||||
#include <boost/config.hpp>
|
||||
#include <cerrno>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
|
||||
#include <cstddef>
|
||||
#include "asio/error_code.hpp"
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
namespace descriptor_ops {
|
||||
|
||||
inline void clear_error(asio::error_code& ec)
|
||||
// Descriptor state bits.
|
||||
enum
|
||||
{
|
||||
errno = 0;
|
||||
ec = asio::error_code();
|
||||
}
|
||||
// The user wants a non-blocking descriptor.
|
||||
user_set_non_blocking = 1,
|
||||
|
||||
// The descriptor has been set non-blocking.
|
||||
internal_non_blocking = 2,
|
||||
|
||||
// Helper "state" used to determine whether the descriptor is non-blocking.
|
||||
non_blocking = user_set_non_blocking | internal_non_blocking
|
||||
};
|
||||
|
||||
typedef unsigned char state_type;
|
||||
|
||||
template <typename ReturnType>
|
||||
inline ReturnType error_wrapper(ReturnType return_value,
|
||||
@@ -46,131 +53,53 @@ inline ReturnType error_wrapper(ReturnType return_value,
|
||||
return return_value;
|
||||
}
|
||||
|
||||
inline int open(const char* path, int flags, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(::open(path, flags), ec);
|
||||
if (result >= 0)
|
||||
clear_error(ec);
|
||||
return result;
|
||||
}
|
||||
ASIO_DECL int open(const char* path, int flags,
|
||||
asio::error_code& ec);
|
||||
|
||||
inline int close(int d, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(::close(d), ec);
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
return result;
|
||||
}
|
||||
ASIO_DECL int close(int d, state_type& state,
|
||||
asio::error_code& ec);
|
||||
|
||||
inline void init_buf_iov_base(void*& base, void* addr)
|
||||
{
|
||||
base = addr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void init_buf_iov_base(T& base, void* addr)
|
||||
{
|
||||
base = static_cast<T>(addr);
|
||||
}
|
||||
ASIO_DECL bool set_internal_non_blocking(int d,
|
||||
state_type& state, asio::error_code& ec);
|
||||
|
||||
typedef iovec buf;
|
||||
|
||||
inline void init_buf(buf& b, void* data, size_t size)
|
||||
{
|
||||
init_buf_iov_base(b.iov_base, data);
|
||||
b.iov_len = size;
|
||||
}
|
||||
ASIO_DECL std::size_t sync_read(int d, state_type state, buf* bufs,
|
||||
std::size_t count, bool all_empty, asio::error_code& ec);
|
||||
|
||||
inline void init_buf(buf& b, const void* data, size_t size)
|
||||
{
|
||||
init_buf_iov_base(b.iov_base, const_cast<void*>(data));
|
||||
b.iov_len = size;
|
||||
}
|
||||
ASIO_DECL bool non_blocking_read(int d, buf* bufs, std::size_t count,
|
||||
asio::error_code& ec, std::size_t& bytes_transferred);
|
||||
|
||||
inline int scatter_read(int d, buf* bufs, size_t count,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(::readv(d, bufs, static_cast<int>(count)), ec);
|
||||
if (result >= 0)
|
||||
clear_error(ec);
|
||||
return result;
|
||||
}
|
||||
ASIO_DECL std::size_t sync_write(int d, state_type state,
|
||||
const buf* bufs, std::size_t count, bool all_empty,
|
||||
asio::error_code& ec);
|
||||
|
||||
inline int gather_write(int d, const buf* bufs, size_t count,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(::writev(d, bufs, static_cast<int>(count)), ec);
|
||||
if (result >= 0)
|
||||
clear_error(ec);
|
||||
return result;
|
||||
}
|
||||
ASIO_DECL bool non_blocking_write(int d,
|
||||
const buf* bufs, std::size_t count,
|
||||
asio::error_code& ec, std::size_t& bytes_transferred);
|
||||
|
||||
inline int ioctl(int d, long cmd, ioctl_arg_type* arg,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(::ioctl(d, cmd, arg), ec);
|
||||
if (result >= 0)
|
||||
clear_error(ec);
|
||||
return result;
|
||||
}
|
||||
ASIO_DECL int ioctl(int d, state_type& state, long cmd,
|
||||
ioctl_arg_type* arg, asio::error_code& ec);
|
||||
|
||||
inline int fcntl(int d, long cmd, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(::fcntl(d, cmd), ec);
|
||||
if (result != -1)
|
||||
clear_error(ec);
|
||||
return result;
|
||||
}
|
||||
ASIO_DECL int fcntl(int d, long cmd, asio::error_code& ec);
|
||||
|
||||
inline int fcntl(int d, long cmd, long arg, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(::fcntl(d, cmd, arg), ec);
|
||||
if (result != -1)
|
||||
clear_error(ec);
|
||||
return result;
|
||||
}
|
||||
ASIO_DECL int fcntl(int d, long cmd,
|
||||
long arg, asio::error_code& ec);
|
||||
|
||||
inline int poll_read(int d, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
pollfd fds;
|
||||
fds.fd = d;
|
||||
fds.events = POLLIN;
|
||||
fds.revents = 0;
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(::poll(&fds, 1, -1), ec);
|
||||
if (result >= 0)
|
||||
clear_error(ec);
|
||||
return result;
|
||||
}
|
||||
ASIO_DECL int poll_read(int d, asio::error_code& ec);
|
||||
|
||||
inline int poll_write(int d, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
pollfd fds;
|
||||
fds.fd = d;
|
||||
fds.events = POLLOUT;
|
||||
fds.revents = 0;
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(::poll(&fds, 1, -1), ec);
|
||||
if (result >= 0)
|
||||
clear_error(ec);
|
||||
return result;
|
||||
}
|
||||
ASIO_DECL int poll_write(int d, asio::error_code& ec);
|
||||
|
||||
} // namespace descriptor_ops
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#if defined(ASIO_HEADER_ONLY)
|
||||
# include "asio/detail/impl/descriptor_ops.ipp"
|
||||
#endif // defined(ASIO_HEADER_ONLY)
|
||||
|
||||
#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
|
||||
#endif // ASIO_DETAIL_DESCRIPTOR_OPS_HPP
|
||||
|
114
ext/asio/asio/detail/descriptor_read_op.hpp
Normal file
114
ext/asio/asio/detail/descriptor_read_op.hpp
Normal file
@@ -0,0 +1,114 @@
|
||||
//
|
||||
// detail/descriptor_read_op.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_DESCRIPTOR_READ_OP_HPP
|
||||
#define ASIO_DETAIL_DESCRIPTOR_READ_OP_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
|
||||
#include <boost/utility/addressof.hpp>
|
||||
#include "asio/detail/bind_handler.hpp"
|
||||
#include "asio/detail/buffer_sequence_adapter.hpp"
|
||||
#include "asio/detail/descriptor_ops.hpp"
|
||||
#include "asio/detail/fenced_block.hpp"
|
||||
#include "asio/detail/reactor_op.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename MutableBufferSequence>
|
||||
class descriptor_read_op_base : public reactor_op
|
||||
{
|
||||
public:
|
||||
descriptor_read_op_base(int descriptor,
|
||||
const MutableBufferSequence& buffers, func_type complete_func)
|
||||
: reactor_op(&descriptor_read_op_base::do_perform, complete_func),
|
||||
descriptor_(descriptor),
|
||||
buffers_(buffers)
|
||||
{
|
||||
}
|
||||
|
||||
static bool do_perform(reactor_op* base)
|
||||
{
|
||||
descriptor_read_op_base* o(static_cast<descriptor_read_op_base*>(base));
|
||||
|
||||
buffer_sequence_adapter<asio::mutable_buffer,
|
||||
MutableBufferSequence> bufs(o->buffers_);
|
||||
|
||||
return descriptor_ops::non_blocking_read(o->descriptor_,
|
||||
bufs.buffers(), bufs.count(), o->ec_, o->bytes_transferred_);
|
||||
}
|
||||
|
||||
private:
|
||||
int descriptor_;
|
||||
MutableBufferSequence buffers_;
|
||||
};
|
||||
|
||||
template <typename MutableBufferSequence, typename Handler>
|
||||
class descriptor_read_op
|
||||
: public descriptor_read_op_base<MutableBufferSequence>
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_PTR(descriptor_read_op);
|
||||
|
||||
descriptor_read_op(int descriptor,
|
||||
const MutableBufferSequence& buffers, Handler handler)
|
||||
: descriptor_read_op_base<MutableBufferSequence>(
|
||||
descriptor, buffers, &descriptor_read_op::do_complete),
|
||||
handler_(handler)
|
||||
{
|
||||
}
|
||||
|
||||
static void do_complete(io_service_impl* owner, operation* base,
|
||||
asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
descriptor_read_op* o(static_cast<descriptor_read_op*>(base));
|
||||
ptr p = { boost::addressof(o->handler_), o, o };
|
||||
|
||||
// Make a copy of the handler so that the memory can be deallocated before
|
||||
// the upcall is made. Even if we're not about to make an upcall, a
|
||||
// sub-object of the handler may be the true owner of the memory associated
|
||||
// with the handler. Consequently, a local copy of the handler is required
|
||||
// to ensure that any owning sub-object remains valid until after we have
|
||||
// deallocated the memory here.
|
||||
detail::binder2<Handler, asio::error_code, std::size_t>
|
||||
handler(o->handler_, o->ec_, o->bytes_transferred_);
|
||||
p.h = boost::addressof(handler.handler_);
|
||||
p.reset();
|
||||
|
||||
// Make the upcall if required.
|
||||
if (owner)
|
||||
{
|
||||
asio::detail::fenced_block b;
|
||||
asio_handler_invoke_helpers::invoke(handler, handler.handler_);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Handler handler_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
|
||||
#endif // ASIO_DETAIL_DESCRIPTOR_READ_OP_HPP
|
114
ext/asio/asio/detail/descriptor_write_op.hpp
Normal file
114
ext/asio/asio/detail/descriptor_write_op.hpp
Normal file
@@ -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
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
ASIO_DECL int register_descriptor(socket_type descriptor,
|
||||
per_descriptor_data& descriptor_data);
|
||||
|
||||
// Post a reactor operation for immediate completion.
|
||||
void post_immediate_completion(reactor_op* op)
|
||||
{
|
||||
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;
|
||||
|
||||
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,
|
||||
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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -1,8 +1,8 @@
|
||||
//
|
||||
// fenced_block.hpp
|
||||
// ~~~~~~~~~~~~~~~~
|
||||
// detail/fenced_block.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -15,23 +15,25 @@
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <boost/config.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
|
||||
#if !defined(BOOST_HAS_THREADS) \
|
||||
|| defined(ASIO_DISABLE_THREADS) \
|
||||
|| defined(ASIO_DISABLE_FENCED_BLOCK)
|
||||
# include "asio/detail/null_fenced_block.hpp"
|
||||
#elif defined(__MACH__) && defined(__APPLE__)
|
||||
# include "asio/detail/macos_fenced_block.hpp"
|
||||
#elif defined(__sun)
|
||||
# include "asio/detail/solaris_fenced_block.hpp"
|
||||
#elif defined(__GNUC__) && defined(__arm__)
|
||||
# include "asio/detail/gcc_arm_fenced_block.hpp"
|
||||
#elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))
|
||||
# include "asio/detail/gcc_hppa_fenced_block.hpp"
|
||||
#elif defined(__GNUC__) \
|
||||
&& ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \
|
||||
&& !defined(__INTEL_COMPILER) && !defined(__ICL) \
|
||||
&& !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)
|
||||
# include "asio/detail/gcc_fenced_block.hpp"
|
||||
# include "asio/detail/gcc_sync_fenced_block.hpp"
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
# include "asio/detail/gcc_x86_fenced_block.hpp"
|
||||
#elif defined(BOOST_WINDOWS) && !defined(UNDER_CE)
|
||||
@@ -43,17 +45,23 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
#if !defined(BOOST_HAS_THREADS) || defined(ASIO_DISABLE_THREADS)
|
||||
#if !defined(BOOST_HAS_THREADS) \
|
||||
|| defined(ASIO_DISABLE_THREADS) \
|
||||
|| defined(ASIO_DISABLE_FENCED_BLOCK)
|
||||
typedef null_fenced_block fenced_block;
|
||||
#elif defined(__MACH__) && defined(__APPLE__)
|
||||
typedef macos_fenced_block fenced_block;
|
||||
#elif defined(__sun)
|
||||
typedef solaris_fenced_block fenced_block;
|
||||
#elif defined(__GNUC__) && defined(__arm__)
|
||||
typedef gcc_arm_fenced_block fenced_block;
|
||||
#elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))
|
||||
typedef gcc_hppa_fenced_block fenced_block;
|
||||
#elif defined(__GNUC__) \
|
||||
&& ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \
|
||||
&& !defined(__INTEL_COMPILER) && !defined(__ICL) \
|
||||
&& !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)
|
||||
typedef gcc_fenced_block fenced_block;
|
||||
typedef gcc_sync_fenced_block fenced_block;
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
typedef gcc_x86_fenced_block fenced_block;
|
||||
#elif defined(BOOST_WINDOWS) && !defined(UNDER_CE)
|
||||
@@ -65,6 +73,4 @@ typedef null_fenced_block fenced_block;
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_FENCED_BLOCK_HPP
|
||||
|
76
ext/asio/asio/detail/gcc_arm_fenced_block.hpp
Normal file
76
ext/asio/asio/detail/gcc_arm_fenced_block.hpp
Normal file
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// detail/gcc_arm_fenced_block.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_GCC_ARM_FENCED_BLOCK_HPP
|
||||
#define ASIO_DETAIL_GCC_ARM_FENCED_BLOCK_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(__GNUC__) && defined(__arm__)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class gcc_arm_fenced_block
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
gcc_arm_fenced_block()
|
||||
{
|
||||
barrier();
|
||||
}
|
||||
|
||||
// Destructor.
|
||||
~gcc_arm_fenced_block()
|
||||
{
|
||||
barrier();
|
||||
}
|
||||
|
||||
private:
|
||||
static void barrier()
|
||||
{
|
||||
#if defined(__ARM_ARCH_4__) \
|
||||
|| defined(__ARM_ARCH_4T__) \
|
||||
|| defined(__ARM_ARCH_5__) \
|
||||
|| defined(__ARM_ARCH_5E__) \
|
||||
|| defined(__ARM_ARCH_5T__) \
|
||||
|| defined(__ARM_ARCH_5TE__) \
|
||||
|| defined(__ARM_ARCH_5TEJ__) \
|
||||
|| defined(__ARM_ARCH_6__) \
|
||||
|| defined(__ARM_ARCH_6J__) \
|
||||
|| defined(__ARM_ARCH_6K__) \
|
||||
|| defined(__ARM_ARCH_6Z__) \
|
||||
|| defined(__ARM_ARCH_6ZK__) \
|
||||
|| defined(__ARM_ARCH_6T2__)
|
||||
int a = 0, b = 0;
|
||||
__asm__ __volatile__ ("swp %0, %1, [%2]"
|
||||
: "=&r"(a) : "r"(1), "r"(&b) : "memory", "cc");
|
||||
#else
|
||||
// ARMv7 and later.
|
||||
__asm__ __volatile__ ("dmb" : : : "memory");
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(__GNUC__) && defined(__arm__)
|
||||
|
||||
#endif // ASIO_DETAIL_GCC_ARM_FENCED_BLOCK_HPP
|
58
ext/asio/asio/detail/gcc_hppa_fenced_block.hpp
Normal file
58
ext/asio/asio/detail/gcc_hppa_fenced_block.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// detail/gcc_hppa_fenced_block.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_GCC_HPPA_FENCED_BLOCK_HPP
|
||||
#define ASIO_DETAIL_GCC_HPPA_FENCED_BLOCK_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class gcc_hppa_fenced_block
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
gcc_hppa_fenced_block()
|
||||
{
|
||||
barrier();
|
||||
}
|
||||
|
||||
// Destructor.
|
||||
~gcc_hppa_fenced_block()
|
||||
{
|
||||
barrier();
|
||||
}
|
||||
|
||||
private:
|
||||
static void barrier()
|
||||
{
|
||||
// This is just a placeholder and almost certainly not sufficient.
|
||||
__asm__ __volatile__ ("" : : : "memory");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))
|
||||
|
||||
#endif // ASIO_DETAIL_GCC_HPPA_FENCED_BLOCK_HPP
|
61
ext/asio/asio/detail/gcc_sync_fenced_block.hpp
Normal file
61
ext/asio/asio/detail/gcc_sync_fenced_block.hpp
Normal file
@@ -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
|
@@ -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
|
||||
|
@@ -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"
|
||||
|
||||
|
@@ -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.
|
||||
|
@@ -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 boost::hash_value(t);
|
||||
return static_cast<std::size_t>(i);
|
||||
}
|
||||
|
||||
#if defined(_WIN64)
|
||||
inline std::size_t calculate_hash_value(void* p)
|
||||
{
|
||||
return reinterpret_cast<std::size_t>(p)
|
||||
+ (reinterpret_cast<std::size_t>(p) >> 3);
|
||||
}
|
||||
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
inline std::size_t calculate_hash_value(SOCKET s)
|
||||
{
|
||||
return static_cast<std::size_t>(s);
|
||||
}
|
||||
#endif // defined(_WIN64)
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
|
||||
// Note: assumes K and V are POD types.
|
||||
template <typename K, typename V>
|
||||
|
382
ext/asio/asio/detail/impl/descriptor_ops.ipp
Normal file
382
ext/asio/asio/detail/impl/descriptor_ops.ipp
Normal file
@@ -0,0 +1,382 @@
|
||||
//
|
||||
// detail/impl/descriptor_ops.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
|
||||
#define ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include <cerrno>
|
||||
#include "asio/detail/descriptor_ops.hpp"
|
||||
#include "asio/error.hpp"
|
||||
|
||||
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
namespace descriptor_ops {
|
||||
|
||||
ASIO_DECL
|
||||
int open(const char* path, int flags, asio::error_code& ec)
|
||||
{
|
||||
errno = 0;
|
||||
int result = error_wrapper(::open(path, flags), ec);
|
||||
if (result >= 0)
|
||||
ec = asio::error_code();
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIO_DECL
|
||||
int close(int d, state_type& state, asio::error_code& ec)
|
||||
{
|
||||
int result = 0;
|
||||
if (d != -1)
|
||||
{
|
||||
if (state & internal_non_blocking)
|
||||
{
|
||||
#if defined(__SYMBIAN32__)
|
||||
int flags = ::fcntl(d, F_GETFL, 0);
|
||||
if (flags >= 0)
|
||||
::fcntl(d, F_SETFL, flags & ~O_NONBLOCK);
|
||||
#else // defined(__SYMBIAN32__)
|
||||
ioctl_arg_type arg = 0;
|
||||
::ioctl(d, FIONBIO, &arg);
|
||||
#endif // defined(__SYMBIAN32__)
|
||||
state &= ~internal_non_blocking;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
result = error_wrapper(::close(d), ec);
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
ec = asio::error_code();
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIO_DECL
|
||||
bool set_internal_non_blocking(int d,
|
||||
state_type& state, asio::error_code& ec)
|
||||
{
|
||||
if (d == -1)
|
||||
{
|
||||
ec = asio::error::bad_descriptor;
|
||||
return false;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
#if defined(__SYMBIAN32__)
|
||||
int result = error_wrapper(::fcntl(d, F_GETFL, 0), ec);
|
||||
if (result >= 0)
|
||||
{
|
||||
errno = 0;
|
||||
result = error_wrapper(::fcntl(d, F_SETFL, result | O_NONBLOCK), ec);
|
||||
}
|
||||
#else // defined(__SYMBIAN32__)
|
||||
ioctl_arg_type arg = 1;
|
||||
int result = error_wrapper(::ioctl(d, FIONBIO, &arg), ec);
|
||||
#endif // defined(__SYMBIAN32__)
|
||||
|
||||
if (result >= 0)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
state |= internal_non_blocking;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ASIO_DECL
|
||||
std::size_t sync_read(int d, state_type state, buf* bufs,
|
||||
std::size_t count, bool all_empty, asio::error_code& ec)
|
||||
{
|
||||
if (d == -1)
|
||||
{
|
||||
ec = asio::error::bad_descriptor;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// A request to read 0 bytes on a stream is a no-op.
|
||||
if (all_empty)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read some data.
|
||||
for (;;)
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
errno = 0;
|
||||
int bytes = error_wrapper(::readv(d, bufs, static_cast<int>(count)), ec);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes > 0)
|
||||
return bytes;
|
||||
|
||||
// Check for EOF.
|
||||
if (bytes == 0)
|
||||
{
|
||||
ec = asio::error::eof;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Operation failed.
|
||||
if ((state & user_set_non_blocking)
|
||||
|| (ec != asio::error::would_block
|
||||
&& ec != asio::error::try_again))
|
||||
return 0;
|
||||
|
||||
// Wait for descriptor to become ready.
|
||||
if (descriptor_ops::poll_read(d, ec) < 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ASIO_DECL
|
||||
bool non_blocking_read(int d, buf* bufs, std::size_t count,
|
||||
asio::error_code& ec, std::size_t& bytes_transferred)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
// Read some data.
|
||||
errno = 0;
|
||||
int bytes = error_wrapper(::readv(d, bufs, static_cast<int>(count)), ec);
|
||||
|
||||
// Check for end of stream.
|
||||
if (bytes == 0)
|
||||
{
|
||||
ec = asio::error::eof;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Retry operation if interrupted by signal.
|
||||
if (ec == asio::error::interrupted)
|
||||
continue;
|
||||
|
||||
// Check if we need to run the operation again.
|
||||
if (ec == asio::error::would_block
|
||||
|| ec == asio::error::try_again)
|
||||
return false;
|
||||
|
||||
// Operation is complete.
|
||||
if (bytes > 0)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
bytes_transferred = bytes;
|
||||
}
|
||||
else
|
||||
bytes_transferred = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ASIO_DECL
|
||||
std::size_t sync_write(int d, state_type state, const buf* bufs,
|
||||
std::size_t count, bool all_empty, asio::error_code& ec)
|
||||
{
|
||||
if (d == -1)
|
||||
{
|
||||
ec = asio::error::bad_descriptor;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// A request to write 0 bytes on a stream is a no-op.
|
||||
if (all_empty)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Write some data.
|
||||
for (;;)
|
||||
{
|
||||
// Try to complete the operation without blocking.
|
||||
errno = 0;
|
||||
int bytes = error_wrapper(::writev(d, bufs, static_cast<int>(count)), ec);
|
||||
|
||||
// Check if operation succeeded.
|
||||
if (bytes > 0)
|
||||
return bytes;
|
||||
|
||||
// Operation failed.
|
||||
if ((state & user_set_non_blocking)
|
||||
|| (ec != asio::error::would_block
|
||||
&& ec != asio::error::try_again))
|
||||
return 0;
|
||||
|
||||
// Wait for descriptor to become ready.
|
||||
if (descriptor_ops::poll_write(d, ec) < 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ASIO_DECL
|
||||
bool non_blocking_write(int d, const buf* bufs, std::size_t count,
|
||||
asio::error_code& ec, std::size_t& bytes_transferred)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
// Write some data.
|
||||
errno = 0;
|
||||
int bytes = error_wrapper(::writev(d, bufs, static_cast<int>(count)), ec);
|
||||
|
||||
// Retry operation if interrupted by signal.
|
||||
if (ec == asio::error::interrupted)
|
||||
continue;
|
||||
|
||||
// Check if we need to run the operation again.
|
||||
if (ec == asio::error::would_block
|
||||
|| ec == asio::error::try_again)
|
||||
return false;
|
||||
|
||||
// Operation is complete.
|
||||
if (bytes >= 0)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
bytes_transferred = bytes;
|
||||
}
|
||||
else
|
||||
bytes_transferred = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ASIO_DECL
|
||||
int ioctl(int d, state_type& state, long cmd,
|
||||
ioctl_arg_type* arg, asio::error_code& ec)
|
||||
{
|
||||
if (d == -1)
|
||||
{
|
||||
ec = asio::error::bad_descriptor;
|
||||
return -1;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
int result = error_wrapper(::ioctl(d, cmd, arg), ec);
|
||||
|
||||
if (result >= 0)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
|
||||
// When updating the non-blocking mode we always perform the ioctl syscall,
|
||||
// even if the flags would otherwise indicate that the descriptor is
|
||||
// already in the correct state. This ensures that the underlying
|
||||
// descriptor is put into the state that has been requested by the user. If
|
||||
// the ioctl syscall was successful then we need to update the flags to
|
||||
// match.
|
||||
if (cmd == static_cast<long>(FIONBIO))
|
||||
{
|
||||
if (*arg)
|
||||
{
|
||||
state |= user_set_non_blocking;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clearing the non-blocking mode always overrides any internally-set
|
||||
// non-blocking flag. Any subsequent asynchronous operations will need
|
||||
// to re-enable non-blocking I/O.
|
||||
state &= ~(user_set_non_blocking | internal_non_blocking);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIO_DECL
|
||||
int fcntl(int d, long cmd, asio::error_code& ec)
|
||||
{
|
||||
if (d == -1)
|
||||
{
|
||||
ec = asio::error::bad_descriptor;
|
||||
return -1;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
int result = error_wrapper(::fcntl(d, cmd), ec);
|
||||
if (result != -1)
|
||||
ec = asio::error_code();
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIO_DECL
|
||||
int fcntl(int d, long cmd, long arg, asio::error_code& ec)
|
||||
{
|
||||
if (d == -1)
|
||||
{
|
||||
ec = asio::error::bad_descriptor;
|
||||
return -1;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
int result = error_wrapper(::fcntl(d, cmd, arg), ec);
|
||||
if (result != -1)
|
||||
ec = asio::error_code();
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIO_DECL
|
||||
int poll_read(int d, asio::error_code& ec)
|
||||
{
|
||||
if (d == -1)
|
||||
{
|
||||
ec = asio::error::bad_descriptor;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pollfd fds;
|
||||
fds.fd = d;
|
||||
fds.events = POLLIN;
|
||||
fds.revents = 0;
|
||||
errno = 0;
|
||||
int result = error_wrapper(::poll(&fds, 1, -1), ec);
|
||||
if (result >= 0)
|
||||
ec = asio::error_code();
|
||||
return result;
|
||||
}
|
||||
|
||||
ASIO_DECL
|
||||
int poll_write(int d, asio::error_code& ec)
|
||||
{
|
||||
if (d == -1)
|
||||
{
|
||||
ec = asio::error::bad_descriptor;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pollfd fds;
|
||||
fds.fd = d;
|
||||
fds.events = POLLOUT;
|
||||
fds.revents = 0;
|
||||
errno = 0;
|
||||
int result = error_wrapper(::poll(&fds, 1, -1), ec);
|
||||
if (result >= 0)
|
||||
ec = asio::error_code();
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace descriptor_ops
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
|
77
ext/asio/asio/detail/impl/dev_poll_reactor.hpp
Normal file
77
ext/asio/asio/detail/impl/dev_poll_reactor.hpp
Normal file
@@ -0,0 +1,77 @@
|
||||
//
|
||||
// detail/impl/dev_poll_reactor.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_HPP
|
||||
#define ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_DEV_POLL)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Time_Traits>
|
||||
void dev_poll_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)
|
||||
{
|
||||
do_add_timer_queue(queue);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void dev_poll_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue)
|
||||
{
|
||||
do_remove_timer_queue(queue);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void dev_poll_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
|
||||
const typename Time_Traits::time_type& time,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
if (shutdown_)
|
||||
{
|
||||
io_service_.post_immediate_completion(op);
|
||||
return;
|
||||
}
|
||||
|
||||
bool earliest = queue.enqueue_timer(time, timer, op);
|
||||
io_service_.work_started();
|
||||
if (earliest)
|
||||
interrupter_.interrupt();
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
std::size_t dev_poll_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
op_queue<operation> ops;
|
||||
std::size_t n = queue.cancel_timer(timer, ops);
|
||||
lock.unlock();
|
||||
io_service_.post_deferred_completions(ops);
|
||||
return n;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(ASIO_HAS_DEV_POLL)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_HPP
|
338
ext/asio/asio/detail/impl/dev_poll_reactor.ipp
Normal file
338
ext/asio/asio/detail/impl/dev_poll_reactor.ipp
Normal file
@@ -0,0 +1,338 @@
|
||||
//
|
||||
// detail/impl/dev_poll_reactor.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_IPP
|
||||
#define ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_DEV_POLL)
|
||||
|
||||
#include "asio/detail/dev_poll_reactor.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
dev_poll_reactor::dev_poll_reactor(asio::io_service& io_service)
|
||||
: asio::detail::service_base<dev_poll_reactor>(io_service),
|
||||
io_service_(use_service<io_service_impl>(io_service)),
|
||||
mutex_(),
|
||||
dev_poll_fd_(do_dev_poll_create()),
|
||||
interrupter_(),
|
||||
shutdown_(false)
|
||||
{
|
||||
// Add the interrupter's descriptor to /dev/poll.
|
||||
::pollfd ev = { 0 };
|
||||
ev.fd = interrupter_.read_descriptor();
|
||||
ev.events = POLLIN | POLLERR;
|
||||
ev.revents = 0;
|
||||
::write(dev_poll_fd_, &ev, sizeof(ev));
|
||||
}
|
||||
|
||||
dev_poll_reactor::~dev_poll_reactor()
|
||||
{
|
||||
shutdown_service();
|
||||
::close(dev_poll_fd_);
|
||||
}
|
||||
|
||||
void dev_poll_reactor::shutdown_service()
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
shutdown_ = true;
|
||||
lock.unlock();
|
||||
|
||||
op_queue<operation> ops;
|
||||
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
op_queue_[i].get_all_operations(ops);
|
||||
|
||||
timer_queues_.get_all_timers(ops);
|
||||
}
|
||||
|
||||
void dev_poll_reactor::init_task()
|
||||
{
|
||||
io_service_.init_task();
|
||||
}
|
||||
|
||||
int dev_poll_reactor::register_descriptor(socket_type, per_descriptor_data&)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dev_poll_reactor::start_op(int op_type, socket_type descriptor,
|
||||
dev_poll_reactor::per_descriptor_data&,
|
||||
reactor_op* op, bool allow_speculative)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
if (shutdown_)
|
||||
{
|
||||
post_immediate_completion(op);
|
||||
return;
|
||||
}
|
||||
|
||||
if (allow_speculative)
|
||||
{
|
||||
if (op_type != read_op || !op_queue_[except_op].has_operation(descriptor))
|
||||
{
|
||||
if (!op_queue_[op_type].has_operation(descriptor))
|
||||
{
|
||||
if (op->perform())
|
||||
{
|
||||
lock.unlock();
|
||||
io_service_.post_immediate_completion(op);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
|
||||
io_service_.work_started();
|
||||
if (first)
|
||||
{
|
||||
::pollfd& ev = add_pending_event_change(descriptor);
|
||||
ev.events = POLLERR | POLLHUP;
|
||||
if (op_type == read_op
|
||||
|| op_queue_[read_op].has_operation(descriptor))
|
||||
ev.events |= POLLIN;
|
||||
if (op_type == write_op
|
||||
|| op_queue_[write_op].has_operation(descriptor))
|
||||
ev.events |= POLLOUT;
|
||||
if (op_type == except_op
|
||||
|| op_queue_[except_op].has_operation(descriptor))
|
||||
ev.events |= POLLPRI;
|
||||
interrupter_.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
void dev_poll_reactor::cancel_ops(socket_type descriptor,
|
||||
dev_poll_reactor::per_descriptor_data&)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
|
||||
}
|
||||
|
||||
void dev_poll_reactor::close_descriptor(socket_type descriptor,
|
||||
dev_poll_reactor::per_descriptor_data&)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
// Remove the descriptor from /dev/poll.
|
||||
::pollfd& ev = add_pending_event_change(descriptor);
|
||||
ev.events = POLLREMOVE;
|
||||
interrupter_.interrupt();
|
||||
|
||||
// Cancel any outstanding operations associated with the descriptor.
|
||||
cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
|
||||
}
|
||||
|
||||
void dev_poll_reactor::run(bool block, op_queue<operation>& ops)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
// We can return immediately if there's no work to do and the reactor is
|
||||
// not supposed to block.
|
||||
if (!block && op_queue_[read_op].empty() && op_queue_[write_op].empty()
|
||||
&& op_queue_[except_op].empty() && timer_queues_.all_empty())
|
||||
return;
|
||||
|
||||
// Write the pending event registration changes to the /dev/poll descriptor.
|
||||
std::size_t events_size = sizeof(::pollfd) * pending_event_changes_.size();
|
||||
if (events_size > 0)
|
||||
{
|
||||
errno = 0;
|
||||
int result = ::write(dev_poll_fd_,
|
||||
&pending_event_changes_[0], events_size);
|
||||
if (result != static_cast<int>(events_size))
|
||||
{
|
||||
asio::error_code ec = asio::error_code(
|
||||
errno, asio::error::get_system_category());
|
||||
for (std::size_t i = 0; i < pending_event_changes_.size(); ++i)
|
||||
{
|
||||
int descriptor = pending_event_changes_[i].fd;
|
||||
for (int j = 0; j < max_ops; ++j)
|
||||
op_queue_[j].cancel_operations(descriptor, ops, ec);
|
||||
}
|
||||
}
|
||||
pending_event_changes_.clear();
|
||||
pending_event_change_index_.clear();
|
||||
}
|
||||
|
||||
int timeout = block ? get_timeout() : 0;
|
||||
lock.unlock();
|
||||
|
||||
// Block on the /dev/poll descriptor.
|
||||
::pollfd events[128] = { { 0 } };
|
||||
::dvpoll dp = { 0 };
|
||||
dp.dp_fds = events;
|
||||
dp.dp_nfds = 128;
|
||||
dp.dp_timeout = timeout;
|
||||
int num_events = ::ioctl(dev_poll_fd_, DP_POLL, &dp);
|
||||
|
||||
lock.lock();
|
||||
|
||||
// Dispatch the waiting events.
|
||||
for (int i = 0; i < num_events; ++i)
|
||||
{
|
||||
int descriptor = events[i].fd;
|
||||
if (descriptor == interrupter_.read_descriptor())
|
||||
{
|
||||
interrupter_.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
bool more_reads = false;
|
||||
bool more_writes = false;
|
||||
bool more_except = false;
|
||||
|
||||
// Exception operations must be processed first to ensure that any
|
||||
// out-of-band data is read before normal data.
|
||||
if (events[i].events & (POLLPRI | POLLERR | POLLHUP))
|
||||
more_except =
|
||||
op_queue_[except_op].perform_operations(descriptor, ops);
|
||||
else
|
||||
more_except = op_queue_[except_op].has_operation(descriptor);
|
||||
|
||||
if (events[i].events & (POLLIN | POLLERR | POLLHUP))
|
||||
more_reads = op_queue_[read_op].perform_operations(descriptor, ops);
|
||||
else
|
||||
more_reads = op_queue_[read_op].has_operation(descriptor);
|
||||
|
||||
if (events[i].events & (POLLOUT | POLLERR | POLLHUP))
|
||||
more_writes = op_queue_[write_op].perform_operations(descriptor, ops);
|
||||
else
|
||||
more_writes = op_queue_[write_op].has_operation(descriptor);
|
||||
|
||||
if ((events[i].events & (POLLERR | POLLHUP)) != 0
|
||||
&& !more_except && !more_reads && !more_writes)
|
||||
{
|
||||
// If we have an event and no operations associated with the
|
||||
// descriptor then we need to delete the descriptor from /dev/poll.
|
||||
// The poll operation can produce POLLHUP or POLLERR events when there
|
||||
// is no operation pending, so if we do not remove the descriptor we
|
||||
// can end up in a tight polling loop.
|
||||
::pollfd ev = { 0 };
|
||||
ev.fd = descriptor;
|
||||
ev.events = POLLREMOVE;
|
||||
ev.revents = 0;
|
||||
::write(dev_poll_fd_, &ev, sizeof(ev));
|
||||
}
|
||||
else
|
||||
{
|
||||
::pollfd ev = { 0 };
|
||||
ev.fd = descriptor;
|
||||
ev.events = POLLERR | POLLHUP;
|
||||
if (more_reads)
|
||||
ev.events |= POLLIN;
|
||||
if (more_writes)
|
||||
ev.events |= POLLOUT;
|
||||
if (more_except)
|
||||
ev.events |= POLLPRI;
|
||||
ev.revents = 0;
|
||||
int result = ::write(dev_poll_fd_, &ev, sizeof(ev));
|
||||
if (result != sizeof(ev))
|
||||
{
|
||||
asio::error_code ec(errno,
|
||||
asio::error::get_system_category());
|
||||
for (int j = 0; j < max_ops; ++j)
|
||||
op_queue_[j].cancel_operations(descriptor, ops, ec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
timer_queues_.get_ready_timers(ops);
|
||||
}
|
||||
|
||||
void dev_poll_reactor::interrupt()
|
||||
{
|
||||
interrupter_.interrupt();
|
||||
}
|
||||
|
||||
int dev_poll_reactor::do_dev_poll_create()
|
||||
{
|
||||
int fd = ::open("/dev/poll", O_RDWR);
|
||||
if (fd == -1)
|
||||
{
|
||||
asio::error_code ec(errno,
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "/dev/poll");
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
void dev_poll_reactor::do_add_timer_queue(timer_queue_base& queue)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
timer_queues_.insert(&queue);
|
||||
}
|
||||
|
||||
void dev_poll_reactor::do_remove_timer_queue(timer_queue_base& queue)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
timer_queues_.erase(&queue);
|
||||
}
|
||||
|
||||
int dev_poll_reactor::get_timeout()
|
||||
{
|
||||
// By default we will wait no longer than 5 minutes. This will ensure that
|
||||
// any changes to the system clock are detected after no longer than this.
|
||||
return timer_queues_.wait_duration_msec(5 * 60 * 1000);
|
||||
}
|
||||
|
||||
void dev_poll_reactor::cancel_ops_unlocked(socket_type descriptor,
|
||||
const asio::error_code& ec)
|
||||
{
|
||||
bool need_interrupt = false;
|
||||
op_queue<operation> ops;
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
need_interrupt = op_queue_[i].cancel_operations(
|
||||
descriptor, ops, ec) || need_interrupt;
|
||||
io_service_.post_deferred_completions(ops);
|
||||
if (need_interrupt)
|
||||
interrupter_.interrupt();
|
||||
}
|
||||
|
||||
::pollfd& dev_poll_reactor::add_pending_event_change(int descriptor)
|
||||
{
|
||||
hash_map<int, std::size_t>::iterator iter
|
||||
= pending_event_change_index_.find(descriptor);
|
||||
if (iter == pending_event_change_index_.end())
|
||||
{
|
||||
std::size_t index = pending_event_changes_.size();
|
||||
pending_event_changes_.reserve(pending_event_changes_.size() + 1);
|
||||
pending_event_change_index_.insert(std::make_pair(descriptor, index));
|
||||
pending_event_changes_.push_back(::pollfd());
|
||||
pending_event_changes_[index].fd = descriptor;
|
||||
pending_event_changes_[index].revents = 0;
|
||||
return pending_event_changes_[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
return pending_event_changes_[iter->second];
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(ASIO_HAS_DEV_POLL)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_IPP
|
75
ext/asio/asio/detail/impl/epoll_reactor.hpp
Normal file
75
ext/asio/asio/detail/impl/epoll_reactor.hpp
Normal file
@@ -0,0 +1,75 @@
|
||||
//
|
||||
// detail/impl/epoll_reactor.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_EPOLL_REACTOR_HPP
|
||||
#define ASIO_DETAIL_IMPL_EPOLL_REACTOR_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#if defined(ASIO_HAS_EPOLL)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Time_Traits>
|
||||
void epoll_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)
|
||||
{
|
||||
do_add_timer_queue(queue);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void epoll_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue)
|
||||
{
|
||||
do_remove_timer_queue(queue);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void epoll_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
|
||||
const typename Time_Traits::time_type& time,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
|
||||
if (shutdown_)
|
||||
{
|
||||
io_service_.post_immediate_completion(op);
|
||||
return;
|
||||
}
|
||||
|
||||
bool earliest = queue.enqueue_timer(time, timer, op);
|
||||
io_service_.work_started();
|
||||
if (earliest)
|
||||
update_timeout();
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
std::size_t epoll_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
op_queue<operation> ops;
|
||||
std::size_t n = queue.cancel_timer(timer, ops);
|
||||
lock.unlock();
|
||||
io_service_.post_deferred_completions(ops);
|
||||
return n;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(ASIO_HAS_EPOLL)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_EPOLL_REACTOR_HPP
|
390
ext/asio/asio/detail/impl/epoll_reactor.ipp
Normal file
390
ext/asio/asio/detail/impl/epoll_reactor.ipp
Normal file
@@ -0,0 +1,390 @@
|
||||
//
|
||||
// detail/impl/epoll_reactor.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP
|
||||
#define ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_EPOLL)
|
||||
|
||||
#include <cstddef>
|
||||
#include <sys/epoll.h>
|
||||
#include "asio/detail/epoll_reactor.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_TIMERFD)
|
||||
# include <sys/timerfd.h>
|
||||
#endif // defined(ASIO_HAS_TIMERFD)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
epoll_reactor::epoll_reactor(asio::io_service& io_service)
|
||||
: asio::detail::service_base<epoll_reactor>(io_service),
|
||||
io_service_(use_service<io_service_impl>(io_service)),
|
||||
mutex_(),
|
||||
epoll_fd_(do_epoll_create()),
|
||||
#if defined(ASIO_HAS_TIMERFD)
|
||||
timer_fd_(timerfd_create(CLOCK_MONOTONIC, 0)),
|
||||
#else // defined(ASIO_HAS_TIMERFD)
|
||||
timer_fd_(-1),
|
||||
#endif // defined(ASIO_HAS_TIMERFD)
|
||||
interrupter_(),
|
||||
shutdown_(false)
|
||||
{
|
||||
// Add the interrupter's descriptor to epoll.
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
ev.events = EPOLLIN | EPOLLERR | EPOLLET;
|
||||
ev.data.ptr = &interrupter_;
|
||||
epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev);
|
||||
interrupter_.interrupt();
|
||||
|
||||
// Add the timer descriptor to epoll.
|
||||
if (timer_fd_ != -1)
|
||||
{
|
||||
ev.events = EPOLLIN | EPOLLERR;
|
||||
ev.data.ptr = &timer_fd_;
|
||||
epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev);
|
||||
}
|
||||
}
|
||||
|
||||
epoll_reactor::~epoll_reactor()
|
||||
{
|
||||
close(epoll_fd_);
|
||||
if (timer_fd_ != -1)
|
||||
close(timer_fd_);
|
||||
}
|
||||
|
||||
void epoll_reactor::shutdown_service()
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
shutdown_ = true;
|
||||
lock.unlock();
|
||||
|
||||
op_queue<operation> ops;
|
||||
|
||||
while (descriptor_state* state = registered_descriptors_.first())
|
||||
{
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
ops.push(state->op_queue_[i]);
|
||||
state->shutdown_ = true;
|
||||
registered_descriptors_.free(state);
|
||||
}
|
||||
|
||||
timer_queues_.get_all_timers(ops);
|
||||
}
|
||||
|
||||
void epoll_reactor::init_task()
|
||||
{
|
||||
io_service_.init_task();
|
||||
}
|
||||
|
||||
int epoll_reactor::register_descriptor(socket_type descriptor,
|
||||
epoll_reactor::per_descriptor_data& descriptor_data)
|
||||
{
|
||||
mutex::scoped_lock lock(registered_descriptors_mutex_);
|
||||
|
||||
descriptor_data = registered_descriptors_.alloc();
|
||||
descriptor_data->shutdown_ = false;
|
||||
|
||||
lock.unlock();
|
||||
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLOUT | EPOLLPRI | EPOLLET;
|
||||
ev.data.ptr = descriptor_data;
|
||||
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
|
||||
if (result != 0)
|
||||
return errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void epoll_reactor::start_op(int op_type, socket_type descriptor,
|
||||
epoll_reactor::per_descriptor_data& descriptor_data,
|
||||
reactor_op* op, bool allow_speculative)
|
||||
{
|
||||
if (!descriptor_data)
|
||||
{
|
||||
op->ec_ = asio::error::bad_descriptor;
|
||||
post_immediate_completion(op);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
|
||||
|
||||
if (descriptor_data->shutdown_)
|
||||
{
|
||||
post_immediate_completion(op);
|
||||
return;
|
||||
}
|
||||
|
||||
if (descriptor_data->op_queue_[op_type].empty())
|
||||
{
|
||||
if (allow_speculative
|
||||
&& (op_type != read_op
|
||||
|| descriptor_data->op_queue_[except_op].empty()))
|
||||
{
|
||||
if (op->perform())
|
||||
{
|
||||
descriptor_lock.unlock();
|
||||
io_service_.post_immediate_completion(op);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
ev.events = EPOLLIN | EPOLLERR | EPOLLHUP
|
||||
| EPOLLOUT | EPOLLPRI | EPOLLET;
|
||||
ev.data.ptr = descriptor_data;
|
||||
epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
|
||||
}
|
||||
}
|
||||
|
||||
descriptor_data->op_queue_[op_type].push(op);
|
||||
io_service_.work_started();
|
||||
}
|
||||
|
||||
void epoll_reactor::cancel_ops(socket_type,
|
||||
epoll_reactor::per_descriptor_data& descriptor_data)
|
||||
{
|
||||
if (!descriptor_data)
|
||||
return;
|
||||
|
||||
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
|
||||
|
||||
op_queue<operation> ops;
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
{
|
||||
while (reactor_op* op = descriptor_data->op_queue_[i].front())
|
||||
{
|
||||
op->ec_ = asio::error::operation_aborted;
|
||||
descriptor_data->op_queue_[i].pop();
|
||||
ops.push(op);
|
||||
}
|
||||
}
|
||||
|
||||
descriptor_lock.unlock();
|
||||
|
||||
io_service_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
void epoll_reactor::close_descriptor(socket_type,
|
||||
epoll_reactor::per_descriptor_data& descriptor_data)
|
||||
{
|
||||
if (!descriptor_data)
|
||||
return;
|
||||
|
||||
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
|
||||
mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
|
||||
|
||||
if (!descriptor_data->shutdown_)
|
||||
{
|
||||
// Remove the descriptor from the set of known descriptors. The descriptor
|
||||
// will be automatically removed from the epoll set when it is closed.
|
||||
|
||||
op_queue<operation> ops;
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
{
|
||||
while (reactor_op* op = descriptor_data->op_queue_[i].front())
|
||||
{
|
||||
op->ec_ = asio::error::operation_aborted;
|
||||
descriptor_data->op_queue_[i].pop();
|
||||
ops.push(op);
|
||||
}
|
||||
}
|
||||
|
||||
descriptor_data->shutdown_ = true;
|
||||
|
||||
descriptor_lock.unlock();
|
||||
|
||||
registered_descriptors_.free(descriptor_data);
|
||||
descriptor_data = 0;
|
||||
|
||||
descriptors_lock.unlock();
|
||||
|
||||
io_service_.post_deferred_completions(ops);
|
||||
}
|
||||
}
|
||||
|
||||
void epoll_reactor::run(bool block, op_queue<operation>& ops)
|
||||
{
|
||||
// Calculate a timeout only if timerfd is not used.
|
||||
int timeout;
|
||||
if (timer_fd_ != -1)
|
||||
timeout = block ? -1 : 0;
|
||||
else
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
timeout = block ? get_timeout() : 0;
|
||||
}
|
||||
|
||||
// Block on the epoll descriptor.
|
||||
epoll_event events[128];
|
||||
int num_events = epoll_wait(epoll_fd_, events, 128, timeout);
|
||||
|
||||
#if defined(ASIO_HAS_TIMERFD)
|
||||
bool check_timers = (timer_fd_ == -1);
|
||||
#else // defined(ASIO_HAS_TIMERFD)
|
||||
bool check_timers = true;
|
||||
#endif // defined(ASIO_HAS_TIMERFD)
|
||||
|
||||
// Dispatch the waiting events.
|
||||
for (int i = 0; i < num_events; ++i)
|
||||
{
|
||||
void* ptr = events[i].data.ptr;
|
||||
if (ptr == &interrupter_)
|
||||
{
|
||||
// No need to reset the interrupter since we're leaving the descriptor
|
||||
// in a ready-to-read state and relying on edge-triggered notifications
|
||||
// to make it so that we only get woken up when the descriptor's epoll
|
||||
// registration is updated.
|
||||
|
||||
#if defined(ASIO_HAS_TIMERFD)
|
||||
if (timer_fd_ == -1)
|
||||
check_timers = true;
|
||||
#else // defined(ASIO_HAS_TIMERFD)
|
||||
check_timers = true;
|
||||
#endif // defined(ASIO_HAS_TIMERFD)
|
||||
}
|
||||
#if defined(ASIO_HAS_TIMERFD)
|
||||
else if (ptr == &timer_fd_)
|
||||
{
|
||||
check_timers = true;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_TIMERFD)
|
||||
else
|
||||
{
|
||||
descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);
|
||||
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
|
||||
|
||||
// Exception operations must be processed first to ensure that any
|
||||
// out-of-band data is read before normal data.
|
||||
static const int flag[max_ops] = { EPOLLIN, EPOLLOUT, EPOLLPRI };
|
||||
for (int j = max_ops - 1; j >= 0; --j)
|
||||
{
|
||||
if (events[i].events & (flag[j] | EPOLLERR | EPOLLHUP))
|
||||
{
|
||||
while (reactor_op* op = descriptor_data->op_queue_[j].front())
|
||||
{
|
||||
if (op->perform())
|
||||
{
|
||||
descriptor_data->op_queue_[j].pop();
|
||||
ops.push(op);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (check_timers)
|
||||
{
|
||||
mutex::scoped_lock common_lock(mutex_);
|
||||
timer_queues_.get_ready_timers(ops);
|
||||
|
||||
#if defined(ASIO_HAS_TIMERFD)
|
||||
if (timer_fd_ != -1)
|
||||
{
|
||||
itimerspec new_timeout;
|
||||
itimerspec old_timeout;
|
||||
int flags = get_timeout(new_timeout);
|
||||
timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);
|
||||
}
|
||||
#endif // defined(ASIO_HAS_TIMERFD)
|
||||
}
|
||||
}
|
||||
|
||||
void epoll_reactor::interrupt()
|
||||
{
|
||||
epoll_event ev = { 0, { 0 } };
|
||||
ev.events = EPOLLIN | EPOLLERR | EPOLLET;
|
||||
ev.data.ptr = &interrupter_;
|
||||
epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, interrupter_.read_descriptor(), &ev);
|
||||
}
|
||||
|
||||
int epoll_reactor::do_epoll_create()
|
||||
{
|
||||
int fd = epoll_create(epoll_size);
|
||||
if (fd == -1)
|
||||
{
|
||||
asio::error_code ec(errno,
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "epoll");
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
void epoll_reactor::do_add_timer_queue(timer_queue_base& queue)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
timer_queues_.insert(&queue);
|
||||
}
|
||||
|
||||
void epoll_reactor::do_remove_timer_queue(timer_queue_base& queue)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
timer_queues_.erase(&queue);
|
||||
}
|
||||
|
||||
void epoll_reactor::update_timeout()
|
||||
{
|
||||
#if defined(ASIO_HAS_TIMERFD)
|
||||
if (timer_fd_ != -1)
|
||||
{
|
||||
itimerspec new_timeout;
|
||||
itimerspec old_timeout;
|
||||
int flags = get_timeout(new_timeout);
|
||||
timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);
|
||||
return;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_TIMERFD)
|
||||
interrupt();
|
||||
}
|
||||
|
||||
int epoll_reactor::get_timeout()
|
||||
{
|
||||
// By default we will wait no longer than 5 minutes. This will ensure that
|
||||
// any changes to the system clock are detected after no longer than this.
|
||||
return timer_queues_.wait_duration_msec(5 * 60 * 1000);
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_TIMERFD)
|
||||
int epoll_reactor::get_timeout(itimerspec& ts)
|
||||
{
|
||||
ts.it_interval.tv_sec = 0;
|
||||
ts.it_interval.tv_nsec = 0;
|
||||
|
||||
long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
|
||||
ts.it_value.tv_sec = usec / 1000000;
|
||||
ts.it_value.tv_nsec = usec ? (usec % 1000000) * 1000 : 1;
|
||||
|
||||
return usec ? 0 : TFD_TIMER_ABSTIME;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_TIMERFD)
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(ASIO_HAS_EPOLL)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP
|
125
ext/asio/asio/detail/impl/eventfd_select_interrupter.ipp
Normal file
125
ext/asio/asio/detail/impl/eventfd_select_interrupter.ipp
Normal file
@@ -0,0 +1,125 @@
|
||||
//
|
||||
// detail/impl/eventfd_select_interrupter.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP
|
||||
#define ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_EVENTFD)
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
|
||||
# include <asm/unistd.h>
|
||||
#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
|
||||
# include <sys/eventfd.h>
|
||||
#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
|
||||
#include "asio/detail/eventfd_select_interrupter.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
eventfd_select_interrupter::eventfd_select_interrupter()
|
||||
{
|
||||
#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
|
||||
write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0);
|
||||
#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
|
||||
write_descriptor_ = read_descriptor_ = ::eventfd(0, 0);
|
||||
#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
|
||||
if (read_descriptor_ != -1)
|
||||
{
|
||||
::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
|
||||
}
|
||||
else
|
||||
{
|
||||
int pipe_fds[2];
|
||||
if (pipe(pipe_fds) == 0)
|
||||
{
|
||||
read_descriptor_ = pipe_fds[0];
|
||||
::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
|
||||
write_descriptor_ = pipe_fds[1];
|
||||
::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
|
||||
}
|
||||
else
|
||||
{
|
||||
asio::error_code ec(errno,
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "eventfd_select_interrupter");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eventfd_select_interrupter::~eventfd_select_interrupter()
|
||||
{
|
||||
if (write_descriptor_ != -1 && write_descriptor_ != read_descriptor_)
|
||||
::close(write_descriptor_);
|
||||
if (read_descriptor_ != -1)
|
||||
::close(read_descriptor_);
|
||||
}
|
||||
|
||||
void eventfd_select_interrupter::interrupt()
|
||||
{
|
||||
uint64_t counter(1UL);
|
||||
int result = ::write(write_descriptor_, &counter, sizeof(uint64_t));
|
||||
(void)result;
|
||||
}
|
||||
|
||||
bool eventfd_select_interrupter::reset()
|
||||
{
|
||||
if (write_descriptor_ == read_descriptor_)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
// Only perform one read. The kernel maintains an atomic counter.
|
||||
uint64_t counter(0);
|
||||
errno = 0;
|
||||
int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t));
|
||||
if (bytes_read < 0 && errno == EINTR)
|
||||
continue;
|
||||
bool was_interrupted = (bytes_read > 0);
|
||||
return was_interrupted;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
// Clear all data from the pipe.
|
||||
char data[1024];
|
||||
int bytes_read = ::read(read_descriptor_, data, sizeof(data));
|
||||
if (bytes_read < 0 && errno == EINTR)
|
||||
continue;
|
||||
bool was_interrupted = (bytes_read > 0);
|
||||
while (bytes_read == sizeof(data))
|
||||
bytes_read = ::read(read_descriptor_, data, sizeof(data));
|
||||
return was_interrupted;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(ASIO_HAS_EVENTFD)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP
|
79
ext/asio/asio/detail/impl/kqueue_reactor.hpp
Normal file
79
ext/asio/asio/detail/impl/kqueue_reactor.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// detail/impl/kqueue_reactor.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_KQUEUE_REACTOR_HPP
|
||||
#define ASIO_DETAIL_IMPL_KQUEUE_REACTOR_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_KQUEUE)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Time_Traits>
|
||||
void kqueue_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)
|
||||
{
|
||||
do_add_timer_queue(queue);
|
||||
}
|
||||
|
||||
// Remove a timer queue from the reactor.
|
||||
template <typename Time_Traits>
|
||||
void kqueue_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue)
|
||||
{
|
||||
do_remove_timer_queue(queue);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void kqueue_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
|
||||
const typename Time_Traits::time_type& time,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
if (shutdown_)
|
||||
{
|
||||
io_service_.post_immediate_completion(op);
|
||||
return;
|
||||
}
|
||||
|
||||
bool earliest = queue.enqueue_timer(time, timer, op);
|
||||
io_service_.work_started();
|
||||
if (earliest)
|
||||
interrupt();
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
std::size_t kqueue_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
op_queue<operation> ops;
|
||||
std::size_t n = queue.cancel_timer(timer, ops);
|
||||
lock.unlock();
|
||||
io_service_.post_deferred_completions(ops);
|
||||
return n;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(ASIO_HAS_KQUEUE)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_KQUEUE_REACTOR_HPP
|
385
ext/asio/asio/detail/impl/kqueue_reactor.ipp
Normal file
385
ext/asio/asio/detail/impl/kqueue_reactor.ipp
Normal file
@@ -0,0 +1,385 @@
|
||||
//
|
||||
// detail/impl/kqueue_reactor.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_KQUEUE_REACTOR_IPP
|
||||
#define ASIO_DETAIL_IMPL_KQUEUE_REACTOR_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_KQUEUE)
|
||||
|
||||
#include "asio/detail/kqueue_reactor.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#if defined(__NetBSD__)
|
||||
# define ASIO_KQUEUE_EV_SET(ev, ident, filt, flags, fflags, data, udata) \
|
||||
EV_SET(ev, ident, filt, flags, fflags, \
|
||||
data, reinterpret_cast<intptr_t>(udata))
|
||||
#else
|
||||
# define ASIO_KQUEUE_EV_SET(ev, ident, filt, flags, fflags, data, udata) \
|
||||
EV_SET(ev, ident, filt, flags, fflags, data, udata)
|
||||
#endif
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
kqueue_reactor::kqueue_reactor(asio::io_service& io_service)
|
||||
: asio::detail::service_base<kqueue_reactor>(io_service),
|
||||
io_service_(use_service<io_service_impl>(io_service)),
|
||||
mutex_(),
|
||||
kqueue_fd_(do_kqueue_create()),
|
||||
interrupter_(),
|
||||
shutdown_(false)
|
||||
{
|
||||
// The interrupter is put into a permanently readable state. Whenever we
|
||||
// want to interrupt the blocked kevent call we register a one-shot read
|
||||
// operation against the descriptor.
|
||||
interrupter_.interrupt();
|
||||
}
|
||||
|
||||
kqueue_reactor::~kqueue_reactor()
|
||||
{
|
||||
close(kqueue_fd_);
|
||||
}
|
||||
|
||||
void kqueue_reactor::shutdown_service()
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
shutdown_ = true;
|
||||
lock.unlock();
|
||||
|
||||
op_queue<operation> ops;
|
||||
|
||||
while (descriptor_state* state = registered_descriptors_.first())
|
||||
{
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
ops.push(state->op_queue_[i]);
|
||||
state->shutdown_ = true;
|
||||
registered_descriptors_.free(state);
|
||||
}
|
||||
|
||||
timer_queues_.get_all_timers(ops);
|
||||
}
|
||||
|
||||
void kqueue_reactor::init_task()
|
||||
{
|
||||
io_service_.init_task();
|
||||
}
|
||||
|
||||
int kqueue_reactor::register_descriptor(socket_type,
|
||||
kqueue_reactor::per_descriptor_data& descriptor_data)
|
||||
{
|
||||
mutex::scoped_lock lock(registered_descriptors_mutex_);
|
||||
|
||||
descriptor_data = registered_descriptors_.alloc();
|
||||
descriptor_data->shutdown_ = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kqueue_reactor::start_op(int op_type, socket_type descriptor,
|
||||
kqueue_reactor::per_descriptor_data& descriptor_data,
|
||||
reactor_op* op, bool allow_speculative)
|
||||
{
|
||||
if (!descriptor_data)
|
||||
{
|
||||
op->ec_ = asio::error::bad_descriptor;
|
||||
post_immediate_completion(op);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
|
||||
|
||||
if (descriptor_data->shutdown_)
|
||||
{
|
||||
post_immediate_completion(op);
|
||||
return;
|
||||
}
|
||||
|
||||
bool first = descriptor_data->op_queue_[op_type].empty();
|
||||
if (first)
|
||||
{
|
||||
if (allow_speculative)
|
||||
{
|
||||
if (op_type != read_op || descriptor_data->op_queue_[except_op].empty())
|
||||
{
|
||||
if (op->perform())
|
||||
{
|
||||
descriptor_lock.unlock();
|
||||
io_service_.post_immediate_completion(op);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
descriptor_data->op_queue_[op_type].push(op);
|
||||
io_service_.work_started();
|
||||
|
||||
if (first)
|
||||
{
|
||||
struct kevent event;
|
||||
switch (op_type)
|
||||
{
|
||||
case read_op:
|
||||
ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
|
||||
EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
|
||||
break;
|
||||
case write_op:
|
||||
ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_WRITE,
|
||||
EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
|
||||
break;
|
||||
case except_op:
|
||||
if (!descriptor_data->op_queue_[read_op].empty())
|
||||
return; // Already registered for read events.
|
||||
ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
|
||||
EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data);
|
||||
break;
|
||||
}
|
||||
|
||||
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
|
||||
{
|
||||
op->ec_ = asio::error_code(errno,
|
||||
asio::error::get_system_category());
|
||||
descriptor_data->op_queue_[op_type].pop();
|
||||
io_service_.post_deferred_completion(op);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kqueue_reactor::cancel_ops(socket_type,
|
||||
kqueue_reactor::per_descriptor_data& descriptor_data)
|
||||
{
|
||||
if (!descriptor_data)
|
||||
return;
|
||||
|
||||
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
|
||||
|
||||
op_queue<operation> ops;
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
{
|
||||
while (reactor_op* op = descriptor_data->op_queue_[i].front())
|
||||
{
|
||||
op->ec_ = asio::error::operation_aborted;
|
||||
descriptor_data->op_queue_[i].pop();
|
||||
ops.push(op);
|
||||
}
|
||||
}
|
||||
|
||||
descriptor_lock.unlock();
|
||||
|
||||
io_service_.post_deferred_completions(ops);
|
||||
}
|
||||
|
||||
void kqueue_reactor::close_descriptor(socket_type,
|
||||
kqueue_reactor::per_descriptor_data& descriptor_data)
|
||||
{
|
||||
if (!descriptor_data)
|
||||
return;
|
||||
|
||||
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
|
||||
mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
|
||||
|
||||
if (!descriptor_data->shutdown_)
|
||||
{
|
||||
// Remove the descriptor from the set of known descriptors. The descriptor
|
||||
// will be automatically removed from the kqueue set when it is closed.
|
||||
|
||||
op_queue<operation> ops;
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
{
|
||||
while (reactor_op* op = descriptor_data->op_queue_[i].front())
|
||||
{
|
||||
op->ec_ = asio::error::operation_aborted;
|
||||
descriptor_data->op_queue_[i].pop();
|
||||
ops.push(op);
|
||||
}
|
||||
}
|
||||
|
||||
descriptor_data->shutdown_ = true;
|
||||
|
||||
descriptor_lock.unlock();
|
||||
|
||||
registered_descriptors_.free(descriptor_data);
|
||||
descriptor_data = 0;
|
||||
|
||||
descriptors_lock.unlock();
|
||||
|
||||
io_service_.post_deferred_completions(ops);
|
||||
}
|
||||
}
|
||||
|
||||
void kqueue_reactor::run(bool block, op_queue<operation>& ops)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
|
||||
// Determine how long to block while waiting for events.
|
||||
timespec timeout_buf = { 0, 0 };
|
||||
timespec* timeout = block ? get_timeout(timeout_buf) : &timeout_buf;
|
||||
|
||||
lock.unlock();
|
||||
|
||||
// Block on the kqueue descriptor.
|
||||
struct kevent events[128];
|
||||
int num_events = kevent(kqueue_fd_, 0, 0, events, 128, timeout);
|
||||
|
||||
// Dispatch the waiting events.
|
||||
for (int i = 0; i < num_events; ++i)
|
||||
{
|
||||
int descriptor = events[i].ident;
|
||||
void* ptr = reinterpret_cast<void*>(events[i].udata);
|
||||
if (ptr == &interrupter_)
|
||||
{
|
||||
// No need to reset the interrupter since we're leaving the descriptor
|
||||
// in a ready-to-read state and relying on one-shot notifications.
|
||||
}
|
||||
else
|
||||
{
|
||||
descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);
|
||||
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
|
||||
|
||||
// Exception operations must be processed first to ensure that any
|
||||
// out-of-band data is read before normal data.
|
||||
#if defined(__NetBSD__)
|
||||
static const unsigned int filter[max_ops] =
|
||||
#else
|
||||
static const int filter[max_ops] =
|
||||
#endif
|
||||
{ EVFILT_READ, EVFILT_WRITE, EVFILT_READ };
|
||||
for (int j = max_ops - 1; j >= 0; --j)
|
||||
{
|
||||
if (events[i].filter == filter[j])
|
||||
{
|
||||
if (j != except_op || events[i].flags & EV_OOBAND)
|
||||
{
|
||||
while (reactor_op* op = descriptor_data->op_queue_[j].front())
|
||||
{
|
||||
if (events[i].flags & EV_ERROR)
|
||||
{
|
||||
op->ec_ = asio::error_code(events[i].data,
|
||||
asio::error::get_system_category());
|
||||
descriptor_data->op_queue_[j].pop();
|
||||
ops.push(op);
|
||||
}
|
||||
if (op->perform())
|
||||
{
|
||||
descriptor_data->op_queue_[j].pop();
|
||||
ops.push(op);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Renew registration for event notifications.
|
||||
struct kevent event;
|
||||
switch (events[i].filter)
|
||||
{
|
||||
case EVFILT_READ:
|
||||
if (!descriptor_data->op_queue_[read_op].empty())
|
||||
ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
|
||||
EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
|
||||
else if (!descriptor_data->op_queue_[except_op].empty())
|
||||
ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_READ,
|
||||
EV_ADD | EV_ONESHOT, EV_OOBAND, 0, descriptor_data);
|
||||
else
|
||||
continue;
|
||||
case EVFILT_WRITE:
|
||||
if (!descriptor_data->op_queue_[write_op].empty())
|
||||
ASIO_KQUEUE_EV_SET(&event, descriptor, EVFILT_WRITE,
|
||||
EV_ADD | EV_ONESHOT, 0, 0, descriptor_data);
|
||||
else
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
|
||||
{
|
||||
asio::error_code error(errno,
|
||||
asio::error::get_system_category());
|
||||
for (int j = 0; j < max_ops; ++j)
|
||||
{
|
||||
while (reactor_op* op = descriptor_data->op_queue_[j].front())
|
||||
{
|
||||
op->ec_ = error;
|
||||
descriptor_data->op_queue_[j].pop();
|
||||
ops.push(op);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lock.lock();
|
||||
timer_queues_.get_ready_timers(ops);
|
||||
}
|
||||
|
||||
void kqueue_reactor::interrupt()
|
||||
{
|
||||
struct kevent event;
|
||||
ASIO_KQUEUE_EV_SET(&event, interrupter_.read_descriptor(),
|
||||
EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, &interrupter_);
|
||||
::kevent(kqueue_fd_, &event, 1, 0, 0, 0);
|
||||
}
|
||||
|
||||
int kqueue_reactor::do_kqueue_create()
|
||||
{
|
||||
int fd = ::kqueue();
|
||||
if (fd == -1)
|
||||
{
|
||||
asio::error_code ec(errno,
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "kqueue");
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
void kqueue_reactor::do_add_timer_queue(timer_queue_base& queue)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
timer_queues_.insert(&queue);
|
||||
}
|
||||
|
||||
void kqueue_reactor::do_remove_timer_queue(timer_queue_base& queue)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
timer_queues_.erase(&queue);
|
||||
}
|
||||
|
||||
timespec* kqueue_reactor::get_timeout(timespec& ts)
|
||||
{
|
||||
// By default we will wait no longer than 5 minutes. This will ensure that
|
||||
// any changes to the system clock are detected after no longer than this.
|
||||
long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
|
||||
ts.tv_sec = usec / 1000000;
|
||||
ts.tv_nsec = (usec % 1000000) * 1000;
|
||||
return &ts;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#undef ASIO_KQUEUE_EV_SET
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(ASIO_HAS_KQUEUE)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_KQUEUE_REACTOR_IPP
|
96
ext/asio/asio/detail/impl/pipe_select_interrupter.ipp
Normal file
96
ext/asio/asio/detail/impl/pipe_select_interrupter.ipp
Normal file
@@ -0,0 +1,96 @@
|
||||
//
|
||||
// detail/impl/pipe_select_interrupter.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP
|
||||
#define ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if !defined(BOOST_WINDOWS)
|
||||
#if !defined(__CYGWIN__)
|
||||
#if !defined(__SYMBIAN32__)
|
||||
#if !defined(ASIO_HAS_EVENTFD)
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include "asio/detail/pipe_select_interrupter.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
pipe_select_interrupter::pipe_select_interrupter()
|
||||
{
|
||||
int pipe_fds[2];
|
||||
if (pipe(pipe_fds) == 0)
|
||||
{
|
||||
read_descriptor_ = pipe_fds[0];
|
||||
::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
|
||||
write_descriptor_ = pipe_fds[1];
|
||||
::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
|
||||
}
|
||||
else
|
||||
{
|
||||
asio::error_code ec(errno,
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "pipe_select_interrupter");
|
||||
}
|
||||
}
|
||||
|
||||
pipe_select_interrupter::~pipe_select_interrupter()
|
||||
{
|
||||
if (read_descriptor_ != -1)
|
||||
::close(read_descriptor_);
|
||||
if (write_descriptor_ != -1)
|
||||
::close(write_descriptor_);
|
||||
}
|
||||
|
||||
void pipe_select_interrupter::interrupt()
|
||||
{
|
||||
char byte = 0;
|
||||
int result = ::write(write_descriptor_, &byte, 1);
|
||||
(void)result;
|
||||
}
|
||||
|
||||
bool pipe_select_interrupter::reset()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
char data[1024];
|
||||
int bytes_read = ::read(read_descriptor_, data, sizeof(data));
|
||||
if (bytes_read < 0 && errno == EINTR)
|
||||
continue;
|
||||
bool was_interrupted = (bytes_read > 0);
|
||||
while (bytes_read == sizeof(data))
|
||||
bytes_read = ::read(read_descriptor_, data, sizeof(data));
|
||||
return was_interrupted;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // !defined(ASIO_HAS_EVENTFD)
|
||||
#endif // !defined(__SYMBIAN32__)
|
||||
#endif // !defined(__CYGWIN__)
|
||||
#endif // !defined(BOOST_WINDOWS)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP
|
46
ext/asio/asio/detail/impl/posix_event.ipp
Normal file
46
ext/asio/asio/detail/impl/posix_event.ipp
Normal file
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// detail/impl/posix_event.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_POSIX_EVENT_IPP
|
||||
#define ASIO_DETAIL_IMPL_POSIX_EVENT_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
|
||||
|
||||
#include "asio/detail/posix_event.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
posix_event::posix_event()
|
||||
: signalled_(false)
|
||||
{
|
||||
int error = ::pthread_cond_init(&cond_, 0);
|
||||
asio::error_code ec(error,
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "event");
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_POSIX_EVENT_IPP
|
46
ext/asio/asio/detail/impl/posix_mutex.ipp
Normal file
46
ext/asio/asio/detail/impl/posix_mutex.ipp
Normal file
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// detail/impl/posix_mutex.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_POSIX_MUTEX_IPP
|
||||
#define ASIO_DETAIL_IMPL_POSIX_MUTEX_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
|
||||
|
||||
#include "asio/detail/posix_mutex.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
posix_mutex::posix_mutex()
|
||||
{
|
||||
int error = ::pthread_mutex_init(&mutex_, 0);
|
||||
asio::error_code ec(error,
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "mutex");
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_POSIX_MUTEX_IPP
|
74
ext/asio/asio/detail/impl/posix_thread.ipp
Normal file
74
ext/asio/asio/detail/impl/posix_thread.ipp
Normal file
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// detail/impl/posix_thread.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_POSIX_THREAD_IPP
|
||||
#define ASIO_DETAIL_IMPL_POSIX_THREAD_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
|
||||
|
||||
#include "asio/detail/posix_thread.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
posix_thread::~posix_thread()
|
||||
{
|
||||
if (!joined_)
|
||||
::pthread_detach(thread_);
|
||||
}
|
||||
|
||||
void posix_thread::join()
|
||||
{
|
||||
if (!joined_)
|
||||
{
|
||||
::pthread_join(thread_, 0);
|
||||
joined_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void posix_thread::start_thread(func_base* arg)
|
||||
{
|
||||
int error = ::pthread_create(&thread_, 0,
|
||||
asio_detail_posix_thread_function, arg);
|
||||
if (error != 0)
|
||||
{
|
||||
delete arg;
|
||||
asio::error_code ec(error,
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "thread");
|
||||
}
|
||||
}
|
||||
|
||||
void* asio_detail_posix_thread_function(void* arg)
|
||||
{
|
||||
posix_thread::auto_func_base_ptr func = {
|
||||
static_cast<posix_thread::func_base*>(arg) };
|
||||
func.ptr->run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_POSIX_THREAD_IPP
|
46
ext/asio/asio/detail/impl/posix_tss_ptr.ipp
Normal file
46
ext/asio/asio/detail/impl/posix_tss_ptr.ipp
Normal file
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// detail/impl/posix_tss_ptr.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_POSIX_TSS_PTR_IPP
|
||||
#define ASIO_DETAIL_IMPL_POSIX_TSS_PTR_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
|
||||
|
||||
#include "asio/detail/posix_tss_ptr.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
void posix_tss_ptr_create(pthread_key_t& key)
|
||||
{
|
||||
int error = ::pthread_key_create(&key, 0);
|
||||
asio::error_code ec(error,
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "tss");
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(BOOST_HAS_PTHREADS) && !defined(ASIO_DISABLE_THREADS)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_POSIX_TSS_PTR_IPP
|
136
ext/asio/asio/detail/impl/reactive_descriptor_service.ipp
Normal file
136
ext/asio/asio/detail/impl/reactive_descriptor_service.ipp
Normal file
@@ -0,0 +1,136 @@
|
||||
//
|
||||
// detail/impl/reactive_descriptor_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP
|
||||
#define ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/detail/reactive_descriptor_service.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
reactive_descriptor_service::reactive_descriptor_service(
|
||||
asio::io_service& io_service)
|
||||
: reactor_(asio::use_service<reactor>(io_service))
|
||||
{
|
||||
reactor_.init_task();
|
||||
}
|
||||
|
||||
void reactive_descriptor_service::shutdown_service()
|
||||
{
|
||||
}
|
||||
|
||||
void reactive_descriptor_service::construct(
|
||||
reactive_descriptor_service::implementation_type& impl)
|
||||
{
|
||||
impl.descriptor_ = -1;
|
||||
impl.state_ = 0;
|
||||
}
|
||||
|
||||
void reactive_descriptor_service::destroy(
|
||||
reactive_descriptor_service::implementation_type& impl)
|
||||
{
|
||||
if (is_open(impl))
|
||||
reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_);
|
||||
|
||||
asio::error_code ignored_ec;
|
||||
descriptor_ops::close(impl.descriptor_, impl.state_, ignored_ec);
|
||||
}
|
||||
|
||||
asio::error_code reactive_descriptor_service::assign(
|
||||
reactive_descriptor_service::implementation_type& impl,
|
||||
const native_type& native_descriptor, asio::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = asio::error::already_open;
|
||||
return ec;
|
||||
}
|
||||
|
||||
if (int err = reactor_.register_descriptor(
|
||||
native_descriptor, impl.reactor_data_))
|
||||
{
|
||||
ec = asio::error_code(err,
|
||||
asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
impl.descriptor_ = native_descriptor;
|
||||
impl.state_ = 0;
|
||||
ec = asio::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
asio::error_code reactive_descriptor_service::close(
|
||||
reactive_descriptor_service::implementation_type& impl,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_);
|
||||
|
||||
if (descriptor_ops::close(impl.descriptor_, impl.state_, ec) == 0)
|
||||
construct(impl);
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
asio::error_code reactive_descriptor_service::cancel(
|
||||
reactive_descriptor_service::implementation_type& impl,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
ec = asio::error::bad_descriptor;
|
||||
return ec;
|
||||
}
|
||||
|
||||
reactor_.cancel_ops(impl.descriptor_, impl.reactor_data_);
|
||||
ec = asio::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
void reactive_descriptor_service::start_op(
|
||||
reactive_descriptor_service::implementation_type& impl,
|
||||
int op_type, reactor_op* op, bool non_blocking, bool noop)
|
||||
{
|
||||
if (!noop)
|
||||
{
|
||||
if ((impl.state_ & descriptor_ops::non_blocking) ||
|
||||
descriptor_ops::set_internal_non_blocking(
|
||||
impl.descriptor_, impl.state_, op->ec_))
|
||||
{
|
||||
reactor_.start_op(op_type, impl.descriptor_,
|
||||
impl.reactor_data_, op, non_blocking);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
reactor_.post_immediate_completion(op);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP
|
151
ext/asio/asio/detail/impl/reactive_serial_port_service.ipp
Normal file
151
ext/asio/asio/detail/impl/reactive_serial_port_service.ipp
Normal file
@@ -0,0 +1,151 @@
|
||||
//
|
||||
// detail/impl/reactive_serial_port_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP
|
||||
#define ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_SERIAL_PORT)
|
||||
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
|
||||
#include <cstring>
|
||||
#include "asio/detail/reactive_serial_port_service.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
reactive_serial_port_service::reactive_serial_port_service(
|
||||
asio::io_service& io_service)
|
||||
: descriptor_service_(io_service)
|
||||
{
|
||||
}
|
||||
|
||||
void reactive_serial_port_service::shutdown_service()
|
||||
{
|
||||
descriptor_service_.shutdown_service();
|
||||
}
|
||||
|
||||
asio::error_code reactive_serial_port_service::open(
|
||||
reactive_serial_port_service::implementation_type& impl,
|
||||
const std::string& device, asio::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = asio::error::already_open;
|
||||
return ec;
|
||||
}
|
||||
|
||||
descriptor_ops::state_type state = 0;
|
||||
int fd = descriptor_ops::open(device.c_str(),
|
||||
O_RDWR | O_NONBLOCK | O_NOCTTY, ec);
|
||||
if (fd < 0)
|
||||
return ec;
|
||||
|
||||
int s = descriptor_ops::fcntl(fd, F_GETFL, ec);
|
||||
if (s >= 0)
|
||||
s = descriptor_ops::fcntl(fd, F_SETFL, s | O_NONBLOCK, ec);
|
||||
if (s < 0)
|
||||
{
|
||||
asio::error_code ignored_ec;
|
||||
descriptor_ops::close(fd, state, ignored_ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Set up default serial port options.
|
||||
termios ios;
|
||||
errno = 0;
|
||||
s = descriptor_ops::error_wrapper(::tcgetattr(fd, &ios), ec);
|
||||
if (s >= 0)
|
||||
{
|
||||
#if defined(_BSD_SOURCE)
|
||||
::cfmakeraw(&ios);
|
||||
#else
|
||||
ios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK
|
||||
| ISTRIP | INLCR | IGNCR | ICRNL | IXON);
|
||||
ios.c_oflag &= ~OPOST;
|
||||
ios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
|
||||
ios.c_cflag &= ~(CSIZE | PARENB);
|
||||
ios.c_cflag |= CS8;
|
||||
#endif
|
||||
ios.c_iflag |= IGNPAR;
|
||||
ios.c_cflag |= CREAD | CLOCAL;
|
||||
errno = 0;
|
||||
s = descriptor_ops::error_wrapper(::tcsetattr(fd, TCSANOW, &ios), ec);
|
||||
}
|
||||
if (s < 0)
|
||||
{
|
||||
asio::error_code ignored_ec;
|
||||
descriptor_ops::close(fd, state, ignored_ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
// We're done. Take ownership of the serial port descriptor.
|
||||
if (descriptor_service_.assign(impl, fd, ec))
|
||||
{
|
||||
asio::error_code ignored_ec;
|
||||
descriptor_ops::close(fd, state, ignored_ec);
|
||||
}
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
asio::error_code reactive_serial_port_service::do_set_option(
|
||||
reactive_serial_port_service::implementation_type& impl,
|
||||
reactive_serial_port_service::store_function_type store,
|
||||
const void* option, asio::error_code& ec)
|
||||
{
|
||||
termios ios;
|
||||
errno = 0;
|
||||
descriptor_ops::error_wrapper(::tcgetattr(
|
||||
descriptor_service_.native(impl), &ios), ec);
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
if (store(option, ios, ec))
|
||||
return ec;
|
||||
|
||||
errno = 0;
|
||||
descriptor_ops::error_wrapper(::tcsetattr(
|
||||
descriptor_service_.native(impl), TCSANOW, &ios), ec);
|
||||
return ec;
|
||||
}
|
||||
|
||||
asio::error_code reactive_serial_port_service::do_get_option(
|
||||
const reactive_serial_port_service::implementation_type& impl,
|
||||
reactive_serial_port_service::load_function_type load,
|
||||
void* option, asio::error_code& ec) const
|
||||
{
|
||||
termios ios;
|
||||
errno = 0;
|
||||
descriptor_ops::error_wrapper(::tcgetattr(
|
||||
descriptor_service_.native(impl), &ios), ec);
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
return load(option, ios, ec);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
#endif // defined(ASIO_HAS_SERIAL_PORT)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP
|
212
ext/asio/asio/detail/impl/reactive_socket_service_base.ipp
Normal file
212
ext/asio/asio/detail/impl/reactive_socket_service_base.ipp
Normal file
@@ -0,0 +1,212 @@
|
||||
//
|
||||
// detail/reactive_socket_service_base.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP
|
||||
#define ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if !defined(ASIO_HAS_IOCP)
|
||||
|
||||
#include "asio/detail/reactive_socket_service_base.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
reactive_socket_service_base::reactive_socket_service_base(
|
||||
asio::io_service& io_service)
|
||||
: reactor_(use_service<reactor>(io_service))
|
||||
{
|
||||
reactor_.init_task();
|
||||
}
|
||||
|
||||
void reactive_socket_service_base::shutdown_service()
|
||||
{
|
||||
}
|
||||
|
||||
void reactive_socket_service_base::construct(
|
||||
reactive_socket_service_base::base_implementation_type& impl)
|
||||
{
|
||||
impl.socket_ = invalid_socket;
|
||||
impl.state_ = 0;
|
||||
}
|
||||
|
||||
void reactive_socket_service_base::destroy(
|
||||
reactive_socket_service_base::base_implementation_type& impl)
|
||||
{
|
||||
if (impl.socket_ != invalid_socket)
|
||||
{
|
||||
reactor_.close_descriptor(impl.socket_, impl.reactor_data_);
|
||||
|
||||
asio::error_code ignored_ec;
|
||||
socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
|
||||
}
|
||||
}
|
||||
|
||||
asio::error_code reactive_socket_service_base::close(
|
||||
reactive_socket_service_base::base_implementation_type& impl,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
reactor_.close_descriptor(impl.socket_, impl.reactor_data_);
|
||||
|
||||
if (socket_ops::close(impl.socket_, impl.state_, true, ec) == 0)
|
||||
construct(impl);
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
asio::error_code reactive_socket_service_base::cancel(
|
||||
reactive_socket_service_base::base_implementation_type& impl,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
ec = asio::error::bad_descriptor;
|
||||
return ec;
|
||||
}
|
||||
|
||||
reactor_.cancel_ops(impl.socket_, impl.reactor_data_);
|
||||
ec = asio::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
asio::error_code reactive_socket_service_base::do_open(
|
||||
reactive_socket_service_base::base_implementation_type& impl,
|
||||
int af, int type, int protocol, asio::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = asio::error::already_open;
|
||||
return ec;
|
||||
}
|
||||
|
||||
socket_holder sock(socket_ops::socket(af, type, protocol, ec));
|
||||
if (sock.get() == invalid_socket)
|
||||
return ec;
|
||||
|
||||
if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_))
|
||||
{
|
||||
ec = asio::error_code(err,
|
||||
asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
impl.socket_ = sock.release();
|
||||
switch (type)
|
||||
{
|
||||
case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
|
||||
case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
|
||||
default: impl.state_ = 0; break;
|
||||
}
|
||||
ec = asio::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
asio::error_code reactive_socket_service_base::do_assign(
|
||||
reactive_socket_service_base::base_implementation_type& impl, int type,
|
||||
const reactive_socket_service_base::native_type& native_socket,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = asio::error::already_open;
|
||||
return ec;
|
||||
}
|
||||
|
||||
if (int err = reactor_.register_descriptor(
|
||||
native_socket, impl.reactor_data_))
|
||||
{
|
||||
ec = asio::error_code(err,
|
||||
asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
impl.socket_ = native_socket;
|
||||
switch (type)
|
||||
{
|
||||
case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
|
||||
case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
|
||||
default: impl.state_ = 0; break;
|
||||
}
|
||||
ec = asio::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
void reactive_socket_service_base::start_op(
|
||||
reactive_socket_service_base::base_implementation_type& impl,
|
||||
int op_type, reactor_op* op, bool non_blocking, bool noop)
|
||||
{
|
||||
if (!noop)
|
||||
{
|
||||
if ((impl.state_ & socket_ops::non_blocking)
|
||||
|| socket_ops::set_internal_non_blocking(
|
||||
impl.socket_, impl.state_, op->ec_))
|
||||
{
|
||||
reactor_.start_op(op_type, impl.socket_,
|
||||
impl.reactor_data_, op, non_blocking);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
reactor_.post_immediate_completion(op);
|
||||
}
|
||||
|
||||
void reactive_socket_service_base::start_accept_op(
|
||||
reactive_socket_service_base::base_implementation_type& impl,
|
||||
reactor_op* op, bool peer_is_open)
|
||||
{
|
||||
if (!peer_is_open)
|
||||
start_op(impl, reactor::read_op, op, true, false);
|
||||
else
|
||||
{
|
||||
op->ec_ = asio::error::already_open;
|
||||
reactor_.post_immediate_completion(op);
|
||||
}
|
||||
}
|
||||
|
||||
void reactive_socket_service_base::start_connect_op(
|
||||
reactive_socket_service_base::base_implementation_type& impl,
|
||||
reactor_op* op, const socket_addr_type* addr, size_t addrlen)
|
||||
{
|
||||
if ((impl.state_ & socket_ops::non_blocking)
|
||||
|| socket_ops::set_internal_non_blocking(
|
||||
impl.socket_, impl.state_, op->ec_))
|
||||
{
|
||||
if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0)
|
||||
{
|
||||
if (op->ec_ == asio::error::in_progress
|
||||
|| op->ec_ == asio::error::would_block)
|
||||
{
|
||||
op->ec_ = asio::error_code();
|
||||
reactor_.start_op(reactor::connect_op,
|
||||
impl.socket_, impl.reactor_data_, op, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reactor_.post_immediate_completion(op);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // !defined(ASIO_HAS_IOCP)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP
|
106
ext/asio/asio/detail/impl/resolver_service_base.ipp
Normal file
106
ext/asio/asio/detail/impl/resolver_service_base.ipp
Normal file
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// detail/impl/resolver_service_base.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP
|
||||
#define ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "asio/detail/resolver_service_base.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class resolver_service_base::work_io_service_runner
|
||||
{
|
||||
public:
|
||||
work_io_service_runner(asio::io_service& io_service)
|
||||
: io_service_(io_service) {}
|
||||
void operator()() { io_service_.run(); }
|
||||
private:
|
||||
asio::io_service& io_service_;
|
||||
};
|
||||
|
||||
resolver_service_base::resolver_service_base(
|
||||
asio::io_service& io_service)
|
||||
: io_service_impl_(asio::use_service<io_service_impl>(io_service)),
|
||||
work_io_service_(new asio::io_service),
|
||||
work_io_service_impl_(asio::use_service<
|
||||
io_service_impl>(*work_io_service_)),
|
||||
work_(new asio::io_service::work(*work_io_service_)),
|
||||
work_thread_(0)
|
||||
{
|
||||
}
|
||||
|
||||
resolver_service_base::~resolver_service_base()
|
||||
{
|
||||
shutdown_service();
|
||||
}
|
||||
|
||||
void resolver_service_base::shutdown_service()
|
||||
{
|
||||
work_.reset();
|
||||
if (work_io_service_)
|
||||
{
|
||||
work_io_service_->stop();
|
||||
if (work_thread_)
|
||||
{
|
||||
work_thread_->join();
|
||||
work_thread_.reset();
|
||||
}
|
||||
work_io_service_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void resolver_service_base::construct(
|
||||
resolver_service_base::implementation_type& impl)
|
||||
{
|
||||
impl.reset(static_cast<void*>(0), socket_ops::noop_deleter());
|
||||
}
|
||||
|
||||
void resolver_service_base::destroy(
|
||||
resolver_service_base::implementation_type&)
|
||||
{
|
||||
}
|
||||
|
||||
void resolver_service_base::cancel(
|
||||
resolver_service_base::implementation_type& impl)
|
||||
{
|
||||
impl.reset(static_cast<void*>(0), socket_ops::noop_deleter());
|
||||
}
|
||||
|
||||
void resolver_service_base::start_resolve_op(operation* op)
|
||||
{
|
||||
start_work_thread();
|
||||
io_service_impl_.work_started();
|
||||
work_io_service_impl_.post_immediate_completion(op);
|
||||
}
|
||||
|
||||
void resolver_service_base::start_work_thread()
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
if (!work_thread_)
|
||||
{
|
||||
work_thread_.reset(new asio::detail::thread(
|
||||
work_io_service_runner(*work_io_service_)));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP
|
84
ext/asio/asio/detail/impl/select_reactor.hpp
Normal file
84
ext/asio/asio/detail/impl/select_reactor.hpp
Normal file
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// detail/impl/select_reactor.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_SELECT_REACTOR_HPP
|
||||
#define ASIO_DETAIL_IMPL_SELECT_REACTOR_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_IOCP) \
|
||||
|| (!defined(ASIO_HAS_DEV_POLL) \
|
||||
&& !defined(ASIO_HAS_EPOLL) \
|
||||
&& !defined(ASIO_HAS_KQUEUE))
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Time_Traits>
|
||||
void select_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)
|
||||
{
|
||||
do_add_timer_queue(queue);
|
||||
}
|
||||
|
||||
// Remove a timer queue from the reactor.
|
||||
template <typename Time_Traits>
|
||||
void select_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue)
|
||||
{
|
||||
do_remove_timer_queue(queue);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void select_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
|
||||
const typename Time_Traits::time_type& time,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
if (shutdown_)
|
||||
{
|
||||
io_service_.post_immediate_completion(op);
|
||||
return;
|
||||
}
|
||||
|
||||
bool earliest = queue.enqueue_timer(time, timer, op);
|
||||
io_service_.work_started();
|
||||
if (earliest)
|
||||
interrupter_.interrupt();
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
std::size_t select_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
op_queue<operation> ops;
|
||||
std::size_t n = queue.cancel_timer(timer, ops);
|
||||
lock.unlock();
|
||||
io_service_.post_deferred_completions(ops);
|
||||
return n;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
// || (!defined(ASIO_HAS_DEV_POLL)
|
||||
// && !defined(ASIO_HAS_EPOLL)
|
||||
// && !defined(ASIO_HAS_KQUEUE))
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_SELECT_REACTOR_HPP
|
273
ext/asio/asio/detail/impl/select_reactor.ipp
Normal file
273
ext/asio/asio/detail/impl/select_reactor.ipp
Normal file
@@ -0,0 +1,273 @@
|
||||
//
|
||||
// detail/impl/select_reactor.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_SELECT_REACTOR_IPP
|
||||
#define ASIO_DETAIL_IMPL_SELECT_REACTOR_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_IOCP) \
|
||||
|| (!defined(ASIO_HAS_DEV_POLL) \
|
||||
&& !defined(ASIO_HAS_EPOLL) \
|
||||
&& !defined(ASIO_HAS_KQUEUE))
|
||||
|
||||
#include "asio/detail/bind_handler.hpp"
|
||||
#include "asio/detail/fd_set_adapter.hpp"
|
||||
#include "asio/detail/select_reactor.hpp"
|
||||
#include "asio/detail/signal_blocker.hpp"
|
||||
#include "asio/detail/socket_ops.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
select_reactor::select_reactor(asio::io_service& io_service)
|
||||
: asio::detail::service_base<select_reactor>(io_service),
|
||||
io_service_(use_service<io_service_impl>(io_service)),
|
||||
mutex_(),
|
||||
interrupter_(),
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
stop_thread_(false),
|
||||
thread_(0),
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
shutdown_(false)
|
||||
{
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
asio::detail::signal_blocker sb;
|
||||
thread_ = new asio::detail::thread(
|
||||
bind_handler(&select_reactor::call_run_thread, this));
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
}
|
||||
|
||||
select_reactor::~select_reactor()
|
||||
{
|
||||
shutdown_service();
|
||||
}
|
||||
|
||||
void select_reactor::shutdown_service()
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
shutdown_ = true;
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
stop_thread_ = true;
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
lock.unlock();
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
if (thread_)
|
||||
{
|
||||
interrupter_.interrupt();
|
||||
thread_->join();
|
||||
delete thread_;
|
||||
thread_ = 0;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
op_queue<operation> ops;
|
||||
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
op_queue_[i].get_all_operations(ops);
|
||||
|
||||
timer_queues_.get_all_timers(ops);
|
||||
}
|
||||
|
||||
void select_reactor::init_task()
|
||||
{
|
||||
io_service_.init_task();
|
||||
}
|
||||
|
||||
int select_reactor::register_descriptor(socket_type,
|
||||
select_reactor::per_descriptor_data&)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void select_reactor::start_op(int op_type, socket_type descriptor,
|
||||
select_reactor::per_descriptor_data&, reactor_op* op, bool)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
if (shutdown_)
|
||||
{
|
||||
post_immediate_completion(op);
|
||||
return;
|
||||
}
|
||||
|
||||
bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
|
||||
io_service_.work_started();
|
||||
if (first)
|
||||
interrupter_.interrupt();
|
||||
}
|
||||
|
||||
void select_reactor::cancel_ops(socket_type descriptor,
|
||||
select_reactor::per_descriptor_data&)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
|
||||
}
|
||||
|
||||
void select_reactor::close_descriptor(socket_type descriptor,
|
||||
select_reactor::per_descriptor_data&)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
cancel_ops_unlocked(descriptor, asio::error::operation_aborted);
|
||||
}
|
||||
|
||||
void select_reactor::run(bool block, op_queue<operation>& ops)
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
// Check if the thread is supposed to stop.
|
||||
if (stop_thread_)
|
||||
return;
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
// Set up the descriptor sets.
|
||||
fd_set_adapter fds[max_select_ops];
|
||||
fds[read_op].set(interrupter_.read_descriptor());
|
||||
socket_type max_fd = 0;
|
||||
bool have_work_to_do = !timer_queues_.all_empty();
|
||||
for (int i = 0; i < max_select_ops; ++i)
|
||||
{
|
||||
have_work_to_do = have_work_to_do || !op_queue_[i].empty();
|
||||
op_queue_[i].get_descriptors(fds[i], ops);
|
||||
if (fds[i].max_descriptor() > max_fd)
|
||||
max_fd = fds[i].max_descriptor();
|
||||
}
|
||||
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
// Connection operations on Windows use both except and write fd_sets.
|
||||
have_work_to_do = have_work_to_do || !op_queue_[connect_op].empty();
|
||||
op_queue_[connect_op].get_descriptors(fds[write_op], ops);
|
||||
if (fds[write_op].max_descriptor() > max_fd)
|
||||
max_fd = fds[write_op].max_descriptor();
|
||||
op_queue_[connect_op].get_descriptors(fds[except_op], ops);
|
||||
if (fds[except_op].max_descriptor() > max_fd)
|
||||
max_fd = fds[except_op].max_descriptor();
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
|
||||
// We can return immediately if there's no work to do and the reactor is
|
||||
// not supposed to block.
|
||||
if (!block && !have_work_to_do)
|
||||
return;
|
||||
|
||||
// Determine how long to block while waiting for events.
|
||||
timeval tv_buf = { 0, 0 };
|
||||
timeval* tv = block ? get_timeout(tv_buf) : &tv_buf;
|
||||
|
||||
lock.unlock();
|
||||
|
||||
// Block on the select call until descriptors become ready.
|
||||
asio::error_code ec;
|
||||
int retval = socket_ops::select(static_cast<int>(max_fd + 1),
|
||||
fds[read_op], fds[write_op], fds[except_op], tv, ec);
|
||||
|
||||
// Reset the interrupter.
|
||||
if (retval > 0 && fds[read_op].is_set(interrupter_.read_descriptor()))
|
||||
interrupter_.reset();
|
||||
|
||||
lock.lock();
|
||||
|
||||
// Dispatch all ready operations.
|
||||
if (retval > 0)
|
||||
{
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
// Connection operations on Windows use both except and write fd_sets.
|
||||
op_queue_[connect_op].perform_operations_for_descriptors(
|
||||
fds[except_op], ops);
|
||||
op_queue_[connect_op].perform_operations_for_descriptors(
|
||||
fds[write_op], ops);
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
|
||||
// Exception operations must be processed first to ensure that any
|
||||
// out-of-band data is read before normal data.
|
||||
for (int i = max_select_ops - 1; i >= 0; --i)
|
||||
op_queue_[i].perform_operations_for_descriptors(fds[i], ops);
|
||||
}
|
||||
timer_queues_.get_ready_timers(ops);
|
||||
}
|
||||
|
||||
void select_reactor::interrupt()
|
||||
{
|
||||
interrupter_.interrupt();
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
void select_reactor::run_thread()
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
while (!stop_thread_)
|
||||
{
|
||||
lock.unlock();
|
||||
op_queue<operation> ops;
|
||||
run(true, ops);
|
||||
io_service_.post_deferred_completions(ops);
|
||||
lock.lock();
|
||||
}
|
||||
}
|
||||
|
||||
void select_reactor::call_run_thread(select_reactor* reactor)
|
||||
{
|
||||
reactor->run_thread();
|
||||
}
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
void select_reactor::do_add_timer_queue(timer_queue_base& queue)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
timer_queues_.insert(&queue);
|
||||
}
|
||||
|
||||
void select_reactor::do_remove_timer_queue(timer_queue_base& queue)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
timer_queues_.erase(&queue);
|
||||
}
|
||||
|
||||
timeval* select_reactor::get_timeout(timeval& tv)
|
||||
{
|
||||
// By default we will wait no longer than 5 minutes. This will ensure that
|
||||
// any changes to the system clock are detected after no longer than this.
|
||||
long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
|
||||
tv.tv_sec = usec / 1000000;
|
||||
tv.tv_usec = usec % 1000000;
|
||||
return &tv;
|
||||
}
|
||||
|
||||
void select_reactor::cancel_ops_unlocked(socket_type descriptor,
|
||||
const asio::error_code& ec)
|
||||
{
|
||||
bool need_interrupt = false;
|
||||
op_queue<operation> ops;
|
||||
for (int i = 0; i < max_ops; ++i)
|
||||
need_interrupt = op_queue_[i].cancel_operations(
|
||||
descriptor, ops, ec) || need_interrupt;
|
||||
io_service_.post_deferred_completions(ops);
|
||||
if (need_interrupt)
|
||||
interrupter_.interrupt();
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
// || (!defined(ASIO_HAS_DEV_POLL)
|
||||
// && !defined(ASIO_HAS_EPOLL)
|
||||
// && !defined(ASIO_HAS_KQUEUE))
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_SELECT_REACTOR_IPP
|
70
ext/asio/asio/detail/impl/service_registry.hpp
Normal file
70
ext/asio/asio/detail/impl/service_registry.hpp
Normal file
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// detail/impl/service_registry.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_SERVICE_REGISTRY_HPP
|
||||
#define ASIO_DETAIL_IMPL_SERVICE_REGISTRY_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Service>
|
||||
Service& service_registry::use_service()
|
||||
{
|
||||
asio::io_service::service::key key;
|
||||
init_key(key, Service::id);
|
||||
factory_type factory = &service_registry::create<Service>;
|
||||
return *static_cast<Service*>(do_use_service(key, factory));
|
||||
}
|
||||
|
||||
template <typename Service>
|
||||
void service_registry::add_service(Service* new_service)
|
||||
{
|
||||
asio::io_service::service::key key;
|
||||
init_key(key, Service::id);
|
||||
return do_add_service(key, new_service);
|
||||
}
|
||||
|
||||
template <typename Service>
|
||||
bool service_registry::has_service() const
|
||||
{
|
||||
asio::io_service::service::key key;
|
||||
init_key(key, Service::id);
|
||||
return do_has_service(key);
|
||||
}
|
||||
|
||||
#if !defined(ASIO_NO_TYPEID)
|
||||
template <typename Service>
|
||||
void service_registry::init_key(asio::io_service::service::key& key,
|
||||
const asio::detail::service_id<Service>& /*id*/)
|
||||
{
|
||||
key.type_info_ = &typeid(typeid_wrapper<Service>);
|
||||
key.id_ = 0;
|
||||
}
|
||||
#endif // !defined(ASIO_NO_TYPEID)
|
||||
|
||||
template <typename Service>
|
||||
asio::io_service::service* service_registry::create(
|
||||
asio::io_service& owner)
|
||||
{
|
||||
return new Service(owner);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_SERVICE_REGISTRY_HPP
|
164
ext/asio/asio/detail/impl/service_registry.ipp
Normal file
164
ext/asio/asio/detail/impl/service_registry.ipp
Normal file
@@ -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
|
2917
ext/asio/asio/detail/impl/socket_ops.ipp
Normal file
2917
ext/asio/asio/detail/impl/socket_ops.ipp
Normal file
File diff suppressed because it is too large
Load Diff
151
ext/asio/asio/detail/impl/socket_select_interrupter.ipp
Normal file
151
ext/asio/asio/detail/impl/socket_select_interrupter.ipp
Normal file
@@ -0,0 +1,151 @@
|
||||
//
|
||||
// detail/impl/socket_select_interrupter.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_SOCKET_SELECT_INTERRUPTER_IPP
|
||||
#define ASIO_DETAIL_IMPL_SOCKET_SELECT_INTERRUPTER_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(BOOST_WINDOWS) \
|
||||
|| defined(__CYGWIN__) \
|
||||
|| defined(__SYMBIAN32__)
|
||||
|
||||
#include <cstdlib>
|
||||
#include "asio/detail/socket_holder.hpp"
|
||||
#include "asio/detail/socket_ops.hpp"
|
||||
#include "asio/detail/socket_select_interrupter.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/error.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
socket_select_interrupter::socket_select_interrupter()
|
||||
{
|
||||
asio::error_code ec;
|
||||
socket_holder acceptor(socket_ops::socket(
|
||||
AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));
|
||||
if (acceptor.get() == invalid_socket)
|
||||
asio::detail::throw_error(ec, "socket_select_interrupter");
|
||||
|
||||
int opt = 1;
|
||||
socket_ops::state_type acceptor_state = 0;
|
||||
socket_ops::setsockopt(acceptor.get(), acceptor_state,
|
||||
SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt), ec);
|
||||
|
||||
using namespace std; // For memset.
|
||||
sockaddr_in4_type addr;
|
||||
std::size_t addr_len = sizeof(addr);
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
addr.sin_port = 0;
|
||||
if (socket_ops::bind(acceptor.get(), (const socket_addr_type*)&addr,
|
||||
addr_len, ec) == socket_error_retval)
|
||||
asio::detail::throw_error(ec, "socket_select_interrupter");
|
||||
|
||||
if (socket_ops::getsockname(acceptor.get(), (socket_addr_type*)&addr,
|
||||
&addr_len, ec) == socket_error_retval)
|
||||
asio::detail::throw_error(ec, "socket_select_interrupter");
|
||||
|
||||
// Some broken firewalls on Windows will intermittently cause getsockname to
|
||||
// return 0.0.0.0 when the socket is actually bound to 127.0.0.1. We
|
||||
// explicitly specify the target address here to work around this problem.
|
||||
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
||||
if (socket_ops::listen(acceptor.get(),
|
||||
SOMAXCONN, ec) == socket_error_retval)
|
||||
asio::detail::throw_error(ec, "socket_select_interrupter");
|
||||
|
||||
socket_holder client(socket_ops::socket(
|
||||
AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));
|
||||
if (client.get() == invalid_socket)
|
||||
asio::detail::throw_error(ec, "socket_select_interrupter");
|
||||
|
||||
if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr,
|
||||
addr_len, ec) == socket_error_retval)
|
||||
asio::detail::throw_error(ec, "socket_select_interrupter");
|
||||
|
||||
socket_holder server(socket_ops::accept(acceptor.get(), 0, 0, ec));
|
||||
if (server.get() == invalid_socket)
|
||||
asio::detail::throw_error(ec, "socket_select_interrupter");
|
||||
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
socket_ops::state_type client_state = 0;
|
||||
if (socket_ops::ioctl(client.get(), client_state,
|
||||
FIONBIO, &non_blocking, ec))
|
||||
asio::detail::throw_error(ec, "socket_select_interrupter");
|
||||
|
||||
opt = 1;
|
||||
socket_ops::setsockopt(client.get(), client_state,
|
||||
IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
|
||||
|
||||
non_blocking = 1;
|
||||
socket_ops::state_type server_state = 0;
|
||||
if (socket_ops::ioctl(server.get(), server_state,
|
||||
FIONBIO, &non_blocking, ec))
|
||||
asio::detail::throw_error(ec, "socket_select_interrupter");
|
||||
|
||||
opt = 1;
|
||||
socket_ops::setsockopt(server.get(), server_state,
|
||||
IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
|
||||
|
||||
read_descriptor_ = server.release();
|
||||
write_descriptor_ = client.release();
|
||||
}
|
||||
|
||||
socket_select_interrupter::~socket_select_interrupter()
|
||||
{
|
||||
asio::error_code ec;
|
||||
socket_ops::state_type state = socket_ops::internal_non_blocking;
|
||||
if (read_descriptor_ != invalid_socket)
|
||||
socket_ops::close(read_descriptor_, state, true, ec);
|
||||
if (write_descriptor_ != invalid_socket)
|
||||
socket_ops::close(write_descriptor_, state, true, ec);
|
||||
}
|
||||
|
||||
void socket_select_interrupter::interrupt()
|
||||
{
|
||||
char byte = 0;
|
||||
socket_ops::buf b;
|
||||
socket_ops::init_buf(b, &byte, 1);
|
||||
asio::error_code ec;
|
||||
socket_ops::send(write_descriptor_, &b, 1, 0, ec);
|
||||
}
|
||||
|
||||
bool socket_select_interrupter::reset()
|
||||
{
|
||||
char data[1024];
|
||||
socket_ops::buf b;
|
||||
socket_ops::init_buf(b, data, sizeof(data));
|
||||
asio::error_code ec;
|
||||
int bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
|
||||
bool was_interrupted = (bytes_read > 0);
|
||||
while (bytes_read == sizeof(data))
|
||||
bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);
|
||||
return was_interrupted;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(BOOST_WINDOWS)
|
||||
// || defined(__CYGWIN__)
|
||||
// || defined(__SYMBIAN32__)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_SOCKET_SELECT_INTERRUPTER_IPP
|
140
ext/asio/asio/detail/impl/strand_service.hpp
Normal file
140
ext/asio/asio/detail/impl/strand_service.hpp
Normal file
@@ -0,0 +1,140 @@
|
||||
//
|
||||
// detail/impl/strand_service.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_STRAND_SERVICE_HPP
|
||||
#define ASIO_DETAIL_IMPL_STRAND_SERVICE_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/call_stack.hpp"
|
||||
#include "asio/detail/completion_handler.hpp"
|
||||
#include "asio/detail/fenced_block.hpp"
|
||||
#include "asio/detail/handler_alloc_helpers.hpp"
|
||||
#include "asio/detail/handler_invoke_helpers.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
inline strand_service::strand_impl::strand_impl()
|
||||
: operation(&strand_service::do_complete),
|
||||
count_(0)
|
||||
{
|
||||
}
|
||||
|
||||
struct strand_service::on_dispatch_exit
|
||||
{
|
||||
io_service_impl* io_service_;
|
||||
strand_impl* impl_;
|
||||
|
||||
~on_dispatch_exit()
|
||||
{
|
||||
impl_->mutex_.lock();
|
||||
bool more_handlers = (--impl_->count_ > 0);
|
||||
impl_->mutex_.unlock();
|
||||
|
||||
if (more_handlers)
|
||||
io_service_->post_immediate_completion(impl_);
|
||||
}
|
||||
};
|
||||
|
||||
inline void strand_service::destroy(strand_service::implementation_type& impl)
|
||||
{
|
||||
impl = 0;
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
void strand_service::dispatch(strand_service::implementation_type& impl,
|
||||
Handler handler)
|
||||
{
|
||||
// If we are already in the strand then the handler can run immediately.
|
||||
if (call_stack<strand_impl>::contains(impl))
|
||||
{
|
||||
asio::detail::fenced_block b;
|
||||
asio_handler_invoke_helpers::invoke(handler, handler);
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef completion_handler<Handler> op;
|
||||
typename op::ptr p = { boost::addressof(handler),
|
||||
asio_handler_alloc_helpers::allocate(
|
||||
sizeof(op), handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
|
||||
// If we are running inside the io_service, and no other handler is queued
|
||||
// or running, then the handler can run immediately.
|
||||
bool can_dispatch = call_stack<io_service_impl>::contains(&io_service_);
|
||||
impl->mutex_.lock();
|
||||
bool first = (++impl->count_ == 1);
|
||||
if (can_dispatch && first)
|
||||
{
|
||||
// Immediate invocation is allowed.
|
||||
impl->mutex_.unlock();
|
||||
|
||||
// Memory must be releaesed before any upcall is made.
|
||||
p.reset();
|
||||
|
||||
// Indicate that this strand is executing on the current thread.
|
||||
call_stack<strand_impl>::context ctx(impl);
|
||||
|
||||
// Ensure the next handler, if any, is scheduled on block exit.
|
||||
on_dispatch_exit on_exit = { &io_service_, impl };
|
||||
(void)on_exit;
|
||||
|
||||
asio::detail::fenced_block b;
|
||||
asio_handler_invoke_helpers::invoke(handler, handler);
|
||||
return;
|
||||
}
|
||||
|
||||
// Immediate invocation is not allowed, so enqueue for later.
|
||||
impl->queue_.push(p.p);
|
||||
impl->mutex_.unlock();
|
||||
p.v = p.p = 0;
|
||||
|
||||
// The first handler to be enqueued is responsible for scheduling the
|
||||
// strand.
|
||||
if (first)
|
||||
io_service_.post_immediate_completion(impl);
|
||||
}
|
||||
|
||||
// Request the io_service to invoke the given handler and return immediately.
|
||||
template <typename Handler>
|
||||
void strand_service::post(strand_service::implementation_type& impl,
|
||||
Handler handler)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef completion_handler<Handler> op;
|
||||
typename op::ptr p = { boost::addressof(handler),
|
||||
asio_handler_alloc_helpers::allocate(
|
||||
sizeof(op), handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
|
||||
// Add the handler to the queue.
|
||||
impl->mutex_.lock();
|
||||
bool first = (++impl->count_ == 1);
|
||||
impl->queue_.push(p.p);
|
||||
impl->mutex_.unlock();
|
||||
p.v = p.p = 0;
|
||||
|
||||
// The first handler to be enqueue is responsible for scheduling the strand.
|
||||
if (first)
|
||||
io_service_.post_immediate_completion(impl);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_STRAND_SERVICE_HPP
|
106
ext/asio/asio/detail/impl/strand_service.ipp
Normal file
106
ext/asio/asio/detail/impl/strand_service.ipp
Normal file
@@ -0,0 +1,106 @@
|
||||
//
|
||||
// detail/impl/strand_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_STRAND_SERVICE_IPP
|
||||
#define ASIO_DETAIL_IMPL_STRAND_SERVICE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "asio/detail/call_stack.hpp"
|
||||
#include "asio/detail/strand_service.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
struct strand_service::on_do_complete_exit
|
||||
{
|
||||
io_service_impl* owner_;
|
||||
strand_impl* impl_;
|
||||
|
||||
~on_do_complete_exit()
|
||||
{
|
||||
impl_->mutex_.lock();
|
||||
bool more_handlers = (--impl_->count_ > 0);
|
||||
impl_->mutex_.unlock();
|
||||
|
||||
if (more_handlers)
|
||||
owner_->post_immediate_completion(impl_);
|
||||
}
|
||||
};
|
||||
|
||||
strand_service::strand_service(asio::io_service& io_service)
|
||||
: asio::detail::service_base<strand_service>(io_service),
|
||||
io_service_(asio::use_service<io_service_impl>(io_service)),
|
||||
mutex_(),
|
||||
salt_(0)
|
||||
{
|
||||
}
|
||||
|
||||
void strand_service::shutdown_service()
|
||||
{
|
||||
op_queue<operation> ops;
|
||||
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
for (std::size_t i = 0; i < num_implementations; ++i)
|
||||
if (strand_impl* impl = implementations_[i].get())
|
||||
ops.push(impl->queue_);
|
||||
}
|
||||
|
||||
void strand_service::construct(strand_service::implementation_type& impl)
|
||||
{
|
||||
std::size_t salt = salt_++;
|
||||
std::size_t index = reinterpret_cast<std::size_t>(&impl);
|
||||
index += (reinterpret_cast<std::size_t>(&impl) >> 3);
|
||||
index ^= salt + 0x9e3779b9 + (index << 6) + (index >> 2);
|
||||
index = index % num_implementations;
|
||||
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
|
||||
if (!implementations_[index])
|
||||
implementations_[index].reset(new strand_impl);
|
||||
impl = implementations_[index].get();
|
||||
}
|
||||
|
||||
void strand_service::do_complete(io_service_impl* owner, operation* base,
|
||||
asio::error_code /*ec*/, std::size_t /*bytes_transferred*/)
|
||||
{
|
||||
if (owner)
|
||||
{
|
||||
strand_impl* impl = static_cast<strand_impl*>(base);
|
||||
|
||||
// Get the next handler to be executed.
|
||||
impl->mutex_.lock();
|
||||
operation* o = impl->queue_.front();
|
||||
impl->queue_.pop();
|
||||
impl->mutex_.unlock();
|
||||
|
||||
// Indicate that this strand is executing on the current thread.
|
||||
call_stack<strand_impl>::context ctx(impl);
|
||||
|
||||
// Ensure the next handler, if any, is scheduled on block exit.
|
||||
on_do_complete_exit on_exit = { owner, impl };
|
||||
(void)on_exit;
|
||||
|
||||
o->complete(*owner);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_STRAND_SERVICE_IPP
|
60
ext/asio/asio/detail/impl/task_io_service.hpp
Normal file
60
ext/asio/asio/detail/impl/task_io_service.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// detail/impl/task_io_service.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_TASK_IO_SERVICE_HPP
|
||||
#define ASIO_DETAIL_IMPL_TASK_IO_SERVICE_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/call_stack.hpp"
|
||||
#include "asio/detail/completion_handler.hpp"
|
||||
#include "asio/detail/fenced_block.hpp"
|
||||
#include "asio/detail/handler_alloc_helpers.hpp"
|
||||
#include "asio/detail/handler_invoke_helpers.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Handler>
|
||||
void task_io_service::dispatch(Handler handler)
|
||||
{
|
||||
if (call_stack<task_io_service>::contains(this))
|
||||
{
|
||||
asio::detail::fenced_block b;
|
||||
asio_handler_invoke_helpers::invoke(handler, handler);
|
||||
}
|
||||
else
|
||||
post(handler);
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
void task_io_service::post(Handler handler)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef completion_handler<Handler> op;
|
||||
typename op::ptr p = { boost::addressof(handler),
|
||||
asio_handler_alloc_helpers::allocate(
|
||||
sizeof(op), handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
|
||||
post_immediate_completion(p.p);
|
||||
p.v = p.p = 0;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_TASK_IO_SERVICE_HPP
|
354
ext/asio/asio/detail/impl/task_io_service.ipp
Normal file
354
ext/asio/asio/detail/impl/task_io_service.ipp
Normal file
@@ -0,0 +1,354 @@
|
||||
//
|
||||
// detail/impl/task_io_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_TASK_IO_SERVICE_IPP
|
||||
#define ASIO_DETAIL_IMPL_TASK_IO_SERVICE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if !defined(ASIO_HAS_IOCP)
|
||||
|
||||
#include <boost/limits.hpp>
|
||||
#include "asio/detail/call_stack.hpp"
|
||||
#include "asio/detail/event.hpp"
|
||||
#include "asio/detail/reactor.hpp"
|
||||
#include "asio/detail/task_io_service.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
struct task_io_service::task_cleanup
|
||||
{
|
||||
~task_cleanup()
|
||||
{
|
||||
// Enqueue the completed operations and reinsert the task at the end of
|
||||
// the operation queue.
|
||||
lock_->lock();
|
||||
task_io_service_->task_interrupted_ = true;
|
||||
task_io_service_->op_queue_.push(*ops_);
|
||||
task_io_service_->op_queue_.push(&task_io_service_->task_operation_);
|
||||
}
|
||||
|
||||
task_io_service* task_io_service_;
|
||||
mutex::scoped_lock* lock_;
|
||||
op_queue<operation>* ops_;
|
||||
};
|
||||
|
||||
struct task_io_service::work_finished_on_block_exit
|
||||
{
|
||||
~work_finished_on_block_exit()
|
||||
{
|
||||
task_io_service_->work_finished();
|
||||
}
|
||||
|
||||
task_io_service* task_io_service_;
|
||||
};
|
||||
|
||||
struct task_io_service::idle_thread_info
|
||||
{
|
||||
event wakeup_event;
|
||||
idle_thread_info* next;
|
||||
};
|
||||
|
||||
task_io_service::task_io_service(asio::io_service& io_service)
|
||||
: asio::detail::service_base<task_io_service>(io_service),
|
||||
mutex_(),
|
||||
task_(0),
|
||||
task_interrupted_(true),
|
||||
outstanding_work_(0),
|
||||
stopped_(false),
|
||||
shutdown_(false),
|
||||
first_idle_thread_(0)
|
||||
{
|
||||
}
|
||||
|
||||
void task_io_service::init(std::size_t /*concurrency_hint*/)
|
||||
{
|
||||
}
|
||||
|
||||
void task_io_service::shutdown_service()
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
shutdown_ = true;
|
||||
lock.unlock();
|
||||
|
||||
// Destroy handler objects.
|
||||
while (!op_queue_.empty())
|
||||
{
|
||||
operation* o = op_queue_.front();
|
||||
op_queue_.pop();
|
||||
if (o != &task_operation_)
|
||||
o->destroy();
|
||||
}
|
||||
|
||||
// Reset to initial state.
|
||||
task_ = 0;
|
||||
}
|
||||
|
||||
void task_io_service::init_task()
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
if (!shutdown_ && !task_)
|
||||
{
|
||||
task_ = &use_service<reactor>(this->get_io_service());
|
||||
op_queue_.push(&task_operation_);
|
||||
wake_one_thread_and_unlock(lock);
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t task_io_service::run(asio::error_code& ec)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
if (outstanding_work_ == 0)
|
||||
{
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
call_stack<task_io_service>::context ctx(this);
|
||||
|
||||
idle_thread_info this_idle_thread;
|
||||
this_idle_thread.next = 0;
|
||||
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
|
||||
std::size_t n = 0;
|
||||
for (; do_one(lock, &this_idle_thread); lock.lock())
|
||||
if (n != (std::numeric_limits<std::size_t>::max)())
|
||||
++n;
|
||||
return n;
|
||||
}
|
||||
|
||||
std::size_t task_io_service::run_one(asio::error_code& ec)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
if (outstanding_work_ == 0)
|
||||
{
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
call_stack<task_io_service>::context ctx(this);
|
||||
|
||||
idle_thread_info this_idle_thread;
|
||||
this_idle_thread.next = 0;
|
||||
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
|
||||
return do_one(lock, &this_idle_thread);
|
||||
}
|
||||
|
||||
std::size_t task_io_service::poll(asio::error_code& ec)
|
||||
{
|
||||
if (outstanding_work_ == 0)
|
||||
{
|
||||
stop();
|
||||
ec = asio::error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
call_stack<task_io_service>::context ctx(this);
|
||||
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
|
||||
std::size_t n = 0;
|
||||
for (; do_one(lock, 0); lock.lock())
|
||||
if (n != (std::numeric_limits<std::size_t>::max)())
|
||||
++n;
|
||||
return n;
|
||||
}
|
||||
|
||||
std::size_t task_io_service::poll_one(asio::error_code& ec)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
if (outstanding_work_ == 0)
|
||||
{
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
call_stack<task_io_service>::context ctx(this);
|
||||
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
|
||||
return do_one(lock, 0);
|
||||
}
|
||||
|
||||
void task_io_service::stop()
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
stop_all_threads(lock);
|
||||
}
|
||||
|
||||
void task_io_service::reset()
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
stopped_ = false;
|
||||
}
|
||||
|
||||
void task_io_service::post_immediate_completion(task_io_service::operation* op)
|
||||
{
|
||||
work_started();
|
||||
post_deferred_completion(op);
|
||||
}
|
||||
|
||||
void task_io_service::post_deferred_completion(task_io_service::operation* op)
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
op_queue_.push(op);
|
||||
wake_one_thread_and_unlock(lock);
|
||||
}
|
||||
|
||||
void task_io_service::post_deferred_completions(
|
||||
op_queue<task_io_service::operation>& ops)
|
||||
{
|
||||
if (!ops.empty())
|
||||
{
|
||||
mutex::scoped_lock lock(mutex_);
|
||||
op_queue_.push(ops);
|
||||
wake_one_thread_and_unlock(lock);
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t task_io_service::do_one(mutex::scoped_lock& lock,
|
||||
task_io_service::idle_thread_info* this_idle_thread)
|
||||
{
|
||||
bool polling = !this_idle_thread;
|
||||
bool task_has_run = false;
|
||||
while (!stopped_)
|
||||
{
|
||||
if (!op_queue_.empty())
|
||||
{
|
||||
// Prepare to execute first handler from queue.
|
||||
operation* o = op_queue_.front();
|
||||
op_queue_.pop();
|
||||
bool more_handlers = (!op_queue_.empty());
|
||||
|
||||
if (o == &task_operation_)
|
||||
{
|
||||
task_interrupted_ = more_handlers || polling;
|
||||
|
||||
// If the task has already run and we're polling then we're done.
|
||||
if (task_has_run && polling)
|
||||
{
|
||||
task_interrupted_ = true;
|
||||
op_queue_.push(&task_operation_);
|
||||
return 0;
|
||||
}
|
||||
task_has_run = true;
|
||||
|
||||
if (!more_handlers || !wake_one_idle_thread_and_unlock(lock))
|
||||
lock.unlock();
|
||||
|
||||
op_queue<operation> completed_ops;
|
||||
task_cleanup c = { this, &lock, &completed_ops };
|
||||
(void)c;
|
||||
|
||||
// Run the task. May throw an exception. Only block if the operation
|
||||
// queue is empty and we're not polling, otherwise we want to return
|
||||
// as soon as possible.
|
||||
task_->run(!more_handlers && !polling, completed_ops);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (more_handlers)
|
||||
wake_one_thread_and_unlock(lock);
|
||||
else
|
||||
lock.unlock();
|
||||
|
||||
// Ensure the count of outstanding work is decremented on block exit.
|
||||
work_finished_on_block_exit on_exit = { this };
|
||||
(void)on_exit;
|
||||
|
||||
// Complete the operation. May throw an exception.
|
||||
o->complete(*this); // deletes the operation object
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (this_idle_thread)
|
||||
{
|
||||
// Nothing to run right now, so just wait for work to do.
|
||||
this_idle_thread->next = first_idle_thread_;
|
||||
first_idle_thread_ = this_idle_thread;
|
||||
this_idle_thread->wakeup_event.clear(lock);
|
||||
this_idle_thread->wakeup_event.wait(lock);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void task_io_service::stop_all_threads(
|
||||
mutex::scoped_lock& lock)
|
||||
{
|
||||
stopped_ = true;
|
||||
|
||||
while (first_idle_thread_)
|
||||
{
|
||||
idle_thread_info* idle_thread = first_idle_thread_;
|
||||
first_idle_thread_ = idle_thread->next;
|
||||
idle_thread->next = 0;
|
||||
idle_thread->wakeup_event.signal(lock);
|
||||
}
|
||||
|
||||
if (!task_interrupted_ && task_)
|
||||
{
|
||||
task_interrupted_ = true;
|
||||
task_->interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
bool task_io_service::wake_one_idle_thread_and_unlock(
|
||||
mutex::scoped_lock& lock)
|
||||
{
|
||||
if (first_idle_thread_)
|
||||
{
|
||||
idle_thread_info* idle_thread = first_idle_thread_;
|
||||
first_idle_thread_ = idle_thread->next;
|
||||
idle_thread->next = 0;
|
||||
idle_thread->wakeup_event.signal_and_unlock(lock);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void task_io_service::wake_one_thread_and_unlock(
|
||||
mutex::scoped_lock& lock)
|
||||
{
|
||||
if (!wake_one_idle_thread_and_unlock(lock))
|
||||
{
|
||||
if (!task_interrupted_ && task_)
|
||||
{
|
||||
task_interrupted_ = true;
|
||||
task_->interrupt();
|
||||
}
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // !defined(ASIO_HAS_IOCP)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_TASK_IO_SERVICE_IPP
|
47
ext/asio/asio/detail/impl/throw_error.ipp
Normal file
47
ext/asio/asio/detail/impl/throw_error.ipp
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// detail/impl/throw_error.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_THROW_ERROR_IPP
|
||||
#define ASIO_DETAIL_IMPL_THROW_ERROR_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/system_error.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
ASIO_DECL
|
||||
void do_throw_error(const asio::error_code& err)
|
||||
{
|
||||
asio::system_error e(err);
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
||||
ASIO_DECL
|
||||
void do_throw_error(const asio::error_code& err, const char* location)
|
||||
{
|
||||
asio::system_error e(err, location);
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_THROW_ERROR_IPP
|
85
ext/asio/asio/detail/impl/timer_queue.ipp
Normal file
85
ext/asio/asio/detail/impl/timer_queue.ipp
Normal file
@@ -0,0 +1,85 @@
|
||||
//
|
||||
// detail/impl/timer_queue.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_TIMER_QUEUE_IPP
|
||||
#define ASIO_DETAIL_IMPL_TIMER_QUEUE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if !defined(ASIO_HEADER_ONLY)
|
||||
|
||||
#include "asio/detail/timer_queue.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
timer_queue<time_traits<boost::posix_time::ptime> >::timer_queue()
|
||||
{
|
||||
}
|
||||
|
||||
timer_queue<time_traits<boost::posix_time::ptime> >::~timer_queue()
|
||||
{
|
||||
}
|
||||
|
||||
bool timer_queue<time_traits<boost::posix_time::ptime> >::enqueue_timer(
|
||||
const time_type& time, per_timer_data& timer, timer_op* op)
|
||||
{
|
||||
return impl_.enqueue_timer(time, timer, op);
|
||||
}
|
||||
|
||||
bool timer_queue<time_traits<boost::posix_time::ptime> >::empty() const
|
||||
{
|
||||
return impl_.empty();
|
||||
}
|
||||
|
||||
long timer_queue<time_traits<boost::posix_time::ptime> >::wait_duration_msec(
|
||||
long max_duration) const
|
||||
{
|
||||
return impl_.wait_duration_msec(max_duration);
|
||||
}
|
||||
|
||||
long timer_queue<time_traits<boost::posix_time::ptime> >::wait_duration_usec(
|
||||
long max_duration) const
|
||||
{
|
||||
return impl_.wait_duration_usec(max_duration);
|
||||
}
|
||||
|
||||
void timer_queue<time_traits<boost::posix_time::ptime> >::get_ready_timers(
|
||||
op_queue<operation>& ops)
|
||||
{
|
||||
impl_.get_ready_timers(ops);
|
||||
}
|
||||
|
||||
void timer_queue<time_traits<boost::posix_time::ptime> >::get_all_timers(
|
||||
op_queue<operation>& ops)
|
||||
{
|
||||
impl_.get_all_timers(ops);
|
||||
}
|
||||
|
||||
std::size_t timer_queue<time_traits<boost::posix_time::ptime> >::cancel_timer(
|
||||
per_timer_data& timer, op_queue<operation>& ops)
|
||||
{
|
||||
return impl_.cancel_timer(timer, ops);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // !defined(ASIO_HEADER_ONLY)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_TIMER_QUEUE_IPP
|
101
ext/asio/asio/detail/impl/timer_queue_set.ipp
Normal file
101
ext/asio/asio/detail/impl/timer_queue_set.ipp
Normal file
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// detail/impl/timer_queue_set.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_TIMER_QUEUE_SET_IPP
|
||||
#define ASIO_DETAIL_IMPL_TIMER_QUEUE_SET_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "asio/detail/timer_queue_set.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
timer_queue_set::timer_queue_set()
|
||||
: first_(0)
|
||||
{
|
||||
}
|
||||
|
||||
void timer_queue_set::insert(timer_queue_base* q)
|
||||
{
|
||||
q->next_ = first_;
|
||||
first_ = q;
|
||||
}
|
||||
|
||||
void timer_queue_set::erase(timer_queue_base* q)
|
||||
{
|
||||
if (first_)
|
||||
{
|
||||
if (q == first_)
|
||||
{
|
||||
first_ = q->next_;
|
||||
q->next_ = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
for (timer_queue_base* p = first_; p->next_; p = p->next_)
|
||||
{
|
||||
if (p->next_ == q)
|
||||
{
|
||||
p->next_ = q->next_;
|
||||
q->next_ = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool timer_queue_set::all_empty() const
|
||||
{
|
||||
for (timer_queue_base* p = first_; p; p = p->next_)
|
||||
if (!p->empty())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
long timer_queue_set::wait_duration_msec(long max_duration) const
|
||||
{
|
||||
long min_duration = max_duration;
|
||||
for (timer_queue_base* p = first_; p; p = p->next_)
|
||||
min_duration = p->wait_duration_msec(min_duration);
|
||||
return min_duration;
|
||||
}
|
||||
|
||||
long timer_queue_set::wait_duration_usec(long max_duration) const
|
||||
{
|
||||
long min_duration = max_duration;
|
||||
for (timer_queue_base* p = first_; p; p = p->next_)
|
||||
min_duration = p->wait_duration_usec(min_duration);
|
||||
return min_duration;
|
||||
}
|
||||
|
||||
void timer_queue_set::get_ready_timers(op_queue<operation>& ops)
|
||||
{
|
||||
for (timer_queue_base* p = first_; p; p = p->next_)
|
||||
p->get_ready_timers(ops);
|
||||
}
|
||||
|
||||
void timer_queue_set::get_all_timers(op_queue<operation>& ops)
|
||||
{
|
||||
for (timer_queue_base* p = first_; p; p = p->next_)
|
||||
p->get_all_timers(ops);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_TIMER_QUEUE_SET_IPP
|
50
ext/asio/asio/detail/impl/win_event.ipp
Normal file
50
ext/asio/asio/detail/impl/win_event.ipp
Normal file
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// detail/win_event.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_WIN_EVENT_IPP
|
||||
#define ASIO_DETAIL_IMPL_WIN_EVENT_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(BOOST_WINDOWS)
|
||||
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/detail/win_event.hpp"
|
||||
#include "asio/error.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
win_event::win_event()
|
||||
: event_(::CreateEvent(0, true, false, 0))
|
||||
{
|
||||
if (!event_)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
asio::error_code ec(last_error,
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "event");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(BOOST_WINDOWS)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_WIN_EVENT_IPP
|
452
ext/asio/asio/detail/impl/win_iocp_handle_service.ipp
Normal file
452
ext/asio/asio/detail/impl/win_iocp_handle_service.ipp
Normal file
@@ -0,0 +1,452 @@
|
||||
//
|
||||
// detail/impl/win_iocp_handle_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_HANDLE_SERVICE_IPP
|
||||
#define ASIO_DETAIL_IMPL_WIN_IOCP_HANDLE_SERVICE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
|
||||
#include "asio/detail/win_iocp_handle_service.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class win_iocp_handle_service::overlapped_wrapper
|
||||
: public OVERLAPPED
|
||||
{
|
||||
public:
|
||||
explicit overlapped_wrapper(asio::error_code& ec)
|
||||
{
|
||||
Internal = 0;
|
||||
InternalHigh = 0;
|
||||
Offset = 0;
|
||||
OffsetHigh = 0;
|
||||
|
||||
// Create a non-signalled manual-reset event, for GetOverlappedResult.
|
||||
hEvent = ::CreateEvent(0, TRUE, FALSE, 0);
|
||||
if (hEvent)
|
||||
{
|
||||
// As documented in GetQueuedCompletionStatus, setting the low order
|
||||
// bit of this event prevents our synchronous writes from being treated
|
||||
// as completion port events.
|
||||
*reinterpret_cast<DWORD_PTR*>(&hEvent) |= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
}
|
||||
}
|
||||
|
||||
~overlapped_wrapper()
|
||||
{
|
||||
if (hEvent)
|
||||
{
|
||||
::CloseHandle(hEvent);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
win_iocp_handle_service::win_iocp_handle_service(
|
||||
asio::io_service& io_service)
|
||||
: iocp_service_(asio::use_service<win_iocp_io_service>(io_service)),
|
||||
mutex_(),
|
||||
impl_list_(0)
|
||||
{
|
||||
}
|
||||
|
||||
void win_iocp_handle_service::shutdown_service()
|
||||
{
|
||||
// Close all implementations, causing all operations to complete.
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
implementation_type* impl = impl_list_;
|
||||
while (impl)
|
||||
{
|
||||
close_for_destruction(*impl);
|
||||
impl = impl->next_;
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_handle_service::construct(
|
||||
win_iocp_handle_service::implementation_type& impl)
|
||||
{
|
||||
impl.handle_ = INVALID_HANDLE_VALUE;
|
||||
impl.safe_cancellation_thread_id_ = 0;
|
||||
|
||||
// Insert implementation into linked list of all implementations.
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
impl.next_ = impl_list_;
|
||||
impl.prev_ = 0;
|
||||
if (impl_list_)
|
||||
impl_list_->prev_ = &impl;
|
||||
impl_list_ = &impl;
|
||||
}
|
||||
|
||||
void win_iocp_handle_service::destroy(
|
||||
win_iocp_handle_service::implementation_type& impl)
|
||||
{
|
||||
close_for_destruction(impl);
|
||||
|
||||
// Remove implementation from linked list of all implementations.
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
if (impl_list_ == &impl)
|
||||
impl_list_ = impl.next_;
|
||||
if (impl.prev_)
|
||||
impl.prev_->next_ = impl.next_;
|
||||
if (impl.next_)
|
||||
impl.next_->prev_= impl.prev_;
|
||||
impl.next_ = 0;
|
||||
impl.prev_ = 0;
|
||||
}
|
||||
|
||||
asio::error_code win_iocp_handle_service::assign(
|
||||
win_iocp_handle_service::implementation_type& impl,
|
||||
const native_type& native_handle, asio::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = asio::error::already_open;
|
||||
return ec;
|
||||
}
|
||||
|
||||
if (iocp_service_.register_handle(native_handle, ec))
|
||||
return ec;
|
||||
|
||||
impl.handle_ = native_handle;
|
||||
ec = asio::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
asio::error_code win_iocp_handle_service::close(
|
||||
win_iocp_handle_service::implementation_type& impl,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
if (!::CloseHandle(impl.handle_))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
impl.handle_ = INVALID_HANDLE_VALUE;
|
||||
impl.safe_cancellation_thread_id_ = 0;
|
||||
}
|
||||
|
||||
ec = asio::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
asio::error_code win_iocp_handle_service::cancel(
|
||||
win_iocp_handle_service::implementation_type& impl,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
ec = asio::error::bad_descriptor;
|
||||
}
|
||||
else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
|
||||
::GetModuleHandleA("KERNEL32"), "CancelIoEx"))
|
||||
{
|
||||
// The version of Windows supports cancellation from any thread.
|
||||
typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);
|
||||
cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr;
|
||||
if (!cancel_io_ex(impl.handle_, 0))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
if (last_error == ERROR_NOT_FOUND)
|
||||
{
|
||||
// ERROR_NOT_FOUND means that there were no operations to be
|
||||
// cancelled. We swallow this error to match the behaviour on other
|
||||
// platforms.
|
||||
ec = asio::error_code();
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = asio::error_code();
|
||||
}
|
||||
}
|
||||
else if (impl.safe_cancellation_thread_id_ == 0)
|
||||
{
|
||||
// No operations have been started, so there's nothing to cancel.
|
||||
ec = asio::error_code();
|
||||
}
|
||||
else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId())
|
||||
{
|
||||
// Asynchronous operations have been started from the current thread only,
|
||||
// so it is safe to try to cancel them using CancelIo.
|
||||
if (!::CancelIo(impl.handle_))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = asio::error_code();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Asynchronous operations have been started from more than one thread,
|
||||
// so cancellation is not safe.
|
||||
ec = asio::error::operation_not_supported;
|
||||
}
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
size_t win_iocp_handle_service::do_write(
|
||||
win_iocp_handle_service::implementation_type& impl, boost::uint64_t offset,
|
||||
const asio::const_buffer& buffer, asio::error_code& ec)
|
||||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
ec = asio::error::bad_descriptor;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// A request to write 0 bytes on a handle is a no-op.
|
||||
if (asio::buffer_size(buffer) == 0)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
overlapped_wrapper overlapped(ec);
|
||||
if (ec)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Write the data.
|
||||
overlapped.Offset = offset & 0xFFFFFFFF;
|
||||
overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
|
||||
BOOL ok = ::WriteFile(impl.handle_,
|
||||
asio::buffer_cast<LPCVOID>(buffer),
|
||||
static_cast<DWORD>(asio::buffer_size(buffer)), 0, &overlapped);
|
||||
if (!ok)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
if (last_error != ERROR_IO_PENDING)
|
||||
{
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for the operation to complete.
|
||||
DWORD bytes_transferred = 0;
|
||||
ok = ::GetOverlappedResult(impl.handle_,
|
||||
&overlapped, &bytes_transferred, TRUE);
|
||||
if (!ok)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
return 0;
|
||||
}
|
||||
|
||||
ec = asio::error_code();
|
||||
return bytes_transferred;
|
||||
}
|
||||
|
||||
void win_iocp_handle_service::start_write_op(
|
||||
win_iocp_handle_service::implementation_type& impl, boost::uint64_t offset,
|
||||
const asio::const_buffer& buffer, operation* op)
|
||||
{
|
||||
update_cancellation_thread_id(impl);
|
||||
iocp_service_.work_started();
|
||||
|
||||
if (!is_open(impl))
|
||||
{
|
||||
iocp_service_.on_completion(op, asio::error::bad_descriptor);
|
||||
}
|
||||
else if (asio::buffer_size(buffer) == 0)
|
||||
{
|
||||
// A request to write 0 bytes on a handle is a no-op.
|
||||
iocp_service_.on_completion(op);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD bytes_transferred = 0;
|
||||
op->Offset = offset & 0xFFFFFFFF;
|
||||
op->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
|
||||
BOOL ok = ::WriteFile(impl.handle_,
|
||||
asio::buffer_cast<LPCVOID>(buffer),
|
||||
static_cast<DWORD>(asio::buffer_size(buffer)),
|
||||
&bytes_transferred, op);
|
||||
DWORD last_error = ::GetLastError();
|
||||
if (!ok && last_error != ERROR_IO_PENDING
|
||||
&& last_error != ERROR_MORE_DATA)
|
||||
{
|
||||
iocp_service_.on_completion(op, last_error, bytes_transferred);
|
||||
}
|
||||
else
|
||||
{
|
||||
iocp_service_.on_pending(op);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t win_iocp_handle_service::do_read(
|
||||
win_iocp_handle_service::implementation_type& impl, boost::uint64_t offset,
|
||||
const asio::mutable_buffer& buffer, asio::error_code& ec)
|
||||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
ec = asio::error::bad_descriptor;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// A request to read 0 bytes on a stream handle is a no-op.
|
||||
if (asio::buffer_size(buffer) == 0)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
overlapped_wrapper overlapped(ec);
|
||||
if (ec)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read some data.
|
||||
overlapped.Offset = offset & 0xFFFFFFFF;
|
||||
overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
|
||||
BOOL ok = ::ReadFile(impl.handle_,
|
||||
asio::buffer_cast<LPVOID>(buffer),
|
||||
static_cast<DWORD>(asio::buffer_size(buffer)), 0, &overlapped);
|
||||
if (!ok)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
if (last_error != ERROR_IO_PENDING && last_error != ERROR_MORE_DATA)
|
||||
{
|
||||
if (last_error == ERROR_HANDLE_EOF)
|
||||
{
|
||||
ec = asio::error::eof;
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for the operation to complete.
|
||||
DWORD bytes_transferred = 0;
|
||||
ok = ::GetOverlappedResult(impl.handle_,
|
||||
&overlapped, &bytes_transferred, TRUE);
|
||||
if (!ok)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
if (last_error == ERROR_HANDLE_EOF)
|
||||
{
|
||||
ec = asio::error::eof;
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ec = asio::error_code();
|
||||
return bytes_transferred;
|
||||
}
|
||||
|
||||
void win_iocp_handle_service::start_read_op(
|
||||
win_iocp_handle_service::implementation_type& impl, boost::uint64_t offset,
|
||||
const asio::mutable_buffer& buffer, operation* op)
|
||||
{
|
||||
update_cancellation_thread_id(impl);
|
||||
iocp_service_.work_started();
|
||||
|
||||
if (!is_open(impl))
|
||||
{
|
||||
iocp_service_.on_completion(op, asio::error::bad_descriptor);
|
||||
}
|
||||
else if (asio::buffer_size(buffer) == 0)
|
||||
{
|
||||
// A request to read 0 bytes on a handle is a no-op.
|
||||
iocp_service_.on_completion(op);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD bytes_transferred = 0;
|
||||
op->Offset = offset & 0xFFFFFFFF;
|
||||
op->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
|
||||
BOOL ok = ::ReadFile(impl.handle_,
|
||||
asio::buffer_cast<LPVOID>(buffer),
|
||||
static_cast<DWORD>(asio::buffer_size(buffer)),
|
||||
&bytes_transferred, op);
|
||||
DWORD last_error = ::GetLastError();
|
||||
if (!ok && last_error != ERROR_IO_PENDING
|
||||
&& last_error != ERROR_MORE_DATA)
|
||||
{
|
||||
iocp_service_.on_completion(op, last_error, bytes_transferred);
|
||||
}
|
||||
else
|
||||
{
|
||||
iocp_service_.on_pending(op);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_handle_service::update_cancellation_thread_id(
|
||||
win_iocp_handle_service::implementation_type& impl)
|
||||
{
|
||||
if (impl.safe_cancellation_thread_id_ == 0)
|
||||
impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
|
||||
else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
|
||||
impl.safe_cancellation_thread_id_ = ~DWORD(0);
|
||||
}
|
||||
|
||||
void win_iocp_handle_service::close_for_destruction(implementation_type& impl)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
::CloseHandle(impl.handle_);
|
||||
impl.handle_ = INVALID_HANDLE_VALUE;
|
||||
impl.safe_cancellation_thread_id_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_WIN_IOCP_HANDLE_SERVICE_IPP
|
115
ext/asio/asio/detail/impl/win_iocp_io_service.hpp
Normal file
115
ext/asio/asio/detail/impl/win_iocp_io_service.hpp
Normal file
@@ -0,0 +1,115 @@
|
||||
//
|
||||
// detail/impl/win_iocp_io_service.hpp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_HPP
|
||||
#define ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_HPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
|
||||
#include "asio/detail/call_stack.hpp"
|
||||
#include "asio/detail/completion_handler.hpp"
|
||||
#include "asio/detail/fenced_block.hpp"
|
||||
#include "asio/detail/handler_alloc_helpers.hpp"
|
||||
#include "asio/detail/handler_invoke_helpers.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
template <typename Handler>
|
||||
void win_iocp_io_service::dispatch(Handler handler)
|
||||
{
|
||||
if (call_stack<win_iocp_io_service>::contains(this))
|
||||
{
|
||||
asio::detail::fenced_block b;
|
||||
asio_handler_invoke_helpers::invoke(handler, handler);
|
||||
}
|
||||
else
|
||||
post(handler);
|
||||
}
|
||||
|
||||
template <typename Handler>
|
||||
void win_iocp_io_service::post(Handler handler)
|
||||
{
|
||||
// Allocate and construct an operation to wrap the handler.
|
||||
typedef completion_handler<Handler> op;
|
||||
typename op::ptr p = { boost::addressof(handler),
|
||||
asio_handler_alloc_helpers::allocate(
|
||||
sizeof(op), handler), 0 };
|
||||
p.p = new (p.v) op(handler);
|
||||
|
||||
post_immediate_completion(p.p);
|
||||
p.v = p.p = 0;
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void win_iocp_io_service::add_timer_queue(
|
||||
timer_queue<Time_Traits>& queue)
|
||||
{
|
||||
do_add_timer_queue(queue);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void win_iocp_io_service::remove_timer_queue(
|
||||
timer_queue<Time_Traits>& queue)
|
||||
{
|
||||
do_remove_timer_queue(queue);
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
void win_iocp_io_service::schedule_timer(timer_queue<Time_Traits>& queue,
|
||||
const typename Time_Traits::time_type& time,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer, timer_op* op)
|
||||
{
|
||||
// If the service has been shut down we silently discard the timer.
|
||||
if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
|
||||
{
|
||||
post_immediate_completion(op);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex::scoped_lock lock(dispatch_mutex_);
|
||||
|
||||
bool earliest = queue.enqueue_timer(time, timer, op);
|
||||
work_started();
|
||||
if (earliest)
|
||||
update_timeout();
|
||||
}
|
||||
|
||||
template <typename Time_Traits>
|
||||
std::size_t win_iocp_io_service::cancel_timer(timer_queue<Time_Traits>& queue,
|
||||
typename timer_queue<Time_Traits>::per_timer_data& timer)
|
||||
{
|
||||
// If the service has been shut down we silently ignore the cancellation.
|
||||
if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
|
||||
return 0;
|
||||
|
||||
mutex::scoped_lock lock(dispatch_mutex_);
|
||||
op_queue<win_iocp_operation> ops;
|
||||
std::size_t n = queue.cancel_timer(timer, ops);
|
||||
post_deferred_completions(ops);
|
||||
return n;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_HPP
|
496
ext/asio/asio/detail/impl/win_iocp_io_service.ipp
Normal file
496
ext/asio/asio/detail/impl/win_iocp_io_service.ipp
Normal file
@@ -0,0 +1,496 @@
|
||||
//
|
||||
// detail/impl/win_iocp_io_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_IPP
|
||||
#define ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
|
||||
#include <boost/limits.hpp>
|
||||
#include "asio/error.hpp"
|
||||
#include "asio/io_service.hpp"
|
||||
#include "asio/detail/handler_alloc_helpers.hpp"
|
||||
#include "asio/detail/handler_invoke_helpers.hpp"
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/detail/win_iocp_io_service.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
struct win_iocp_io_service::work_finished_on_block_exit
|
||||
{
|
||||
~work_finished_on_block_exit()
|
||||
{
|
||||
io_service_->work_finished();
|
||||
}
|
||||
|
||||
win_iocp_io_service* io_service_;
|
||||
};
|
||||
|
||||
struct win_iocp_io_service::timer_thread_function
|
||||
{
|
||||
void operator()()
|
||||
{
|
||||
while (::InterlockedExchangeAdd(&io_service_->shutdown_, 0) == 0)
|
||||
{
|
||||
if (::WaitForSingleObject(io_service_->waitable_timer_.handle,
|
||||
INFINITE) == WAIT_OBJECT_0)
|
||||
{
|
||||
::InterlockedExchange(&io_service_->dispatch_required_, 1);
|
||||
::PostQueuedCompletionStatus(io_service_->iocp_.handle,
|
||||
0, wake_for_dispatch, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
win_iocp_io_service* io_service_;
|
||||
};
|
||||
|
||||
win_iocp_io_service::win_iocp_io_service(asio::io_service& io_service)
|
||||
: asio::detail::service_base<win_iocp_io_service>(io_service),
|
||||
iocp_(),
|
||||
outstanding_work_(0),
|
||||
stopped_(0),
|
||||
shutdown_(0),
|
||||
dispatch_required_(0)
|
||||
{
|
||||
}
|
||||
|
||||
void win_iocp_io_service::init(size_t concurrency_hint)
|
||||
{
|
||||
iocp_.handle = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0,
|
||||
static_cast<DWORD>((std::min<size_t>)(concurrency_hint, DWORD(~0))));
|
||||
if (!iocp_.handle)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
asio::error_code ec(last_error,
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "iocp");
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_io_service::shutdown_service()
|
||||
{
|
||||
::InterlockedExchange(&shutdown_, 1);
|
||||
|
||||
if (timer_thread_)
|
||||
{
|
||||
LARGE_INTEGER timeout;
|
||||
timeout.QuadPart = 1;
|
||||
::SetWaitableTimer(waitable_timer_.handle, &timeout, 1, 0, 0, FALSE);
|
||||
}
|
||||
|
||||
while (::InterlockedExchangeAdd(&outstanding_work_, 0) > 0)
|
||||
{
|
||||
op_queue<win_iocp_operation> ops;
|
||||
timer_queues_.get_all_timers(ops);
|
||||
ops.push(completed_ops_);
|
||||
if (!ops.empty())
|
||||
{
|
||||
while (win_iocp_operation* op = ops.front())
|
||||
{
|
||||
ops.pop();
|
||||
::InterlockedDecrement(&outstanding_work_);
|
||||
op->destroy();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD bytes_transferred = 0;
|
||||
dword_ptr_t completion_key = 0;
|
||||
LPOVERLAPPED overlapped = 0;
|
||||
::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
|
||||
&completion_key, &overlapped, gqcs_timeout);
|
||||
if (overlapped)
|
||||
{
|
||||
::InterlockedDecrement(&outstanding_work_);
|
||||
static_cast<win_iocp_operation*>(overlapped)->destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (timer_thread_)
|
||||
timer_thread_->join();
|
||||
}
|
||||
|
||||
asio::error_code win_iocp_io_service::register_handle(
|
||||
HANDLE handle, asio::error_code& ec)
|
||||
{
|
||||
if (::CreateIoCompletionPort(handle, iocp_.handle, 0, 0) == 0)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = asio::error_code();
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
|
||||
size_t win_iocp_io_service::run(asio::error_code& ec)
|
||||
{
|
||||
if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
|
||||
{
|
||||
stop();
|
||||
ec = asio::error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
call_stack<win_iocp_io_service>::context ctx(this);
|
||||
|
||||
size_t n = 0;
|
||||
while (do_one(true, ec))
|
||||
if (n != (std::numeric_limits<size_t>::max)())
|
||||
++n;
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t win_iocp_io_service::run_one(asio::error_code& ec)
|
||||
{
|
||||
if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
|
||||
{
|
||||
stop();
|
||||
ec = asio::error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
call_stack<win_iocp_io_service>::context ctx(this);
|
||||
|
||||
return do_one(true, ec);
|
||||
}
|
||||
|
||||
size_t win_iocp_io_service::poll(asio::error_code& ec)
|
||||
{
|
||||
if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
|
||||
{
|
||||
stop();
|
||||
ec = asio::error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
call_stack<win_iocp_io_service>::context ctx(this);
|
||||
|
||||
size_t n = 0;
|
||||
while (do_one(false, ec))
|
||||
if (n != (std::numeric_limits<size_t>::max)())
|
||||
++n;
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t win_iocp_io_service::poll_one(asio::error_code& ec)
|
||||
{
|
||||
if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
|
||||
{
|
||||
stop();
|
||||
ec = asio::error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
call_stack<win_iocp_io_service>::context ctx(this);
|
||||
|
||||
return do_one(false, ec);
|
||||
}
|
||||
|
||||
void win_iocp_io_service::stop()
|
||||
{
|
||||
if (::InterlockedExchange(&stopped_, 1) == 0)
|
||||
{
|
||||
if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
asio::error_code ec(last_error,
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "pqcs");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_io_service::post_deferred_completion(win_iocp_operation* op)
|
||||
{
|
||||
// Flag the operation as ready.
|
||||
op->ready_ = 1;
|
||||
|
||||
// Enqueue the operation on the I/O completion port.
|
||||
if (!::PostQueuedCompletionStatus(iocp_.handle,
|
||||
0, overlapped_contains_result, op))
|
||||
{
|
||||
// Out of resources. Put on completed queue instead.
|
||||
mutex::scoped_lock lock(dispatch_mutex_);
|
||||
completed_ops_.push(op);
|
||||
::InterlockedExchange(&dispatch_required_, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_io_service::post_deferred_completions(
|
||||
op_queue<win_iocp_operation>& ops)
|
||||
{
|
||||
while (win_iocp_operation* op = ops.front())
|
||||
{
|
||||
ops.pop();
|
||||
|
||||
// Flag the operation as ready.
|
||||
op->ready_ = 1;
|
||||
|
||||
// Enqueue the operation on the I/O completion port.
|
||||
if (!::PostQueuedCompletionStatus(iocp_.handle,
|
||||
0, overlapped_contains_result, op))
|
||||
{
|
||||
// Out of resources. Put on completed queue instead.
|
||||
mutex::scoped_lock lock(dispatch_mutex_);
|
||||
completed_ops_.push(op);
|
||||
completed_ops_.push(ops);
|
||||
::InterlockedExchange(&dispatch_required_, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_io_service::on_pending(win_iocp_operation* op)
|
||||
{
|
||||
if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1)
|
||||
{
|
||||
// Enqueue the operation on the I/O completion port.
|
||||
if (!::PostQueuedCompletionStatus(iocp_.handle,
|
||||
0, overlapped_contains_result, op))
|
||||
{
|
||||
// Out of resources. Put on completed queue instead.
|
||||
mutex::scoped_lock lock(dispatch_mutex_);
|
||||
completed_ops_.push(op);
|
||||
::InterlockedExchange(&dispatch_required_, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_io_service::on_completion(win_iocp_operation* op,
|
||||
DWORD last_error, DWORD bytes_transferred)
|
||||
{
|
||||
// Flag that the operation is ready for invocation.
|
||||
op->ready_ = 1;
|
||||
|
||||
// Store results in the OVERLAPPED structure.
|
||||
op->Internal = asio::error::get_system_category();
|
||||
op->Offset = last_error;
|
||||
op->OffsetHigh = bytes_transferred;
|
||||
|
||||
// Enqueue the operation on the I/O completion port.
|
||||
if (!::PostQueuedCompletionStatus(iocp_.handle,
|
||||
0, overlapped_contains_result, op))
|
||||
{
|
||||
// Out of resources. Put on completed queue instead.
|
||||
mutex::scoped_lock lock(dispatch_mutex_);
|
||||
completed_ops_.push(op);
|
||||
::InterlockedExchange(&dispatch_required_, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_io_service::on_completion(win_iocp_operation* op,
|
||||
const asio::error_code& ec, DWORD bytes_transferred)
|
||||
{
|
||||
// Flag that the operation is ready for invocation.
|
||||
op->ready_ = 1;
|
||||
|
||||
// Store results in the OVERLAPPED structure.
|
||||
op->Internal = ec.category();
|
||||
op->Offset = ec.value();
|
||||
op->OffsetHigh = bytes_transferred;
|
||||
|
||||
// Enqueue the operation on the I/O completion port.
|
||||
if (!::PostQueuedCompletionStatus(iocp_.handle,
|
||||
0, overlapped_contains_result, op))
|
||||
{
|
||||
// Out of resources. Put on completed queue instead.
|
||||
mutex::scoped_lock lock(dispatch_mutex_);
|
||||
completed_ops_.push(op);
|
||||
::InterlockedExchange(&dispatch_required_, 1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t win_iocp_io_service::do_one(bool block, asio::error_code& ec)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
// Try to acquire responsibility for dispatching timers and completed ops.
|
||||
if (::InterlockedCompareExchange(&dispatch_required_, 0, 1) == 1)
|
||||
{
|
||||
mutex::scoped_lock lock(dispatch_mutex_);
|
||||
|
||||
// Dispatch pending timers and operations.
|
||||
op_queue<win_iocp_operation> ops;
|
||||
ops.push(completed_ops_);
|
||||
timer_queues_.get_ready_timers(ops);
|
||||
post_deferred_completions(ops);
|
||||
update_timeout();
|
||||
}
|
||||
|
||||
// Get the next operation from the queue.
|
||||
DWORD bytes_transferred = 0;
|
||||
dword_ptr_t completion_key = 0;
|
||||
LPOVERLAPPED overlapped = 0;
|
||||
::SetLastError(0);
|
||||
BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
|
||||
&completion_key, &overlapped, block ? gqcs_timeout : 0);
|
||||
DWORD last_error = ::GetLastError();
|
||||
|
||||
if (overlapped)
|
||||
{
|
||||
win_iocp_operation* op = static_cast<win_iocp_operation*>(overlapped);
|
||||
asio::error_code result_ec(last_error,
|
||||
asio::error::get_system_category());
|
||||
|
||||
// We may have been passed the last_error and bytes_transferred in the
|
||||
// OVERLAPPED structure itself.
|
||||
if (completion_key == overlapped_contains_result)
|
||||
{
|
||||
result_ec = asio::error_code(static_cast<int>(op->Offset),
|
||||
static_cast<asio::error_category>(op->Internal));
|
||||
bytes_transferred = op->OffsetHigh;
|
||||
}
|
||||
|
||||
// Otherwise ensure any result has been saved into the OVERLAPPED
|
||||
// structure.
|
||||
else
|
||||
{
|
||||
op->Internal = result_ec.category();
|
||||
op->Offset = result_ec.value();
|
||||
op->OffsetHigh = bytes_transferred;
|
||||
}
|
||||
|
||||
// Dispatch the operation only if ready. The operation may not be ready
|
||||
// if the initiating function (e.g. a call to WSARecv) has not yet
|
||||
// returned. This is because the initiating function still wants access
|
||||
// to the operation's OVERLAPPED structure.
|
||||
if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1)
|
||||
{
|
||||
// Ensure the count of outstanding work is decremented on block exit.
|
||||
work_finished_on_block_exit on_exit = { this };
|
||||
(void)on_exit;
|
||||
|
||||
op->complete(*this, result_ec, bytes_transferred);
|
||||
ec = asio::error_code();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (!ok)
|
||||
{
|
||||
if (last_error != WAIT_TIMEOUT)
|
||||
{
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If we're not polling we need to keep going until we get a real handler.
|
||||
if (block)
|
||||
continue;
|
||||
|
||||
ec = asio::error_code();
|
||||
return 0;
|
||||
}
|
||||
else if (completion_key == wake_for_dispatch)
|
||||
{
|
||||
// We have been woken up to try to acquire responsibility for dispatching
|
||||
// timers and completed operations.
|
||||
}
|
||||
else
|
||||
{
|
||||
// The stopped_ flag is always checked to ensure that any leftover
|
||||
// interrupts from a previous run invocation are ignored.
|
||||
if (::InterlockedExchangeAdd(&stopped_, 0) != 0)
|
||||
{
|
||||
// Wake up next thread that is blocked on GetQueuedCompletionStatus.
|
||||
if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
|
||||
{
|
||||
last_error = ::GetLastError();
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
return 0;
|
||||
}
|
||||
|
||||
ec = asio::error_code();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_io_service::do_add_timer_queue(timer_queue_base& queue)
|
||||
{
|
||||
mutex::scoped_lock lock(dispatch_mutex_);
|
||||
|
||||
timer_queues_.insert(&queue);
|
||||
|
||||
if (!waitable_timer_.handle)
|
||||
{
|
||||
waitable_timer_.handle = ::CreateWaitableTimer(0, FALSE, 0);
|
||||
if (waitable_timer_.handle == 0)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
asio::error_code ec(last_error,
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "timer");
|
||||
}
|
||||
|
||||
LARGE_INTEGER timeout;
|
||||
timeout.QuadPart = -max_timeout_usec;
|
||||
timeout.QuadPart *= 10;
|
||||
::SetWaitableTimer(waitable_timer_.handle,
|
||||
&timeout, max_timeout_msec, 0, 0, FALSE);
|
||||
}
|
||||
|
||||
if (!timer_thread_)
|
||||
{
|
||||
timer_thread_function thread_function = { this };
|
||||
timer_thread_.reset(new thread(thread_function, 65536));
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_io_service::do_remove_timer_queue(timer_queue_base& queue)
|
||||
{
|
||||
mutex::scoped_lock lock(dispatch_mutex_);
|
||||
|
||||
timer_queues_.erase(&queue);
|
||||
}
|
||||
|
||||
void win_iocp_io_service::update_timeout()
|
||||
{
|
||||
if (timer_thread_)
|
||||
{
|
||||
// There's no point updating the waitable timer if the new timeout period
|
||||
// exceeds the maximum timeout. In that case, we might as well wait for the
|
||||
// existing period of the timer to expire.
|
||||
long timeout_usec = timer_queues_.wait_duration_usec(max_timeout_usec);
|
||||
if (timeout_usec < max_timeout_usec)
|
||||
{
|
||||
LARGE_INTEGER timeout;
|
||||
timeout.QuadPart = -timeout_usec;
|
||||
timeout.QuadPart *= 10;
|
||||
::SetWaitableTimer(waitable_timer_.handle,
|
||||
&timeout, max_timeout_msec, 0, 0, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_IPP
|
180
ext/asio/asio/detail/impl/win_iocp_serial_port_service.ipp
Normal file
180
ext/asio/asio/detail/impl/win_iocp_serial_port_service.ipp
Normal file
@@ -0,0 +1,180 @@
|
||||
//
|
||||
// detail/impl/win_iocp_serial_port_service.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_SERIAL_PORT_SERVICE_IPP
|
||||
#define ASIO_DETAIL_IMPL_WIN_IOCP_SERIAL_PORT_SERVICE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_IOCP) && defined(ASIO_HAS_SERIAL_PORT)
|
||||
|
||||
#include <cstring>
|
||||
#include "asio/detail/win_iocp_serial_port_service.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
win_iocp_serial_port_service::win_iocp_serial_port_service(
|
||||
asio::io_service& io_service)
|
||||
: handle_service_(io_service)
|
||||
{
|
||||
}
|
||||
|
||||
void win_iocp_serial_port_service::shutdown_service()
|
||||
{
|
||||
}
|
||||
|
||||
asio::error_code win_iocp_serial_port_service::open(
|
||||
win_iocp_serial_port_service::implementation_type& impl,
|
||||
const std::string& device, asio::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = asio::error::already_open;
|
||||
return ec;
|
||||
}
|
||||
|
||||
// For convenience, add a leading \\.\ sequence if not already present.
|
||||
std::string name = (device[0] == '\\') ? device : "\\\\.\\" + device;
|
||||
|
||||
// Open a handle to the serial port.
|
||||
::HANDLE handle = ::CreateFileA(name.c_str(),
|
||||
GENERIC_READ | GENERIC_WRITE, 0, 0,
|
||||
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Determine the initial serial port parameters.
|
||||
using namespace std; // For memset.
|
||||
::DCB dcb;
|
||||
memset(&dcb, 0, sizeof(DCB));
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
if (!::GetCommState(handle, &dcb))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
::CloseHandle(handle);
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Set some default serial port parameters. This implementation does not
|
||||
// support changing these, so they might as well be in a known state.
|
||||
dcb.fBinary = TRUE; // Win32 only supports binary mode.
|
||||
dcb.fDsrSensitivity = FALSE;
|
||||
dcb.fNull = FALSE; // Do not ignore NULL characters.
|
||||
dcb.fAbortOnError = FALSE; // Ignore serial framing errors.
|
||||
if (!::SetCommState(handle, &dcb))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
::CloseHandle(handle);
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Set up timeouts so that the serial port will behave similarly to a
|
||||
// network socket. Reads wait for at least one byte, then return with
|
||||
// whatever they have. Writes return once everything is out the door.
|
||||
::COMMTIMEOUTS timeouts;
|
||||
timeouts.ReadIntervalTimeout = 1;
|
||||
timeouts.ReadTotalTimeoutMultiplier = 0;
|
||||
timeouts.ReadTotalTimeoutConstant = 0;
|
||||
timeouts.WriteTotalTimeoutMultiplier = 0;
|
||||
timeouts.WriteTotalTimeoutConstant = 0;
|
||||
if (!::SetCommTimeouts(handle, &timeouts))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
::CloseHandle(handle);
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
// We're done. Take ownership of the serial port handle.
|
||||
if (handle_service_.assign(impl, handle, ec))
|
||||
::CloseHandle(handle);
|
||||
return ec;
|
||||
}
|
||||
|
||||
asio::error_code win_iocp_serial_port_service::do_set_option(
|
||||
win_iocp_serial_port_service::implementation_type& impl,
|
||||
win_iocp_serial_port_service::store_function_type store,
|
||||
const void* option, asio::error_code& ec)
|
||||
{
|
||||
using namespace std; // For memcpy.
|
||||
|
||||
::DCB dcb;
|
||||
memset(&dcb, 0, sizeof(DCB));
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
if (!::GetCommState(handle_service_.native(impl), &dcb))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
if (store(option, dcb, ec))
|
||||
return ec;
|
||||
|
||||
if (!::SetCommState(handle_service_.native(impl), &dcb))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
ec = asio::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
asio::error_code win_iocp_serial_port_service::do_get_option(
|
||||
const win_iocp_serial_port_service::implementation_type& impl,
|
||||
win_iocp_serial_port_service::load_function_type load,
|
||||
void* option, asio::error_code& ec) const
|
||||
{
|
||||
using namespace std; // For memset.
|
||||
|
||||
::DCB dcb;
|
||||
memset(&dcb, 0, sizeof(DCB));
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
if (!::GetCommState(handle_service_.native(impl), &dcb))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
return load(option, dcb, ec);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(ASIO_HAS_IOCP) && defined(ASIO_HAS_SERIAL_PORT)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_WIN_IOCP_SERIAL_PORT_SERVICE_IPP
|
575
ext/asio/asio/detail/impl/win_iocp_socket_service_base.ipp
Normal file
575
ext/asio/asio/detail/impl/win_iocp_socket_service_base.ipp
Normal file
@@ -0,0 +1,575 @@
|
||||
//
|
||||
// detail/impl/win_iocp_socket_service_base.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_SOCKET_SERVICE_BASE_IPP
|
||||
#define ASIO_DETAIL_IMPL_WIN_IOCP_SOCKET_SERVICE_BASE_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
|
||||
#include "asio/detail/win_iocp_socket_service_base.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
win_iocp_socket_service_base::win_iocp_socket_service_base(
|
||||
asio::io_service& io_service)
|
||||
: io_service_(io_service),
|
||||
iocp_service_(use_service<win_iocp_io_service>(io_service)),
|
||||
reactor_(0),
|
||||
mutex_(),
|
||||
impl_list_(0)
|
||||
{
|
||||
}
|
||||
|
||||
void win_iocp_socket_service_base::shutdown_service()
|
||||
{
|
||||
// Close all implementations, causing all operations to complete.
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
base_implementation_type* impl = impl_list_;
|
||||
while (impl)
|
||||
{
|
||||
asio::error_code ignored_ec;
|
||||
close_for_destruction(*impl);
|
||||
impl = impl->next_;
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_socket_service_base::construct(
|
||||
win_iocp_socket_service_base::base_implementation_type& impl)
|
||||
{
|
||||
impl.socket_ = invalid_socket;
|
||||
impl.state_ = 0;
|
||||
impl.cancel_token_.reset();
|
||||
#if defined(ASIO_ENABLE_CANCELIO)
|
||||
impl.safe_cancellation_thread_id_ = 0;
|
||||
#endif // defined(ASIO_ENABLE_CANCELIO)
|
||||
|
||||
// Insert implementation into linked list of all implementations.
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
impl.next_ = impl_list_;
|
||||
impl.prev_ = 0;
|
||||
if (impl_list_)
|
||||
impl_list_->prev_ = &impl;
|
||||
impl_list_ = &impl;
|
||||
}
|
||||
|
||||
void win_iocp_socket_service_base::destroy(
|
||||
win_iocp_socket_service_base::base_implementation_type& impl)
|
||||
{
|
||||
close_for_destruction(impl);
|
||||
|
||||
// Remove implementation from linked list of all implementations.
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
if (impl_list_ == &impl)
|
||||
impl_list_ = impl.next_;
|
||||
if (impl.prev_)
|
||||
impl.prev_->next_ = impl.next_;
|
||||
if (impl.next_)
|
||||
impl.next_->prev_= impl.prev_;
|
||||
impl.next_ = 0;
|
||||
impl.prev_ = 0;
|
||||
}
|
||||
|
||||
asio::error_code win_iocp_socket_service_base::close(
|
||||
win_iocp_socket_service_base::base_implementation_type& impl,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
// Check if the reactor was created, in which case we need to close the
|
||||
// socket on the reactor as well to cancel any operations that might be
|
||||
// running there.
|
||||
reactor* r = static_cast<reactor*>(
|
||||
interlocked_compare_exchange_pointer(
|
||||
reinterpret_cast<void**>(&reactor_), 0, 0));
|
||||
if (r)
|
||||
r->close_descriptor(impl.socket_, impl.reactor_data_);
|
||||
}
|
||||
|
||||
if (socket_ops::close(impl.socket_, impl.state_, false, ec) == 0)
|
||||
{
|
||||
impl.socket_ = invalid_socket;
|
||||
impl.state_ = 0;
|
||||
impl.cancel_token_.reset();
|
||||
#if defined(ASIO_ENABLE_CANCELIO)
|
||||
impl.safe_cancellation_thread_id_ = 0;
|
||||
#endif // defined(ASIO_ENABLE_CANCELIO)
|
||||
}
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
asio::error_code win_iocp_socket_service_base::cancel(
|
||||
win_iocp_socket_service_base::base_implementation_type& impl,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
if (!is_open(impl))
|
||||
{
|
||||
ec = asio::error::bad_descriptor;
|
||||
return ec;
|
||||
}
|
||||
else if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
|
||||
::GetModuleHandleA("KERNEL32"), "CancelIoEx"))
|
||||
{
|
||||
// The version of Windows supports cancellation from any thread.
|
||||
typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);
|
||||
cancel_io_ex_t cancel_io_ex = (cancel_io_ex_t)cancel_io_ex_ptr;
|
||||
socket_type sock = impl.socket_;
|
||||
HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock);
|
||||
if (!cancel_io_ex(sock_as_handle, 0))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
if (last_error == ERROR_NOT_FOUND)
|
||||
{
|
||||
// ERROR_NOT_FOUND means that there were no operations to be
|
||||
// cancelled. We swallow this error to match the behaviour on other
|
||||
// platforms.
|
||||
ec = asio::error_code();
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = asio::error_code();
|
||||
}
|
||||
}
|
||||
#if defined(ASIO_ENABLE_CANCELIO)
|
||||
else if (impl.safe_cancellation_thread_id_ == 0)
|
||||
{
|
||||
// No operations have been started, so there's nothing to cancel.
|
||||
ec = asio::error_code();
|
||||
}
|
||||
else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId())
|
||||
{
|
||||
// Asynchronous operations have been started from the current thread only,
|
||||
// so it is safe to try to cancel them using CancelIo.
|
||||
socket_type sock = impl.socket_;
|
||||
HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock);
|
||||
if (!::CancelIo(sock_as_handle))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = asio::error_code();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Asynchronous operations have been started from more than one thread,
|
||||
// so cancellation is not safe.
|
||||
ec = asio::error::operation_not_supported;
|
||||
}
|
||||
#else // defined(ASIO_ENABLE_CANCELIO)
|
||||
else
|
||||
{
|
||||
// Cancellation is not supported as CancelIo may not be used.
|
||||
ec = asio::error::operation_not_supported;
|
||||
}
|
||||
#endif // defined(ASIO_ENABLE_CANCELIO)
|
||||
|
||||
// Cancel any operations started via the reactor.
|
||||
if (!ec)
|
||||
{
|
||||
reactor* r = static_cast<reactor*>(
|
||||
interlocked_compare_exchange_pointer(
|
||||
reinterpret_cast<void**>(&reactor_), 0, 0));
|
||||
if (r)
|
||||
r->cancel_ops(impl.socket_, impl.reactor_data_);
|
||||
}
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
asio::error_code win_iocp_socket_service_base::do_open(
|
||||
win_iocp_socket_service_base::base_implementation_type& impl,
|
||||
int family, int type, int protocol, asio::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = asio::error::already_open;
|
||||
return ec;
|
||||
}
|
||||
|
||||
socket_holder sock(socket_ops::socket(family, type, protocol, ec));
|
||||
if (sock.get() == invalid_socket)
|
||||
return ec;
|
||||
|
||||
HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock.get());
|
||||
if (iocp_service_.register_handle(sock_as_handle, ec))
|
||||
return ec;
|
||||
|
||||
impl.socket_ = sock.release();
|
||||
switch (type)
|
||||
{
|
||||
case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
|
||||
case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
|
||||
default: impl.state_ = 0; break;
|
||||
}
|
||||
impl.cancel_token_.reset(static_cast<void*>(0), socket_ops::noop_deleter());
|
||||
ec = asio::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
asio::error_code win_iocp_socket_service_base::do_assign(
|
||||
win_iocp_socket_service_base::base_implementation_type& impl,
|
||||
int type, socket_type native_socket, asio::error_code& ec)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
ec = asio::error::already_open;
|
||||
return ec;
|
||||
}
|
||||
|
||||
HANDLE sock_as_handle = reinterpret_cast<HANDLE>(native_socket);
|
||||
if (iocp_service_.register_handle(sock_as_handle, ec))
|
||||
return ec;
|
||||
|
||||
impl.socket_ = native_socket;
|
||||
switch (type)
|
||||
{
|
||||
case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;
|
||||
case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;
|
||||
default: impl.state_ = 0; break;
|
||||
}
|
||||
impl.cancel_token_.reset(static_cast<void*>(0), socket_ops::noop_deleter());
|
||||
ec = asio::error_code();
|
||||
return ec;
|
||||
}
|
||||
|
||||
void win_iocp_socket_service_base::start_send_op(
|
||||
win_iocp_socket_service_base::base_implementation_type& impl,
|
||||
WSABUF* buffers, std::size_t buffer_count,
|
||||
socket_base::message_flags flags, bool noop, operation* op)
|
||||
{
|
||||
update_cancellation_thread_id(impl);
|
||||
iocp_service_.work_started();
|
||||
|
||||
if (noop)
|
||||
iocp_service_.on_completion(op);
|
||||
else if (!is_open(impl))
|
||||
iocp_service_.on_completion(op, asio::error::bad_descriptor);
|
||||
else
|
||||
{
|
||||
DWORD bytes_transferred = 0;
|
||||
int result = ::WSASend(impl.socket_, buffers,
|
||||
static_cast<DWORD>(buffer_count), &bytes_transferred, flags, op, 0);
|
||||
DWORD last_error = ::WSAGetLastError();
|
||||
if (last_error == ERROR_PORT_UNREACHABLE)
|
||||
last_error = WSAECONNREFUSED;
|
||||
if (result != 0 && last_error != WSA_IO_PENDING)
|
||||
iocp_service_.on_completion(op, last_error, bytes_transferred);
|
||||
else
|
||||
iocp_service_.on_pending(op);
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_socket_service_base::start_send_to_op(
|
||||
win_iocp_socket_service_base::base_implementation_type& impl,
|
||||
WSABUF* buffers, std::size_t buffer_count,
|
||||
const socket_addr_type* addr, int addrlen,
|
||||
socket_base::message_flags flags, operation* op)
|
||||
{
|
||||
update_cancellation_thread_id(impl);
|
||||
iocp_service_.work_started();
|
||||
|
||||
if (!is_open(impl))
|
||||
iocp_service_.on_completion(op, asio::error::bad_descriptor);
|
||||
else
|
||||
{
|
||||
DWORD bytes_transferred = 0;
|
||||
int result = ::WSASendTo(impl.socket_, buffers,
|
||||
static_cast<DWORD>(buffer_count),
|
||||
&bytes_transferred, flags, addr, addrlen, op, 0);
|
||||
DWORD last_error = ::WSAGetLastError();
|
||||
if (last_error == ERROR_PORT_UNREACHABLE)
|
||||
last_error = WSAECONNREFUSED;
|
||||
if (result != 0 && last_error != WSA_IO_PENDING)
|
||||
iocp_service_.on_completion(op, last_error, bytes_transferred);
|
||||
else
|
||||
iocp_service_.on_pending(op);
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_socket_service_base::start_receive_op(
|
||||
win_iocp_socket_service_base::base_implementation_type& impl,
|
||||
WSABUF* buffers, std::size_t buffer_count,
|
||||
socket_base::message_flags flags, bool noop, operation* op)
|
||||
{
|
||||
update_cancellation_thread_id(impl);
|
||||
iocp_service_.work_started();
|
||||
|
||||
if (noop)
|
||||
iocp_service_.on_completion(op);
|
||||
else if (!is_open(impl))
|
||||
iocp_service_.on_completion(op, asio::error::bad_descriptor);
|
||||
else
|
||||
{
|
||||
DWORD bytes_transferred = 0;
|
||||
DWORD recv_flags = flags;
|
||||
int result = ::WSARecv(impl.socket_, buffers,
|
||||
static_cast<DWORD>(buffer_count),
|
||||
&bytes_transferred, &recv_flags, op, 0);
|
||||
DWORD last_error = ::WSAGetLastError();
|
||||
if (last_error == ERROR_NETNAME_DELETED)
|
||||
last_error = WSAECONNRESET;
|
||||
else if (last_error == ERROR_PORT_UNREACHABLE)
|
||||
last_error = WSAECONNREFUSED;
|
||||
if (result != 0 && last_error != WSA_IO_PENDING)
|
||||
iocp_service_.on_completion(op, last_error, bytes_transferred);
|
||||
else
|
||||
iocp_service_.on_pending(op);
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_socket_service_base::start_null_buffers_receive_op(
|
||||
win_iocp_socket_service_base::base_implementation_type& impl,
|
||||
socket_base::message_flags flags, reactor_op* op)
|
||||
{
|
||||
if ((impl.state_ & socket_ops::stream_oriented) != 0)
|
||||
{
|
||||
// For stream sockets on Windows, we may issue a 0-byte overlapped
|
||||
// WSARecv to wait until there is data available on the socket.
|
||||
::WSABUF buf = { 0, 0 };
|
||||
start_receive_op(impl, &buf, 1, flags, false, op);
|
||||
}
|
||||
else
|
||||
{
|
||||
start_reactor_op(impl,
|
||||
(flags & socket_base::message_out_of_band)
|
||||
? reactor::except_op : reactor::read_op,
|
||||
op);
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_socket_service_base::start_receive_from_op(
|
||||
win_iocp_socket_service_base::base_implementation_type& impl,
|
||||
WSABUF* buffers, std::size_t buffer_count, socket_addr_type* addr,
|
||||
socket_base::message_flags flags, int* addrlen, operation* op)
|
||||
{
|
||||
update_cancellation_thread_id(impl);
|
||||
iocp_service_.work_started();
|
||||
|
||||
if (!is_open(impl))
|
||||
iocp_service_.on_completion(op, asio::error::bad_descriptor);
|
||||
else
|
||||
{
|
||||
DWORD bytes_transferred = 0;
|
||||
DWORD recv_flags = flags;
|
||||
int result = ::WSARecvFrom(impl.socket_, buffers,
|
||||
static_cast<DWORD>(buffer_count),
|
||||
&bytes_transferred, &recv_flags, addr, addrlen, op, 0);
|
||||
DWORD last_error = ::WSAGetLastError();
|
||||
if (last_error == ERROR_PORT_UNREACHABLE)
|
||||
last_error = WSAECONNREFUSED;
|
||||
if (result != 0 && last_error != WSA_IO_PENDING)
|
||||
iocp_service_.on_completion(op, last_error, bytes_transferred);
|
||||
else
|
||||
iocp_service_.on_pending(op);
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_socket_service_base::start_accept_op(
|
||||
win_iocp_socket_service_base::base_implementation_type& impl,
|
||||
bool peer_is_open, socket_holder& new_socket, int family, int type,
|
||||
int protocol, void* output_buffer, DWORD address_length, operation* op)
|
||||
{
|
||||
update_cancellation_thread_id(impl);
|
||||
iocp_service_.work_started();
|
||||
|
||||
if (!is_open(impl))
|
||||
iocp_service_.on_completion(op, asio::error::bad_descriptor);
|
||||
else if (peer_is_open)
|
||||
iocp_service_.on_completion(op, asio::error::already_open);
|
||||
else
|
||||
{
|
||||
asio::error_code ec;
|
||||
new_socket.reset(socket_ops::socket(family, type, protocol, ec));
|
||||
if (new_socket.get() == invalid_socket)
|
||||
iocp_service_.on_completion(op, ec);
|
||||
else
|
||||
{
|
||||
DWORD bytes_read = 0;
|
||||
BOOL result = ::AcceptEx(impl.socket_, new_socket.get(), output_buffer,
|
||||
0, address_length, address_length, &bytes_read, op);
|
||||
DWORD last_error = ::WSAGetLastError();
|
||||
if (!result && last_error != WSA_IO_PENDING)
|
||||
iocp_service_.on_completion(op, last_error);
|
||||
else
|
||||
iocp_service_.on_pending(op);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_socket_service_base::restart_accept_op(
|
||||
socket_type s, socket_holder& new_socket, int family, int type,
|
||||
int protocol, void* output_buffer, DWORD address_length, operation* op)
|
||||
{
|
||||
new_socket.reset();
|
||||
iocp_service_.work_started();
|
||||
|
||||
asio::error_code ec;
|
||||
new_socket.reset(socket_ops::socket(family, type, protocol, ec));
|
||||
if (new_socket.get() == invalid_socket)
|
||||
iocp_service_.on_completion(op, ec);
|
||||
else
|
||||
{
|
||||
DWORD bytes_read = 0;
|
||||
BOOL result = ::AcceptEx(s, new_socket.get(), output_buffer,
|
||||
0, address_length, address_length, &bytes_read, op);
|
||||
DWORD last_error = ::WSAGetLastError();
|
||||
if (!result && last_error != WSA_IO_PENDING)
|
||||
iocp_service_.on_completion(op, last_error);
|
||||
else
|
||||
iocp_service_.on_pending(op);
|
||||
}
|
||||
}
|
||||
|
||||
void win_iocp_socket_service_base::start_reactor_op(
|
||||
win_iocp_socket_service_base::base_implementation_type& impl,
|
||||
int op_type, reactor_op* op)
|
||||
{
|
||||
reactor& r = get_reactor();
|
||||
update_cancellation_thread_id(impl);
|
||||
|
||||
if (is_open(impl))
|
||||
{
|
||||
r.start_op(op_type, impl.socket_, impl.reactor_data_, op, false);
|
||||
return;
|
||||
}
|
||||
else
|
||||
op->ec_ = asio::error::bad_descriptor;
|
||||
|
||||
iocp_service_.post_immediate_completion(op);
|
||||
}
|
||||
|
||||
void win_iocp_socket_service_base::start_connect_op(
|
||||
win_iocp_socket_service_base::base_implementation_type& impl,
|
||||
reactor_op* op, const socket_addr_type* addr, std::size_t addrlen)
|
||||
{
|
||||
reactor& r = get_reactor();
|
||||
update_cancellation_thread_id(impl);
|
||||
|
||||
if ((impl.state_ & socket_ops::non_blocking) != 0
|
||||
|| socket_ops::set_internal_non_blocking(
|
||||
impl.socket_, impl.state_, op->ec_))
|
||||
{
|
||||
if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0)
|
||||
{
|
||||
if (op->ec_ == asio::error::in_progress
|
||||
|| op->ec_ == asio::error::would_block)
|
||||
{
|
||||
op->ec_ = asio::error_code();
|
||||
r.start_op(reactor::connect_op, impl.socket_,
|
||||
impl.reactor_data_, op, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r.post_immediate_completion(op);
|
||||
}
|
||||
|
||||
void win_iocp_socket_service_base::close_for_destruction(
|
||||
win_iocp_socket_service_base::base_implementation_type& impl)
|
||||
{
|
||||
if (is_open(impl))
|
||||
{
|
||||
// Check if the reactor was created, in which case we need to close the
|
||||
// socket on the reactor as well to cancel any operations that might be
|
||||
// running there.
|
||||
reactor* r = static_cast<reactor*>(
|
||||
interlocked_compare_exchange_pointer(
|
||||
reinterpret_cast<void**>(&reactor_), 0, 0));
|
||||
if (r)
|
||||
r->close_descriptor(impl.socket_, impl.reactor_data_);
|
||||
}
|
||||
|
||||
asio::error_code ignored_ec;
|
||||
socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);
|
||||
impl.socket_ = invalid_socket;
|
||||
impl.state_ = 0;
|
||||
impl.cancel_token_.reset();
|
||||
#if defined(ASIO_ENABLE_CANCELIO)
|
||||
impl.safe_cancellation_thread_id_ = 0;
|
||||
#endif // defined(ASIO_ENABLE_CANCELIO)
|
||||
}
|
||||
|
||||
void win_iocp_socket_service_base::update_cancellation_thread_id(
|
||||
win_iocp_socket_service_base::base_implementation_type& impl)
|
||||
{
|
||||
#if defined(ASIO_ENABLE_CANCELIO)
|
||||
if (impl.safe_cancellation_thread_id_ == 0)
|
||||
impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();
|
||||
else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())
|
||||
impl.safe_cancellation_thread_id_ = ~DWORD(0);
|
||||
#else // defined(ASIO_ENABLE_CANCELIO)
|
||||
(void)impl;
|
||||
#endif // defined(ASIO_ENABLE_CANCELIO)
|
||||
}
|
||||
|
||||
reactor& win_iocp_socket_service_base::get_reactor()
|
||||
{
|
||||
reactor* r = static_cast<reactor*>(
|
||||
interlocked_compare_exchange_pointer(
|
||||
reinterpret_cast<void**>(&reactor_), 0, 0));
|
||||
if (!r)
|
||||
{
|
||||
r = &(use_service<reactor>(io_service_));
|
||||
interlocked_exchange_pointer(reinterpret_cast<void**>(&reactor_), r);
|
||||
}
|
||||
return *r;
|
||||
}
|
||||
|
||||
void* win_iocp_socket_service_base::interlocked_compare_exchange_pointer(
|
||||
void** dest, void* exch, void* cmp)
|
||||
{
|
||||
#if defined(_M_IX86)
|
||||
return reinterpret_cast<void*>(InterlockedCompareExchange(
|
||||
reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(exch),
|
||||
reinterpret_cast<LONG>(cmp)));
|
||||
#else
|
||||
return InterlockedCompareExchangePointer(dest, exch, cmp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void* win_iocp_socket_service_base::interlocked_exchange_pointer(
|
||||
void** dest, void* val)
|
||||
{
|
||||
#if defined(_M_IX86)
|
||||
return reinterpret_cast<void*>(InterlockedExchange(
|
||||
reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(val)));
|
||||
#else
|
||||
return InterlockedExchangePointer(dest, val);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(ASIO_HAS_IOCP)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_WIN_IOCP_SOCKET_SERVICE_BASE_IPP
|
78
ext/asio/asio/detail/impl/win_mutex.ipp
Normal file
78
ext/asio/asio/detail/impl/win_mutex.ipp
Normal file
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// detail/impl/win_mutex.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_WIN_MUTEX_IPP
|
||||
#define ASIO_DETAIL_IMPL_WIN_MUTEX_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(BOOST_WINDOWS)
|
||||
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/detail/win_mutex.hpp"
|
||||
#include "asio/error.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
win_mutex::win_mutex()
|
||||
{
|
||||
int error = do_init();
|
||||
asio::error_code ec(error,
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "mutex");
|
||||
}
|
||||
|
||||
int win_mutex::do_init()
|
||||
{
|
||||
#if defined(__MINGW32__)
|
||||
// Not sure if MinGW supports structured exception handling, so for now
|
||||
// we'll just call the Windows API and hope.
|
||||
# if defined(UNDER_CE)
|
||||
::InitializeCriticalSection(&crit_section_);
|
||||
# else
|
||||
if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000))
|
||||
return ::GetLastError();
|
||||
# endif
|
||||
return 0;
|
||||
#else
|
||||
__try
|
||||
{
|
||||
# if defined(UNDER_CE)
|
||||
::InitializeCriticalSection(&crit_section_);
|
||||
# else
|
||||
if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000))
|
||||
return ::GetLastError();
|
||||
# endif
|
||||
}
|
||||
__except(GetExceptionCode() == STATUS_NO_MEMORY
|
||||
? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
|
||||
{
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(BOOST_WINDOWS)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_WIN_MUTEX_IPP
|
138
ext/asio/asio/detail/impl/win_thread.ipp
Normal file
138
ext/asio/asio/detail/impl/win_thread.ipp
Normal file
@@ -0,0 +1,138 @@
|
||||
//
|
||||
// detail/impl/win_thread.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_WIN_THREAD_IPP
|
||||
#define ASIO_DETAIL_IMPL_WIN_THREAD_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(BOOST_WINDOWS) && !defined(UNDER_CE)
|
||||
|
||||
#include <process.h>
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/detail/win_thread.hpp"
|
||||
#include "asio/error.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
win_thread::~win_thread()
|
||||
{
|
||||
::CloseHandle(thread_);
|
||||
|
||||
// The exit_event_ handle is deliberately allowed to leak here since it
|
||||
// is an error for the owner of an internal thread not to join() it.
|
||||
}
|
||||
|
||||
void win_thread::join()
|
||||
{
|
||||
HANDLE handles[2] = { exit_event_, thread_ };
|
||||
::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
|
||||
::CloseHandle(exit_event_);
|
||||
if (terminate_threads())
|
||||
{
|
||||
::TerminateThread(thread_, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
::QueueUserAPC(apc_function, thread_, 0);
|
||||
::WaitForSingleObject(thread_, INFINITE);
|
||||
}
|
||||
}
|
||||
|
||||
void win_thread::start_thread(func_base* arg, unsigned int stack_size)
|
||||
{
|
||||
::HANDLE entry_event = 0;
|
||||
arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0);
|
||||
if (!entry_event)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
delete arg;
|
||||
asio::error_code ec(last_error,
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "thread.entry_event");
|
||||
}
|
||||
|
||||
arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0);
|
||||
if (!exit_event_)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
delete arg;
|
||||
asio::error_code ec(last_error,
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "thread.exit_event");
|
||||
}
|
||||
|
||||
unsigned int thread_id = 0;
|
||||
thread_ = reinterpret_cast<HANDLE>(::_beginthreadex(0,
|
||||
stack_size, win_thread_function, arg, 0, &thread_id));
|
||||
if (!thread_)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
delete arg;
|
||||
if (entry_event)
|
||||
::CloseHandle(entry_event);
|
||||
if (exit_event_)
|
||||
::CloseHandle(exit_event_);
|
||||
asio::error_code ec(last_error,
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "thread");
|
||||
}
|
||||
|
||||
if (entry_event)
|
||||
{
|
||||
::WaitForSingleObject(entry_event, INFINITE);
|
||||
::CloseHandle(entry_event);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int __stdcall win_thread_function(void* arg)
|
||||
{
|
||||
std::auto_ptr<win_thread::func_base> func(
|
||||
static_cast<win_thread::func_base*>(arg));
|
||||
|
||||
::SetEvent(func->entry_event_);
|
||||
|
||||
func->run();
|
||||
|
||||
// Signal that the thread has finished its work, but rather than returning go
|
||||
// to sleep to put the thread into a well known state. If the thread is being
|
||||
// joined during global object destruction then it may be killed using
|
||||
// TerminateThread (to avoid a deadlock in DllMain). Otherwise, the SleepEx
|
||||
// call will be interrupted using QueueUserAPC and the thread will shut down
|
||||
// cleanly.
|
||||
HANDLE exit_event = func->exit_event_;
|
||||
func.reset();
|
||||
::SetEvent(exit_event);
|
||||
::SleepEx(INFINITE, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(WINVER) && (WINVER < 0x0500)
|
||||
void __stdcall apc_function(ULONG) {}
|
||||
#else
|
||||
void __stdcall apc_function(ULONG_PTR) {}
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_WIN_THREAD_IPP
|
57
ext/asio/asio/detail/impl/win_tss_ptr.ipp
Normal file
57
ext/asio/asio/detail/impl/win_tss_ptr.ipp
Normal file
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// detail/impl/win_tss_ptr.ipp
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
//
|
||||
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef ASIO_DETAIL_IMPL_WIN_TSS_PTR_IPP
|
||||
#define ASIO_DETAIL_IMPL_WIN_TSS_PTR_IPP
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
# pragma once
|
||||
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||
|
||||
#include "asio/detail/config.hpp"
|
||||
|
||||
#if defined(BOOST_WINDOWS)
|
||||
|
||||
#include "asio/detail/throw_error.hpp"
|
||||
#include "asio/detail/win_tss_ptr.hpp"
|
||||
#include "asio/error.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
DWORD win_tss_ptr_create()
|
||||
{
|
||||
#if defined(UNDER_CE)
|
||||
enum { out_of_indexes = 0xFFFFFFFF };
|
||||
#else
|
||||
enum { out_of_indexes = TLS_OUT_OF_INDEXES };
|
||||
#endif
|
||||
|
||||
DWORD tss_key = ::TlsAlloc();
|
||||
if (tss_key == out_of_indexes)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
asio::error_code ec(last_error,
|
||||
asio::error::get_system_category());
|
||||
asio::detail::throw_error(ec, "tss");
|
||||
}
|
||||
return tss_key;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // defined(BOOST_WINDOWS)
|
||||
|
||||
#endif // ASIO_DETAIL_IMPL_WIN_TSS_PTR_IPP
|
69
ext/asio/asio/detail/impl/winsock_init.ipp
Normal file
69
ext/asio/asio/detail/impl/winsock_init.ipp
Normal file
@@ -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
|
@@ -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 {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user