|
Boost-Commit : |
From: troy_at_[hidden]
Date: 2008-07-01 14:19:39
Author: troy
Date: 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
New Revision: 46974
URL: http://svn.boost.org/trac/boost/changeset/46974
Log:
modularize asio
Added:
branches/CMake/release/libs/asio/include/
branches/CMake/release/libs/asio/include/boost/
branches/CMake/release/libs/asio/include/boost/asio/
branches/CMake/release/libs/asio/include/boost/asio.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/basic_datagram_socket.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/basic_deadline_timer.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/basic_io_object.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/basic_raw_socket.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/basic_serial_port.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/basic_socket.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/basic_socket_acceptor.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/basic_socket_iostream.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/basic_socket_streambuf.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/basic_stream_socket.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/basic_streambuf.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/buffer.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/buffered_read_stream.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/buffered_read_stream_fwd.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/buffered_stream.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/buffered_stream_fwd.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/buffered_write_stream.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/buffered_write_stream_fwd.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/buffers_iterator.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/completion_condition.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/datagram_socket_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/deadline_timer.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/deadline_timer_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/
branches/CMake/release/libs/asio/include/boost/asio/detail/bind_handler.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/buffer_resize_guard.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/buffered_stream_storage.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/call_stack.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/const_buffers_iterator.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/consuming_buffers.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/deadline_timer_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/descriptor_ops.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/dev_poll_reactor.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/dev_poll_reactor_fwd.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/epoll_reactor.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/epoll_reactor_fwd.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/event.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/fd_set_adapter.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/handler_alloc_helpers.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/handler_base_from_member.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/handler_invoke_helpers.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/handler_queue.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/hash_map.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/indirect_handler_queue.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/io_control.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/kqueue_reactor.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/kqueue_reactor_fwd.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/local_free_on_block_exit.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/mutex.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/noncopyable.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/null_event.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/null_mutex.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/null_signal_blocker.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/null_thread.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/null_tss_ptr.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/old_win_sdk_compat.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/pipe_select_interrupter.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/pop_options.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/posix_event.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/posix_fd_set_adapter.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/posix_mutex.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/posix_signal_blocker.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/posix_thread.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/posix_tss_ptr.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/push_options.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/reactive_descriptor_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/reactive_serial_port_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/reactive_socket_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/reactor_op_queue.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/resolver_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/scoped_lock.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/select_interrupter.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/select_reactor.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/select_reactor_fwd.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/service_base.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/service_id.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/service_registry.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/service_registry_fwd.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/signal_blocker.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/signal_init.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/socket_holder.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/socket_ops.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/socket_option.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/socket_select_interrupter.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/socket_types.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/strand_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/task_io_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/task_io_service_2lock.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/task_io_service_fwd.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/thread.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/throw_error.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/timer_queue.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/timer_queue_base.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/tss_ptr.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/win_event.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/win_fd_set_adapter.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/win_iocp_handle_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/win_iocp_io_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/win_iocp_io_service_fwd.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/win_iocp_serial_port_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/win_iocp_socket_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/win_mutex.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/win_signal_blocker.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/win_thread.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/win_tss_ptr.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/wince_thread.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/winsock_init.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/detail/wrapped_handler.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/error.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/handler_alloc_hook.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/handler_invoke_hook.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/impl/
branches/CMake/release/libs/asio/include/boost/asio/impl/io_service.ipp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/impl/read.ipp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/impl/read_at.ipp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/impl/read_until.ipp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/impl/serial_port_base.ipp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/impl/write.ipp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/impl/write_at.ipp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/io_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ip/
branches/CMake/release/libs/asio/include/boost/asio/ip/address.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ip/address_v4.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ip/address_v6.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ip/basic_endpoint.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ip/basic_resolver.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ip/basic_resolver_entry.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ip/basic_resolver_iterator.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ip/basic_resolver_query.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ip/detail/
branches/CMake/release/libs/asio/include/boost/asio/ip/detail/socket_option.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ip/host_name.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ip/icmp.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ip/multicast.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ip/resolver_query_base.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ip/resolver_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ip/tcp.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ip/udp.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ip/unicast.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ip/v6_only.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/is_read_buffered.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/is_write_buffered.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/local/
branches/CMake/release/libs/asio/include/boost/asio/local/basic_endpoint.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/local/connect_pair.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/local/datagram_protocol.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/local/stream_protocol.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/placeholders.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/posix/
branches/CMake/release/libs/asio/include/boost/asio/posix/basic_descriptor.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/posix/basic_stream_descriptor.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/posix/descriptor_base.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/posix/stream_descriptor.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/posix/stream_descriptor_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/raw_socket_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/read.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/read_at.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/read_until.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/serial_port.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/serial_port_base.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/serial_port_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/socket_acceptor_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/socket_base.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ssl/
branches/CMake/release/libs/asio/include/boost/asio/ssl.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ssl/basic_context.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ssl/context.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ssl/context_base.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ssl/context_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ssl/detail/
branches/CMake/release/libs/asio/include/boost/asio/ssl/detail/openssl_context_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ssl/detail/openssl_init.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ssl/detail/openssl_operation.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ssl/detail/openssl_stream_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ssl/detail/openssl_types.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ssl/stream.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ssl/stream_base.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/ssl/stream_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/strand.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/stream_socket_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/streambuf.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/time_traits.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/version.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/windows/
branches/CMake/release/libs/asio/include/boost/asio/windows/basic_handle.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/windows/basic_random_access_handle.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/windows/basic_stream_handle.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/windows/random_access_handle.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/windows/random_access_handle_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/windows/stream_handle.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/windows/stream_handle_service.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/write.hpp (contents, props changed)
branches/CMake/release/libs/asio/include/boost/asio/write_at.hpp (contents, props changed)
branches/CMake/release/libs/asio/module.cmake (contents, props changed)
Removed:
branches/CMake/release/boost/asio/
branches/CMake/release/boost/asio.hpp
Text files modified:
branches/CMake/release/libs/asio/CMakeLists.txt | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
Deleted: branches/CMake/release/boost/asio.hpp
==============================================================================
--- branches/CMake/release/boost/asio.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
+++ (empty file)
@@ -1,99 +0,0 @@
-//
-// asio.hpp
-// ~~~~~~~~
-//
-// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-// See www.boost.org/libs/asio for documentation.
-//
-
-#ifndef BOOST_ASIO_HPP
-#define BOOST_ASIO_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/basic_datagram_socket.hpp>
-#include <boost/asio/basic_deadline_timer.hpp>
-#include <boost/asio/basic_io_object.hpp>
-#include <boost/asio/basic_raw_socket.hpp>
-#include <boost/asio/basic_serial_port.hpp>
-#include <boost/asio/basic_socket_acceptor.hpp>
-#include <boost/asio/basic_socket_iostream.hpp>
-#include <boost/asio/basic_socket_streambuf.hpp>
-#include <boost/asio/basic_stream_socket.hpp>
-#include <boost/asio/basic_streambuf.hpp>
-#include <boost/asio/buffer.hpp>
-#include <boost/asio/buffered_read_stream_fwd.hpp>
-#include <boost/asio/buffered_read_stream.hpp>
-#include <boost/asio/buffered_stream_fwd.hpp>
-#include <boost/asio/buffered_stream.hpp>
-#include <boost/asio/buffered_write_stream_fwd.hpp>
-#include <boost/asio/buffered_write_stream.hpp>
-#include <boost/asio/buffers_iterator.hpp>
-#include <boost/asio/completion_condition.hpp>
-#include <boost/asio/datagram_socket_service.hpp>
-#include <boost/asio/deadline_timer_service.hpp>
-#include <boost/asio/deadline_timer.hpp>
-#include <boost/asio/error.hpp>
-#include <boost/asio/handler_alloc_hook.hpp>
-#include <boost/asio/handler_invoke_hook.hpp>
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/ip/address.hpp>
-#include <boost/asio/ip/address_v4.hpp>
-#include <boost/asio/ip/address_v6.hpp>
-#include <boost/asio/ip/basic_endpoint.hpp>
-#include <boost/asio/ip/basic_resolver.hpp>
-#include <boost/asio/ip/basic_resolver_entry.hpp>
-#include <boost/asio/ip/basic_resolver_iterator.hpp>
-#include <boost/asio/ip/basic_resolver_query.hpp>
-#include <boost/asio/ip/host_name.hpp>
-#include <boost/asio/ip/icmp.hpp>
-#include <boost/asio/ip/multicast.hpp>
-#include <boost/asio/ip/resolver_query_base.hpp>
-#include <boost/asio/ip/resolver_service.hpp>
-#include <boost/asio/ip/tcp.hpp>
-#include <boost/asio/ip/udp.hpp>
-#include <boost/asio/ip/unicast.hpp>
-#include <boost/asio/ip/v6_only.hpp>
-#include <boost/asio/is_read_buffered.hpp>
-#include <boost/asio/is_write_buffered.hpp>
-#include <boost/asio/local/basic_endpoint.hpp>
-#include <boost/asio/local/connect_pair.hpp>
-#include <boost/asio/local/datagram_protocol.hpp>
-#include <boost/asio/local/stream_protocol.hpp>
-#include <boost/asio/placeholders.hpp>
-#include <boost/asio/posix/basic_descriptor.hpp>
-#include <boost/asio/posix/basic_stream_descriptor.hpp>
-#include <boost/asio/posix/descriptor_base.hpp>
-#include <boost/asio/posix/stream_descriptor.hpp>
-#include <boost/asio/posix/stream_descriptor_service.hpp>
-#include <boost/asio/raw_socket_service.hpp>
-#include <boost/asio/read.hpp>
-#include <boost/asio/read_at.hpp>
-#include <boost/asio/read_until.hpp>
-#include <boost/asio/serial_port.hpp>
-#include <boost/asio/serial_port_base.hpp>
-#include <boost/asio/serial_port_service.hpp>
-#include <boost/asio/socket_acceptor_service.hpp>
-#include <boost/asio/socket_base.hpp>
-#include <boost/asio/strand.hpp>
-#include <boost/asio/stream_socket_service.hpp>
-#include <boost/asio/streambuf.hpp>
-#include <boost/asio/time_traits.hpp>
-#include <boost/asio/version.hpp>
-#include <boost/asio/windows/basic_handle.hpp>
-#include <boost/asio/windows/basic_random_access_handle.hpp>
-#include <boost/asio/windows/basic_stream_handle.hpp>
-#include <boost/asio/windows/random_access_handle.hpp>
-#include <boost/asio/windows/random_access_handle_service.hpp>
-#include <boost/asio/windows/stream_handle.hpp>
-#include <boost/asio/windows/stream_handle_service.hpp>
-#include <boost/asio/write.hpp>
-#include <boost/asio/write_at.hpp>
-
-#endif // BOOST_ASIO_HPP
Modified: branches/CMake/release/libs/asio/CMakeLists.txt
==============================================================================
--- branches/CMake/release/libs/asio/CMakeLists.txt (original)
+++ branches/CMake/release/libs/asio/CMakeLists.txt 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -1,7 +1,7 @@
boost_library_project(
- Any
- TESTDIRS test
- HEADERS any.hpp
+ Asio
+ HEADERS asio.hpp asio
+ MODULAR
)
Added: branches/CMake/release/libs/asio/include/boost/asio.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,99 @@
+//
+// asio.hpp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// See www.boost.org/libs/asio for documentation.
+//
+
+#ifndef BOOST_ASIO_HPP
+#define BOOST_ASIO_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/basic_datagram_socket.hpp>
+#include <boost/asio/basic_deadline_timer.hpp>
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/basic_raw_socket.hpp>
+#include <boost/asio/basic_serial_port.hpp>
+#include <boost/asio/basic_socket_acceptor.hpp>
+#include <boost/asio/basic_socket_iostream.hpp>
+#include <boost/asio/basic_socket_streambuf.hpp>
+#include <boost/asio/basic_stream_socket.hpp>
+#include <boost/asio/basic_streambuf.hpp>
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/buffered_read_stream_fwd.hpp>
+#include <boost/asio/buffered_read_stream.hpp>
+#include <boost/asio/buffered_stream_fwd.hpp>
+#include <boost/asio/buffered_stream.hpp>
+#include <boost/asio/buffered_write_stream_fwd.hpp>
+#include <boost/asio/buffered_write_stream.hpp>
+#include <boost/asio/buffers_iterator.hpp>
+#include <boost/asio/completion_condition.hpp>
+#include <boost/asio/datagram_socket_service.hpp>
+#include <boost/asio/deadline_timer_service.hpp>
+#include <boost/asio/deadline_timer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/handler_alloc_hook.hpp>
+#include <boost/asio/handler_invoke_hook.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/ip/address.hpp>
+#include <boost/asio/ip/address_v4.hpp>
+#include <boost/asio/ip/address_v6.hpp>
+#include <boost/asio/ip/basic_endpoint.hpp>
+#include <boost/asio/ip/basic_resolver.hpp>
+#include <boost/asio/ip/basic_resolver_entry.hpp>
+#include <boost/asio/ip/basic_resolver_iterator.hpp>
+#include <boost/asio/ip/basic_resolver_query.hpp>
+#include <boost/asio/ip/host_name.hpp>
+#include <boost/asio/ip/icmp.hpp>
+#include <boost/asio/ip/multicast.hpp>
+#include <boost/asio/ip/resolver_query_base.hpp>
+#include <boost/asio/ip/resolver_service.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include <boost/asio/ip/unicast.hpp>
+#include <boost/asio/ip/v6_only.hpp>
+#include <boost/asio/is_read_buffered.hpp>
+#include <boost/asio/is_write_buffered.hpp>
+#include <boost/asio/local/basic_endpoint.hpp>
+#include <boost/asio/local/connect_pair.hpp>
+#include <boost/asio/local/datagram_protocol.hpp>
+#include <boost/asio/local/stream_protocol.hpp>
+#include <boost/asio/placeholders.hpp>
+#include <boost/asio/posix/basic_descriptor.hpp>
+#include <boost/asio/posix/basic_stream_descriptor.hpp>
+#include <boost/asio/posix/descriptor_base.hpp>
+#include <boost/asio/posix/stream_descriptor.hpp>
+#include <boost/asio/posix/stream_descriptor_service.hpp>
+#include <boost/asio/raw_socket_service.hpp>
+#include <boost/asio/read.hpp>
+#include <boost/asio/read_at.hpp>
+#include <boost/asio/read_until.hpp>
+#include <boost/asio/serial_port.hpp>
+#include <boost/asio/serial_port_base.hpp>
+#include <boost/asio/serial_port_service.hpp>
+#include <boost/asio/socket_acceptor_service.hpp>
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/asio/stream_socket_service.hpp>
+#include <boost/asio/streambuf.hpp>
+#include <boost/asio/time_traits.hpp>
+#include <boost/asio/version.hpp>
+#include <boost/asio/windows/basic_handle.hpp>
+#include <boost/asio/windows/basic_random_access_handle.hpp>
+#include <boost/asio/windows/basic_stream_handle.hpp>
+#include <boost/asio/windows/random_access_handle.hpp>
+#include <boost/asio/windows/random_access_handle_service.hpp>
+#include <boost/asio/windows/stream_handle.hpp>
+#include <boost/asio/windows/stream_handle_service.hpp>
+#include <boost/asio/write.hpp>
+#include <boost/asio/write_at.hpp>
+
+#endif // BOOST_ASIO_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/basic_datagram_socket.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/basic_datagram_socket.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,805 @@
+//
+// basic_datagram_socket.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BASIC_DATAGRAM_SOCKET_HPP
+#define BOOST_ASIO_BASIC_DATAGRAM_SOCKET_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/basic_socket.hpp>
+#include <boost/asio/datagram_socket_service.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Provides datagram-oriented socket functionality.
+/**
+ * The basic_datagram_socket class template provides asynchronous and blocking
+ * datagram-oriented socket functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename Protocol,
+ typename DatagramSocketService = datagram_socket_service<Protocol> >
+class basic_datagram_socket
+ : public basic_socket<Protocol, DatagramSocketService>
+{
+public:
+ /// The native representation of a socket.
+ typedef typename DatagramSocketService::native_type native_type;
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ /// Construct a basic_datagram_socket without opening it.
+ /**
+ * This constructor creates a datagram socket without opening it. The open()
+ * function must be called before data can be sent or received on the socket.
+ *
+ * @param io_service The io_service object that the datagram socket will use
+ * to dispatch handlers for any asynchronous operations performed on the
+ * socket.
+ */
+ explicit basic_datagram_socket(boost::asio::io_service& io_service)
+ : basic_socket<Protocol, DatagramSocketService>(io_service)
+ {
+ }
+
+ /// Construct and open a basic_datagram_socket.
+ /**
+ * This constructor creates and opens a datagram socket.
+ *
+ * @param io_service The io_service object that the datagram socket will use
+ * to dispatch handlers for any asynchronous operations performed on the
+ * socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_datagram_socket(boost::asio::io_service& io_service,
+ const protocol_type& protocol)
+ : basic_socket<Protocol, DatagramSocketService>(io_service, protocol)
+ {
+ }
+
+ /// Construct a basic_datagram_socket, opening it and binding it to the given
+ /// local endpoint.
+ /**
+ * This constructor creates a datagram socket and automatically opens it bound
+ * to the specified endpoint on the local machine. The protocol used is the
+ * protocol associated with the given endpoint.
+ *
+ * @param io_service The io_service object that the datagram socket will use
+ * to dispatch handlers for any asynchronous operations performed on the
+ * socket.
+ *
+ * @param endpoint An endpoint on the local machine to which the datagram
+ * socket will be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_datagram_socket(boost::asio::io_service& io_service,
+ const endpoint_type& endpoint)
+ : basic_socket<Protocol, DatagramSocketService>(io_service, endpoint)
+ {
+ }
+
+ /// Construct a basic_datagram_socket on an existing native socket.
+ /**
+ * This constructor creates a datagram socket object to hold an existing
+ * native socket.
+ *
+ * @param io_service The io_service object that the datagram socket will use
+ * to dispatch handlers for any asynchronous operations performed on the
+ * socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_socket The new underlying socket implementation.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_datagram_socket(boost::asio::io_service& io_service,
+ const protocol_type& protocol, const native_type& native_socket)
+ : basic_socket<Protocol, DatagramSocketService>(
+ io_service, protocol, native_socket)
+ {
+ }
+
+ /// Send some data on a connected socket.
+ /**
+ * This function is used to send data on the datagram socket. The function
+ * call will block until the data has been sent successfully or an error
+ * occurs.
+ *
+ * @param buffers One ore more data buffers to be sent on the socket.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The send operation can only be used with a connected socket. Use
+ * the send_to function to send data on an unconnected datagram socket.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code socket.send(boost::asio::buffer(data, size)); @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.send(this->implementation, buffers, 0, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Send some data on a connected socket.
+ /**
+ * This function is used to send data on the datagram socket. The function
+ * call will block until the data has been sent successfully or an error
+ * occurs.
+ *
+ * @param buffers One ore more data buffers to be sent on the socket.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The send operation can only be used with a connected socket. Use
+ * the send_to function to send data on an unconnected datagram socket.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.send(
+ this->implementation, buffers, flags, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Send some data on a connected socket.
+ /**
+ * This function is used to send data on the datagram socket. The function
+ * call will block until the data has been sent successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @note The send operation can only be used with a connected socket. Use
+ * the send_to function to send data on an unconnected datagram socket.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return this->service.send(this->implementation, buffers, flags, ec);
+ }
+
+ /// Start an asynchronous send on a connected socket.
+ /**
+ * This function is used to send data on the datagram socket. The function
+ * call will block until the data has been sent successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket. Although
+ * the buffers object may be copied as necessary, ownership of the underlying
+ * memory blocks is retained by the caller, which must guarantee that they
+ * remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The async_send operation can only be used with a connected socket.
+ * Use the async_send_to function to send data on an unconnected datagram
+ * socket.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_send(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_send(const ConstBufferSequence& buffers, WriteHandler handler)
+ {
+ this->service.async_send(this->implementation, buffers, 0, handler);
+ }
+
+ /// Start an asynchronous send on a connected socket.
+ /**
+ * This function is used to send data on the datagram socket. The function
+ * call will block until the data has been sent successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket. Although
+ * the buffers object may be copied as necessary, ownership of the underlying
+ * memory blocks is retained by the caller, which must guarantee that they
+ * remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The async_send operation can only be used with a connected socket.
+ * Use the async_send_to function to send data on an unconnected datagram
+ * socket.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, WriteHandler handler)
+ {
+ this->service.async_send(this->implementation, buffers, flags, handler);
+ }
+
+ /// Send a datagram to the specified endpoint.
+ /**
+ * This function is used to send a datagram to the specified remote endpoint.
+ * The function call will block until the data has been sent successfully or
+ * an error occurs.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * boost::asio::ip::udp::endpoint destination(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.send_to(boost::asio::buffer(data, size), destination);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.send_to(
+ this->implementation, buffers, destination, 0, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Send a datagram to the specified endpoint.
+ /**
+ * This function is used to send a datagram to the specified remote endpoint.
+ * The function call will block until the data has been sent successfully or
+ * an error occurs.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.send_to(
+ this->implementation, buffers, destination, flags, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Send a datagram to the specified endpoint.
+ /**
+ * This function is used to send a datagram to the specified remote endpoint.
+ * The function call will block until the data has been sent successfully or
+ * an error occurs.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes sent.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ return this->service.send_to(this->implementation,
+ buffers, destination, flags, ec);
+ }
+
+ /// Start an asynchronous send.
+ /**
+ * This function is used to asynchronously send a datagram to the specified
+ * remote endpoint. The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ * Copies will be made of the endpoint as required.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * boost::asio::ip::udp::endpoint destination(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.async_send_to(
+ * boost::asio::buffer(data, size), destination, handler);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination, WriteHandler handler)
+ {
+ this->service.async_send_to(this->implementation, buffers, destination, 0,
+ handler);
+ }
+
+ /// Start an asynchronous send.
+ /**
+ * This function is used to asynchronously send a datagram to the specified
+ * remote endpoint. The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ * Copies will be made of the endpoint as required.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ WriteHandler handler)
+ {
+ this->service.async_send_to(this->implementation, buffers, destination,
+ flags, handler);
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the datagram socket. The function
+ * call will block until data has been received successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The receive operation can only be used with a connected socket. Use
+ * the receive_from function to receive data on an unconnected datagram
+ * socket.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code socket.receive(boost::asio::buffer(data, size)); @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.receive(
+ this->implementation, buffers, 0, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the datagram socket. The function
+ * call will block until data has been received successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The receive operation can only be used with a connected socket. Use
+ * the receive_from function to receive data on an unconnected datagram
+ * socket.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.receive(
+ this->implementation, buffers, flags, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the datagram socket. The function
+ * call will block until data has been received successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes received.
+ *
+ * @note The receive operation can only be used with a connected socket. Use
+ * the receive_from function to receive data on an unconnected datagram
+ * socket.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return this->service.receive(this->implementation, buffers, flags, ec);
+ }
+
+ /// Start an asynchronous receive on a connected socket.
+ /**
+ * This function is used to asynchronously receive data from the datagram
+ * socket. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The async_receive operation can only be used with a connected socket.
+ * Use the async_receive_from function to receive data on an unconnected
+ * datagram socket.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.async_receive(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_receive(const MutableBufferSequence& buffers, ReadHandler handler)
+ {
+ this->service.async_receive(this->implementation, buffers, 0, handler);
+ }
+
+ /// Start an asynchronous receive on a connected socket.
+ /**
+ * This function is used to asynchronously receive data from the datagram
+ * socket. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The async_receive operation can only be used with a connected socket.
+ * Use the async_receive_from function to receive data on an unconnected
+ * datagram socket.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, ReadHandler handler)
+ {
+ this->service.async_receive(this->implementation, buffers, flags, handler);
+ }
+
+ /// Receive a datagram with the endpoint of the sender.
+ /**
+ * This function is used to receive a datagram. The function call will block
+ * until data has been received successfully or an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * boost::asio::ip::udp::endpoint sender_endpoint;
+ * socket.receive_from(
+ * boost::asio::buffer(data, size), sender_endpoint);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.receive_from(
+ this->implementation, buffers, sender_endpoint, 0, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Receive a datagram with the endpoint of the sender.
+ /**
+ * This function is used to receive a datagram. The function call will block
+ * until data has been received successfully or an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.receive_from(
+ this->implementation, buffers, sender_endpoint, flags, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Receive a datagram with the endpoint of the sender.
+ /**
+ * This function is used to receive a datagram. The function call will block
+ * until data has been received successfully or an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes received.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ return this->service.receive_from(this->implementation, buffers,
+ sender_endpoint, flags, ec);
+ }
+
+ /// Start an asynchronous receive.
+ /**
+ * This function is used to asynchronously receive a datagram. The function
+ * call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram. Ownership of the sender_endpoint object
+ * is retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code socket.async_receive_from(
+ * boost::asio::buffer(data, size), 0, sender_endpoint, handler); @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, ReadHandler handler)
+ {
+ this->service.async_receive_from(this->implementation, buffers,
+ sender_endpoint, 0, handler);
+ }
+
+ /// Start an asynchronous receive.
+ /**
+ * This function is used to asynchronously receive a datagram. The function
+ * call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the datagram. Ownership of the sender_endpoint object
+ * is retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ ReadHandler handler)
+ {
+ this->service.async_receive_from(this->implementation, buffers,
+ sender_endpoint, flags, handler);
+ }
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_DATAGRAM_SOCKET_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/basic_deadline_timer.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/basic_deadline_timer.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,383 @@
+//
+// basic_deadline_timer.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BASIC_DEADLINE_TIMER_HPP
+#define BOOST_ASIO_BASIC_DEADLINE_TIMER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/deadline_timer_service.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Provides waitable timer functionality.
+/**
+ * The basic_deadline_timer class template provides the ability to perform a
+ * blocking or asynchronous wait for a timer to expire.
+ *
+ * Most applications will use the boost::asio::deadline_timer typedef.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Examples
+ * Performing a blocking wait:
+ * @code
+ * // Construct a timer without setting an expiry time.
+ * boost::asio::deadline_timer timer(io_service);
+ *
+ * // Set an expiry time relative to now.
+ * timer.expires_from_now(boost::posix_time::seconds(5));
+ *
+ * // Wait for the timer to expire.
+ * timer.wait();
+ * @endcode
+ *
+ * @par
+ * Performing an asynchronous wait:
+ * @code
+ * void handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Timer expired.
+ * }
+ * }
+ *
+ * ...
+ *
+ * // Construct a timer with an absolute expiry time.
+ * boost::asio::deadline_timer timer(io_service,
+ * boost::posix_time::time_from_string("2005-12-07 23:59:59.000"));
+ *
+ * // Start an asynchronous wait.
+ * timer.async_wait(handler);
+ * @endcode
+ *
+ * @par Changing an active deadline_timer's expiry time
+ *
+ * Changing the expiry time of a timer while there are pending asynchronous
+ * waits causes those wait operations to be cancelled. To ensure that the action
+ * associated with the timer is performed only once, use something like this:
+ * used:
+ *
+ * @code
+ * void on_some_event()
+ * {
+ * if (my_timer.expires_from_now(seconds(5)) > 0)
+ * {
+ * // We managed to cancel the timer. Start new asynchronous wait.
+ * my_timer.async_wait(on_timeout);
+ * }
+ * else
+ * {
+ * // Too late, timer has already expired!
+ * }
+ * }
+ *
+ * void on_timeout(const boost::system::error_code& e)
+ * {
+ * if (e != boost::asio::error::operation_aborted)
+ * {
+ * // Timer was not cancelled, take necessary action.
+ * }
+ * }
+ * @endcode
+ *
+ * @li The boost::asio::basic_deadline_timer::expires_from_now() function
+ * cancels any pending asynchronous waits, and returns the number of
+ * asynchronous waits that were cancelled. If it returns 0 then you were too
+ * late and the wait handler has already been executed, or will soon be
+ * executed. If it returns 1 then the wait handler was successfully cancelled.
+ *
+ * @li If a wait handler is cancelled, the boost::system::error_code passed to
+ * it contains the value boost::asio::error::operation_aborted.
+ */
+template <typename Time,
+ typename TimeTraits = boost::asio::time_traits<Time>,
+ typename TimerService = deadline_timer_service<Time, TimeTraits> >
+class basic_deadline_timer
+ : public basic_io_object<TimerService>
+{
+public:
+ /// The time traits type.
+ typedef TimeTraits traits_type;
+
+ /// The time type.
+ typedef typename traits_type::time_type time_type;
+
+ /// The duration type.
+ typedef typename traits_type::duration_type duration_type;
+
+ /// Constructor.
+ /**
+ * This constructor creates a timer without setting an expiry time. The
+ * expires_at() or expires_from_now() functions must be called to set an
+ * expiry time before the timer can be waited on.
+ *
+ * @param io_service The io_service object that the timer will use to dispatch
+ * handlers for any asynchronous operations performed on the timer.
+ */
+ explicit basic_deadline_timer(boost::asio::io_service& io_service)
+ : basic_io_object<TimerService>(io_service)
+ {
+ }
+
+ /// Constructor to set a particular expiry time as an absolute time.
+ /**
+ * This constructor creates a timer and sets the expiry time.
+ *
+ * @param io_service The io_service object that the timer will use to dispatch
+ * handlers for any asynchronous operations performed on the timer.
+ *
+ * @param expiry_time The expiry time to be used for the timer, expressed
+ * as an absolute time.
+ */
+ basic_deadline_timer(boost::asio::io_service& io_service,
+ const time_type& expiry_time)
+ : basic_io_object<TimerService>(io_service)
+ {
+ boost::system::error_code ec;
+ this->service.expires_at(this->implementation, expiry_time, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Constructor to set a particular expiry time relative to now.
+ /**
+ * This constructor creates a timer and sets the expiry time.
+ *
+ * @param io_service The io_service object that the timer will use to dispatch
+ * handlers for any asynchronous operations performed on the timer.
+ *
+ * @param expiry_time The expiry time to be used for the timer, relative to
+ * now.
+ */
+ basic_deadline_timer(boost::asio::io_service& io_service,
+ const duration_type& expiry_time)
+ : basic_io_object<TimerService>(io_service)
+ {
+ boost::system::error_code ec;
+ this->service.expires_from_now(this->implementation, expiry_time, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Cancel any asynchronous operations that are waiting on the timer.
+ /**
+ * This function forces the completion of any pending asynchronous wait
+ * operations against the timer. The handler for each cancelled operation will
+ * be invoked with the boost::asio::error::operation_aborted error code.
+ *
+ * Cancelling the timer does not change the expiry time.
+ *
+ * @return The number of asynchronous operations that were cancelled.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ std::size_t cancel()
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.cancel(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Cancel any asynchronous operations that are waiting on the timer.
+ /**
+ * This function forces the completion of any pending asynchronous wait
+ * operations against the timer. The handler for each cancelled operation will
+ * be invoked with the boost::asio::error::operation_aborted error code.
+ *
+ * Cancelling the timer does not change the expiry time.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return The number of asynchronous operations that were cancelled.
+ */
+ std::size_t cancel(boost::system::error_code& ec)
+ {
+ return this->service.cancel(this->implementation, ec);
+ }
+
+ /// Get the timer's expiry time as an absolute time.
+ /**
+ * This function may be used to obtain the timer's current expiry time.
+ * Whether the timer has expired or not does not affect this value.
+ */
+ time_type expires_at() const
+ {
+ return this->service.expires_at(this->implementation);
+ }
+
+ /// Set the timer's expiry time as an absolute time.
+ /**
+ * This function sets the expiry time. Any pending asynchronous wait
+ * operations will be cancelled. The handler for each cancelled operation will
+ * be invoked with the boost::asio::error::operation_aborted error code.
+ *
+ * @param expiry_time The expiry time to be used for the timer.
+ *
+ * @return The number of asynchronous operations that were cancelled.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ std::size_t expires_at(const time_type& expiry_time)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.expires_at(
+ this->implementation, expiry_time, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Set the timer's expiry time as an absolute time.
+ /**
+ * This function sets the expiry time. Any pending asynchronous wait
+ * operations will be cancelled. The handler for each cancelled operation will
+ * be invoked with the boost::asio::error::operation_aborted error code.
+ *
+ * @param expiry_time The expiry time to be used for the timer.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return The number of asynchronous operations that were cancelled.
+ */
+ std::size_t expires_at(const time_type& expiry_time,
+ boost::system::error_code& ec)
+ {
+ return this->service.expires_at(this->implementation, expiry_time, ec);
+ }
+
+ /// Get the timer's expiry time relative to now.
+ /**
+ * This function may be used to obtain the timer's current expiry time.
+ * Whether the timer has expired or not does not affect this value.
+ */
+ duration_type expires_from_now() const
+ {
+ return this->service.expires_from_now(this->implementation);
+ }
+
+ /// Set the timer's expiry time relative to now.
+ /**
+ * This function sets the expiry time. Any pending asynchronous wait
+ * operations will be cancelled. The handler for each cancelled operation will
+ * be invoked with the boost::asio::error::operation_aborted error code.
+ *
+ * @param expiry_time The expiry time to be used for the timer.
+ *
+ * @return The number of asynchronous operations that were cancelled.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ std::size_t expires_from_now(const duration_type& expiry_time)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.expires_from_now(
+ this->implementation, expiry_time, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Set the timer's expiry time relative to now.
+ /**
+ * This function sets the expiry time. Any pending asynchronous wait
+ * operations will be cancelled. The handler for each cancelled operation will
+ * be invoked with the boost::asio::error::operation_aborted error code.
+ *
+ * @param expiry_time The expiry time to be used for the timer.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return The number of asynchronous operations that were cancelled.
+ */
+ std::size_t expires_from_now(const duration_type& expiry_time,
+ boost::system::error_code& ec)
+ {
+ return this->service.expires_from_now(
+ this->implementation, expiry_time, ec);
+ }
+
+ /// Perform a blocking wait on the timer.
+ /**
+ * This function is used to wait for the timer to expire. This function
+ * blocks and does not return until the timer has expired.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void wait()
+ {
+ boost::system::error_code ec;
+ this->service.wait(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Perform a blocking wait on the timer.
+ /**
+ * This function is used to wait for the timer to expire. This function
+ * blocks and does not return until the timer has expired.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ void wait(boost::system::error_code& ec)
+ {
+ this->service.wait(this->implementation, ec);
+ }
+
+ /// Start an asynchronous wait on the timer.
+ /**
+ * This function may be used to initiate an asynchronous wait against the
+ * timer. It always returns immediately.
+ *
+ * For each call to async_wait(), the supplied handler will be called exactly
+ * once. The handler will be called when:
+ *
+ * @li The timer has expired.
+ *
+ * @li The timer was cancelled, in which case the handler is passed the error
+ * code boost::asio::error::operation_aborted.
+ *
+ * @param handler The handler to be called when the timer expires. Copies
+ * will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ */
+ template <typename WaitHandler>
+ void async_wait(WaitHandler handler)
+ {
+ this->service.async_wait(this->implementation, handler);
+ }
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_DEADLINE_TIMER_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/basic_io_object.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/basic_io_object.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,99 @@
+//
+// basic_io_object.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BASIC_IO_OBJECT_HPP
+#define BOOST_ASIO_BASIC_IO_OBJECT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Base class for all I/O objects.
+template <typename IoObjectService>
+class basic_io_object
+ : private noncopyable
+{
+public:
+ /// The type of the service that will be used to provide I/O operations.
+ typedef IoObjectService service_type;
+
+ /// The underlying implementation type of I/O object.
+ typedef typename service_type::implementation_type implementation_type;
+
+ /// (Deprecated: use get_io_service().) Get the io_service associated with
+ /// the object.
+ /**
+ * This function may be used to obtain the io_service object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_service object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_service& io_service()
+ {
+ return service.get_io_service();
+ }
+
+ /// Get the io_service associated with the object.
+ /**
+ * This function may be used to obtain the io_service object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_service object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_service& get_io_service()
+ {
+ return service.get_io_service();
+ }
+
+protected:
+ /// Construct a basic_io_object.
+ /**
+ * Performs:
+ * @code service.construct(implementation); @endcode
+ */
+ explicit basic_io_object(boost::asio::io_service& io_service)
+ : service(boost::asio::use_service<IoObjectService>(io_service))
+ {
+ service.construct(implementation);
+ }
+
+ /// Protected destructor to prevent deletion through this type.
+ /**
+ * Performs:
+ * @code service.destroy(implementation); @endcode
+ */
+ ~basic_io_object()
+ {
+ service.destroy(implementation);
+ }
+
+ /// The service associated with the I/O object.
+ service_type& service;
+
+ /// The underlying implementation of the I/O object.
+ implementation_type implementation;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_IO_OBJECT_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/basic_raw_socket.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/basic_raw_socket.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,800 @@
+//
+// basic_raw_socket.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BASIC_RAW_SOCKET_HPP
+#define BOOST_ASIO_BASIC_RAW_SOCKET_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/basic_socket.hpp>
+#include <boost/asio/raw_socket_service.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Provides raw-oriented socket functionality.
+/**
+ * The basic_raw_socket class template provides asynchronous and blocking
+ * raw-oriented socket functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename Protocol,
+ typename RawSocketService = raw_socket_service<Protocol> >
+class basic_raw_socket
+ : public basic_socket<Protocol, RawSocketService>
+{
+public:
+ /// The native representation of a socket.
+ typedef typename RawSocketService::native_type native_type;
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ /// Construct a basic_raw_socket without opening it.
+ /**
+ * This constructor creates a raw socket without opening it. The open()
+ * function must be called before data can be sent or received on the socket.
+ *
+ * @param io_service The io_service object that the raw socket will use
+ * to dispatch handlers for any asynchronous operations performed on the
+ * socket.
+ */
+ explicit basic_raw_socket(boost::asio::io_service& io_service)
+ : basic_socket<Protocol, RawSocketService>(io_service)
+ {
+ }
+
+ /// Construct and open a basic_raw_socket.
+ /**
+ * This constructor creates and opens a raw socket.
+ *
+ * @param io_service The io_service object that the raw socket will use
+ * to dispatch handlers for any asynchronous operations performed on the
+ * socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_raw_socket(boost::asio::io_service& io_service,
+ const protocol_type& protocol)
+ : basic_socket<Protocol, RawSocketService>(io_service, protocol)
+ {
+ }
+
+ /// Construct a basic_raw_socket, opening it and binding it to the given
+ /// local endpoint.
+ /**
+ * This constructor creates a raw socket and automatically opens it bound
+ * to the specified endpoint on the local machine. The protocol used is the
+ * protocol associated with the given endpoint.
+ *
+ * @param io_service The io_service object that the raw socket will use
+ * to dispatch handlers for any asynchronous operations performed on the
+ * socket.
+ *
+ * @param endpoint An endpoint on the local machine to which the raw
+ * socket will be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_raw_socket(boost::asio::io_service& io_service,
+ const endpoint_type& endpoint)
+ : basic_socket<Protocol, RawSocketService>(io_service, endpoint)
+ {
+ }
+
+ /// Construct a basic_raw_socket on an existing native socket.
+ /**
+ * This constructor creates a raw socket object to hold an existing
+ * native socket.
+ *
+ * @param io_service The io_service object that the raw socket will use
+ * to dispatch handlers for any asynchronous operations performed on the
+ * socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_socket The new underlying socket implementation.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_raw_socket(boost::asio::io_service& io_service,
+ const protocol_type& protocol, const native_type& native_socket)
+ : basic_socket<Protocol, RawSocketService>(
+ io_service, protocol, native_socket)
+ {
+ }
+
+ /// Send some data on a connected socket.
+ /**
+ * This function is used to send data on the raw socket. The function call
+ * will block until the data has been sent successfully or an error occurs.
+ *
+ * @param buffers One ore more data buffers to be sent on the socket.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The send operation can only be used with a connected socket. Use
+ * the send_to function to send data on an unconnected raw socket.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code socket.send(boost::asio::buffer(data, size)); @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.send(this->implementation, buffers, 0, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Send some data on a connected socket.
+ /**
+ * This function is used to send data on the raw socket. The function call
+ * will block until the data has been sent successfully or an error occurs.
+ *
+ * @param buffers One ore more data buffers to be sent on the socket.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The send operation can only be used with a connected socket. Use
+ * the send_to function to send data on an unconnected raw socket.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.send(
+ this->implementation, buffers, flags, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Send some data on a connected socket.
+ /**
+ * This function is used to send data on the raw socket. The function call
+ * will block until the data has been sent successfully or an error occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @note The send operation can only be used with a connected socket. Use
+ * the send_to function to send data on an unconnected raw socket.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return this->service.send(this->implementation, buffers, flags, ec);
+ }
+
+ /// Start an asynchronous send on a connected socket.
+ /**
+ * This function is used to send data on the raw socket. The function call
+ * will block until the data has been sent successfully or an error occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket. Although
+ * the buffers object may be copied as necessary, ownership of the underlying
+ * memory blocks is retained by the caller, which must guarantee that they
+ * remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The async_send operation can only be used with a connected socket.
+ * Use the async_send_to function to send data on an unconnected raw
+ * socket.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_send(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_send(const ConstBufferSequence& buffers, WriteHandler handler)
+ {
+ this->service.async_send(this->implementation, buffers, 0, handler);
+ }
+
+ /// Start an asynchronous send on a connected socket.
+ /**
+ * This function is used to send data on the raw socket. The function call
+ * will block until the data has been sent successfully or an error occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket. Although
+ * the buffers object may be copied as necessary, ownership of the underlying
+ * memory blocks is retained by the caller, which must guarantee that they
+ * remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The async_send operation can only be used with a connected socket.
+ * Use the async_send_to function to send data on an unconnected raw
+ * socket.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, WriteHandler handler)
+ {
+ this->service.async_send(this->implementation, buffers, flags, handler);
+ }
+
+ /// Send raw data to the specified endpoint.
+ /**
+ * This function is used to send raw data to the specified remote endpoint.
+ * The function call will block until the data has been sent successfully or
+ * an error occurs.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * boost::asio::ip::udp::endpoint destination(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.send_to(boost::asio::buffer(data, size), destination);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.send_to(
+ this->implementation, buffers, destination, 0, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Send raw data to the specified endpoint.
+ /**
+ * This function is used to send raw data to the specified remote endpoint.
+ * The function call will block until the data has been sent successfully or
+ * an error occurs.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.send_to(
+ this->implementation, buffers, destination, flags, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Send raw data to the specified endpoint.
+ /**
+ * This function is used to send raw data to the specified remote endpoint.
+ * The function call will block until the data has been sent successfully or
+ * an error occurs.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes sent.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ return this->service.send_to(this->implementation,
+ buffers, destination, flags, ec);
+ }
+
+ /// Start an asynchronous send.
+ /**
+ * This function is used to asynchronously send raw data to the specified
+ * remote endpoint. The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ * Copies will be made of the endpoint as required.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * boost::asio::ip::udp::endpoint destination(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.async_send_to(
+ * boost::asio::buffer(data, size), destination, handler);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination, WriteHandler handler)
+ {
+ this->service.async_send_to(this->implementation, buffers, destination, 0,
+ handler);
+ }
+
+ /// Start an asynchronous send.
+ /**
+ * This function is used to asynchronously send raw data to the specified
+ * remote endpoint. The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent to the remote endpoint.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param destination The remote endpoint to which the data will be sent.
+ * Copies will be made of the endpoint as required.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_send_to(const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ WriteHandler handler)
+ {
+ this->service.async_send_to(this->implementation, buffers, destination,
+ flags, handler);
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the raw socket. The function
+ * call will block until data has been received successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The receive operation can only be used with a connected socket. Use
+ * the receive_from function to receive data on an unconnected raw
+ * socket.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code socket.receive(boost::asio::buffer(data, size)); @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.receive(
+ this->implementation, buffers, 0, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the raw socket. The function
+ * call will block until data has been received successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The receive operation can only be used with a connected socket. Use
+ * the receive_from function to receive data on an unconnected raw
+ * socket.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.receive(
+ this->implementation, buffers, flags, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the raw socket. The function
+ * call will block until data has been received successfully or an error
+ * occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes received.
+ *
+ * @note The receive operation can only be used with a connected socket. Use
+ * the receive_from function to receive data on an unconnected raw
+ * socket.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return this->service.receive(this->implementation, buffers, flags, ec);
+ }
+
+ /// Start an asynchronous receive on a connected socket.
+ /**
+ * This function is used to asynchronously receive data from the raw
+ * socket. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The async_receive operation can only be used with a connected socket.
+ * Use the async_receive_from function to receive data on an unconnected
+ * raw socket.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.async_receive(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_receive(const MutableBufferSequence& buffers, ReadHandler handler)
+ {
+ this->service.async_receive(this->implementation, buffers, 0, handler);
+ }
+
+ /// Start an asynchronous receive on a connected socket.
+ /**
+ * This function is used to asynchronously receive data from the raw
+ * socket. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The async_receive operation can only be used with a connected socket.
+ * Use the async_receive_from function to receive data on an unconnected
+ * raw socket.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, ReadHandler handler)
+ {
+ this->service.async_receive(this->implementation, buffers, flags, handler);
+ }
+
+ /// Receive raw data with the endpoint of the sender.
+ /**
+ * This function is used to receive raw data. The function call will block
+ * until data has been received successfully or an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the data.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * boost::asio::ip::udp::endpoint sender_endpoint;
+ * socket.receive_from(
+ * boost::asio::buffer(data, size), sender_endpoint);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.receive_from(
+ this->implementation, buffers, sender_endpoint, 0, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Receive raw data with the endpoint of the sender.
+ /**
+ * This function is used to receive raw data. The function call will block
+ * until data has been received successfully or an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the data.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.receive_from(
+ this->implementation, buffers, sender_endpoint, flags, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Receive raw data with the endpoint of the sender.
+ /**
+ * This function is used to receive raw data. The function call will block
+ * until data has been received successfully or an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the data.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes received.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ return this->service.receive_from(this->implementation, buffers,
+ sender_endpoint, flags, ec);
+ }
+
+ /// Start an asynchronous receive.
+ /**
+ * This function is used to asynchronously receive raw data. The function
+ * call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the data. Ownership of the sender_endpoint object
+ * is retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code socket.async_receive_from(
+ * boost::asio::buffer(data, size), 0, sender_endpoint, handler); @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, ReadHandler handler)
+ {
+ this->service.async_receive_from(this->implementation, buffers,
+ sender_endpoint, 0, handler);
+ }
+
+ /// Start an asynchronous receive.
+ /**
+ * This function is used to asynchronously receive raw data. The function
+ * call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param sender_endpoint An endpoint object that receives the endpoint of
+ * the remote sender of the data. Ownership of the sender_endpoint object
+ * is retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_receive_from(const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ ReadHandler handler)
+ {
+ this->service.async_receive_from(this->implementation, buffers,
+ sender_endpoint, flags, handler);
+ }
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_RAW_SOCKET_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/basic_serial_port.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/basic_serial_port.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,610 @@
+//
+// basic_serial_port.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info_at_[hidden])
+//
+// Distributed under the 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 BOOST_ASIO_BASIC_SERIAL_PORT_HPP
+#define BOOST_ASIO_BASIC_SERIAL_PORT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <string>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/serial_port_base.hpp>
+#include <boost/asio/serial_port_service.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+#if defined(BOOST_ASIO_HAS_SERIAL_PORT) \
+ || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+
+/// Provides serial port functionality.
+/**
+ * The basic_serial_port class template provides functionality that is common
+ * to all serial ports.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename SerialPortService = serial_port_service>
+class basic_serial_port
+ : public basic_io_object<SerialPortService>,
+ public serial_port_base
+{
+public:
+ /// The native representation of a serial port.
+ typedef typename SerialPortService::native_type native_type;
+
+ /// A basic_serial_port is always the lowest layer.
+ typedef basic_serial_port<SerialPortService> lowest_layer_type;
+
+ /// Construct a basic_serial_port without opening it.
+ /**
+ * This constructor creates a serial port without opening it.
+ *
+ * @param io_service The io_service object that the serial port will use to
+ * dispatch handlers for any asynchronous operations performed on the port.
+ */
+ explicit basic_serial_port(boost::asio::io_service& io_service)
+ : basic_io_object<SerialPortService>(io_service)
+ {
+ }
+
+ /// Construct and open a basic_serial_port.
+ /**
+ * This constructor creates and opens a serial port for the specified device
+ * name.
+ *
+ * @param io_service The io_service object that the serial port will use to
+ * dispatch handlers for any asynchronous operations performed on the port.
+ *
+ * @param device The platform-specific device name for this serial
+ * port.
+ */
+ explicit basic_serial_port(boost::asio::io_service& io_service,
+ const char* device)
+ : basic_io_object<SerialPortService>(io_service)
+ {
+ boost::system::error_code ec;
+ this->service.open(this->implementation, device, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Construct and open a basic_serial_port.
+ /**
+ * This constructor creates and opens a serial port for the specified device
+ * name.
+ *
+ * @param io_service The io_service object that the serial port will use to
+ * dispatch handlers for any asynchronous operations performed on the port.
+ *
+ * @param device The platform-specific device name for this serial
+ * port.
+ */
+ explicit basic_serial_port(boost::asio::io_service& io_service,
+ const std::string& device)
+ : basic_io_object<SerialPortService>(io_service)
+ {
+ boost::system::error_code ec;
+ this->service.open(this->implementation, device, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Construct a basic_serial_port on an existing native serial port.
+ /**
+ * This constructor creates a serial port object to hold an existing native
+ * serial port.
+ *
+ * @param io_service The io_service object that the serial port will use to
+ * dispatch handlers for any asynchronous operations performed on the port.
+ *
+ * @param native_serial_port A native serial port.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_serial_port(boost::asio::io_service& io_service,
+ const native_type& native_serial_port)
+ : basic_io_object<SerialPortService>(io_service)
+ {
+ boost::system::error_code ec;
+ this->service.assign(this->implementation, native_serial_port, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Get a reference to the lowest layer.
+ /**
+ * This function returns a reference to the lowest layer in a stack of
+ * layers. Since a basic_serial_port cannot contain any further layers, it
+ * simply returns a reference to itself.
+ *
+ * @return A reference to the lowest layer in the stack of layers. Ownership
+ * is not transferred to the caller.
+ */
+ lowest_layer_type& lowest_layer()
+ {
+ return *this;
+ }
+
+ /// Open the serial port using the specified device name.
+ /**
+ * This function opens the serial port for the specified device name.
+ *
+ * @param device The platform-specific device name.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void open(const std::string& device)
+ {
+ boost::system::error_code ec;
+ this->service.open(this->implementation, device, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Open the serial port using the specified device name.
+ /**
+ * This function opens the serial port using the given platform-specific
+ * device name.
+ *
+ * @param device The platform-specific device name.
+ *
+ * @param ec Set the indicate what error occurred, if any.
+ */
+ boost::system::error_code open(const std::string& device,
+ boost::system::error_code& ec)
+ {
+ return this->service.open(this->implementation, device, ec);
+ }
+
+ /// Assign an existing native serial port to the serial port.
+ /*
+ * This function opens the serial port to hold an existing native serial port.
+ *
+ * @param native_serial_port A native serial port.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void assign(const native_type& native_serial_port)
+ {
+ boost::system::error_code ec;
+ this->service.assign(this->implementation, native_serial_port, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Assign an existing native serial port to the serial port.
+ /*
+ * This function opens the serial port to hold an existing native serial port.
+ *
+ * @param native_serial_port A native serial port.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code assign(const native_type& native_serial_port,
+ boost::system::error_code& ec)
+ {
+ return this->service.assign(this->implementation, native_serial_port, ec);
+ }
+
+ /// Determine whether the serial port is open.
+ bool is_open() const
+ {
+ return this->service.is_open(this->implementation);
+ }
+
+ /// Close the serial port.
+ /**
+ * This function is used to close the serial port. Any asynchronous read or
+ * write operations will be cancelled immediately, and will complete with the
+ * boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void close()
+ {
+ boost::system::error_code ec;
+ this->service.close(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Close the serial port.
+ /**
+ * This function is used to close the serial port. Any asynchronous read or
+ * write operations will be cancelled immediately, and will complete with the
+ * boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code close(boost::system::error_code& ec)
+ {
+ return this->service.close(this->implementation, ec);
+ }
+
+ /// Get the native serial port representation.
+ /**
+ * This function may be used to obtain the underlying representation of the
+ * serial port. This is intended to allow access to native serial port
+ * functionality that is not otherwise provided.
+ */
+ native_type native()
+ {
+ return this->service.native(this->implementation);
+ }
+
+ /// Cancel all asynchronous operations associated with the serial port.
+ /**
+ * This function causes all outstanding asynchronous read or write operations
+ * to finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void cancel()
+ {
+ boost::system::error_code ec;
+ this->service.cancel(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Cancel all asynchronous operations associated with the serial port.
+ /**
+ * This function causes all outstanding asynchronous read or write operations
+ * to finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code cancel(boost::system::error_code& ec)
+ {
+ return this->service.cancel(this->implementation, ec);
+ }
+
+ /// Send a break sequence to the serial port.
+ /**
+ * This function causes a break sequence of platform-specific duration to be
+ * sent out the serial port.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void send_break()
+ {
+ boost::system::error_code ec;
+ this->service.send_break(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Send a break sequence to the serial port.
+ /**
+ * This function causes a break sequence of platform-specific duration to be
+ * sent out the serial port.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code send_break(boost::system::error_code& ec)
+ {
+ return this->service.send_break(this->implementation, ec);
+ }
+
+ /// Set an option on the serial port.
+ /**
+ * This function is used to set an option on the serial port.
+ *
+ * @param option The option value to be set on the serial port.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa SettableSerialPortOption @n
+ * boost::asio::serial_port_base::baud_rate @n
+ * boost::asio::serial_port_base::flow_control @n
+ * boost::asio::serial_port_base::parity @n
+ * boost::asio::serial_port_base::stop_bits @n
+ * boost::asio::serial_port_base::character_size
+ */
+ template <typename SettableSerialPortOption>
+ void set_option(const SettableSerialPortOption& option)
+ {
+ boost::system::error_code ec;
+ this->service.set_option(this->implementation, option, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Set an option on the serial port.
+ /**
+ * This function is used to set an option on the serial port.
+ *
+ * @param option The option value to be set on the serial port.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa SettableSerialPortOption @n
+ * boost::asio::serial_port_base::baud_rate @n
+ * boost::asio::serial_port_base::flow_control @n
+ * boost::asio::serial_port_base::parity @n
+ * boost::asio::serial_port_base::stop_bits @n
+ * boost::asio::serial_port_base::character_size
+ */
+ template <typename SettableSerialPortOption>
+ boost::system::error_code set_option(const SettableSerialPortOption& option,
+ boost::system::error_code& ec)
+ {
+ return this->service.set_option(this->implementation, option, ec);
+ }
+
+ /// Get an option from the serial port.
+ /**
+ * This function is used to get the current value of an option on the serial
+ * port.
+ *
+ * @param option The option value to be obtained from the serial port.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa GettableSerialPortOption @n
+ * boost::asio::serial_port_base::baud_rate @n
+ * boost::asio::serial_port_base::flow_control @n
+ * boost::asio::serial_port_base::parity @n
+ * boost::asio::serial_port_base::stop_bits @n
+ * boost::asio::serial_port_base::character_size
+ */
+ template <typename GettableSerialPortOption>
+ void get_option(GettableSerialPortOption& option)
+ {
+ boost::system::error_code ec;
+ this->service.get_option(this->implementation, option, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Get an option from the serial port.
+ /**
+ * This function is used to get the current value of an option on the serial
+ * port.
+ *
+ * @param option The option value to be obtained from the serial port.
+ *
+ * @param ec Set to indicate what error occured, if any.
+ *
+ * @sa GettableSerialPortOption @n
+ * boost::asio::serial_port_base::baud_rate @n
+ * boost::asio::serial_port_base::flow_control @n
+ * boost::asio::serial_port_base::parity @n
+ * boost::asio::serial_port_base::stop_bits @n
+ * boost::asio::serial_port_base::character_size
+ */
+ template <typename GettableSerialPortOption>
+ boost::system::error_code get_option(GettableSerialPortOption& option,
+ boost::system::error_code& ec)
+ {
+ return this->service.get_option(this->implementation, option, ec);
+ }
+
+ /// Write some data to the serial port.
+ /**
+ * This function is used to write data to the serial port. The function call
+ * will block until one or more bytes of the data has been written
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more data buffers to be written to the serial port.
+ *
+ * @returns The number of bytes written.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The write_some operation may not transmit all of the data to the
+ * peer. Consider using the @ref write function if you need to ensure that
+ * all data is written before the blocking operation completes.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * serial_port.write_some(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.write_some(this->implementation, buffers, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Write some data to the serial port.
+ /**
+ * This function is used to write data to the serial port. The function call
+ * will block until one or more bytes of the data has been written
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more data buffers to be written to the serial port.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes written. Returns 0 if an error occurred.
+ *
+ * @note The write_some operation may not transmit all of the data to the
+ * peer. Consider using the @ref write function if you need to ensure that
+ * all data is written before the blocking operation completes.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return this->service.write_some(this->implementation, buffers, ec);
+ }
+
+ /// Start an asynchronous write.
+ /**
+ * This function is used to asynchronously write data to the serial port.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be written to the serial port.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes written.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The write operation may not transmit all of the data to the peer.
+ * Consider using the @ref async_write function if you need to ensure that all
+ * data is written before the asynchronous operation completes.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * serial_port.async_write_some(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_write_some(const ConstBufferSequence& buffers,
+ WriteHandler handler)
+ {
+ this->service.async_write_some(this->implementation, buffers, handler);
+ }
+
+ /// Read some data from the serial port.
+ /**
+ * This function is used to read data from the serial port. The function
+ * call will block until one or more bytes of data has been read successfully,
+ * or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ *
+ * @returns The number of bytes read.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The read_some operation may not read all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that
+ * the requested amount of data is read before the blocking operation
+ * completes.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code
+ * serial_port.read_some(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.read_some(this->implementation, buffers, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Read some data from the serial port.
+ /**
+ * This function is used to read data from the serial port. The function
+ * call will block until one or more bytes of data has been read successfully,
+ * or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes read. Returns 0 if an error occurred.
+ *
+ * @note The read_some operation may not read all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that
+ * the requested amount of data is read before the blocking operation
+ * completes.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return this->service.read_some(this->implementation, buffers, ec);
+ }
+
+ /// Start an asynchronous read.
+ /**
+ * This function is used to asynchronously read data from the serial port.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes read.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The read operation may not read all of the requested number of bytes.
+ * Consider using the @ref async_read function if you need to ensure that the
+ * requested amount of data is read before the asynchronous operation
+ * completes.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code
+ * serial_port.async_read_some(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_read_some(const MutableBufferSequence& buffers,
+ ReadHandler handler)
+ {
+ this->service.async_read_some(this->implementation, buffers, handler);
+ }
+};
+
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_SERIAL_PORT_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/basic_socket.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/basic_socket.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,1051 @@
+//
+// basic_socket.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BASIC_SOCKET_HPP
+#define BOOST_ASIO_BASIC_SOCKET_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Provides socket functionality.
+/**
+ * The basic_socket class template provides functionality that is common to both
+ * stream-oriented and datagram-oriented sockets.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename Protocol, typename SocketService>
+class basic_socket
+ : public basic_io_object<SocketService>,
+ public socket_base
+{
+public:
+ /// The native representation of a socket.
+ typedef typename SocketService::native_type native_type;
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ /// A basic_socket is always the lowest layer.
+ typedef basic_socket<Protocol, SocketService> lowest_layer_type;
+
+ /// Construct a basic_socket without opening it.
+ /**
+ * This constructor creates a socket without opening it.
+ *
+ * @param io_service The io_service object that the socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ */
+ explicit basic_socket(boost::asio::io_service& io_service)
+ : basic_io_object<SocketService>(io_service)
+ {
+ }
+
+ /// Construct and open a basic_socket.
+ /**
+ * This constructor creates and opens a socket.
+ *
+ * @param io_service The io_service object that the socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket(boost::asio::io_service& io_service,
+ const protocol_type& protocol)
+ : basic_io_object<SocketService>(io_service)
+ {
+ boost::system::error_code ec;
+ this->service.open(this->implementation, protocol, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Construct a basic_socket, opening it and binding it to the given local
+ /// endpoint.
+ /**
+ * This constructor creates a socket and automatically opens it bound to the
+ * specified endpoint on the local machine. The protocol used is the protocol
+ * associated with the given endpoint.
+ *
+ * @param io_service The io_service object that the socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket will
+ * be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket(boost::asio::io_service& io_service,
+ const endpoint_type& endpoint)
+ : basic_io_object<SocketService>(io_service)
+ {
+ boost::system::error_code ec;
+ this->service.open(this->implementation, endpoint.protocol(), ec);
+ boost::asio::detail::throw_error(ec);
+ this->service.bind(this->implementation, endpoint, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Construct a basic_socket on an existing native socket.
+ /**
+ * This constructor creates a socket object to hold an existing native socket.
+ *
+ * @param io_service The io_service object that the socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_socket A native socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket(boost::asio::io_service& io_service,
+ const protocol_type& protocol, const native_type& native_socket)
+ : basic_io_object<SocketService>(io_service)
+ {
+ boost::system::error_code ec;
+ this->service.assign(this->implementation, protocol, native_socket, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Get a reference to the lowest layer.
+ /**
+ * This function returns a reference to the lowest layer in a stack of
+ * layers. Since a basic_socket cannot contain any further layers, it simply
+ * returns a reference to itself.
+ *
+ * @return A reference to the lowest layer in the stack of layers. Ownership
+ * is not transferred to the caller.
+ */
+ lowest_layer_type& lowest_layer()
+ {
+ return *this;
+ }
+
+ /// Open the socket using the specified protocol.
+ /**
+ * This function opens the socket so that it will use the specified protocol.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * socket.open(boost::asio::ip::tcp::v4());
+ * @endcode
+ */
+ void open(const protocol_type& protocol = protocol_type())
+ {
+ boost::system::error_code ec;
+ this->service.open(this->implementation, protocol, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Open the socket using the specified protocol.
+ /**
+ * This function opens the socket so that it will use the specified protocol.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::system::error_code ec;
+ * socket.open(boost::asio::ip::tcp::v4(), ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ boost::system::error_code open(const protocol_type& protocol,
+ boost::system::error_code& ec)
+ {
+ return this->service.open(this->implementation, protocol, ec);
+ }
+
+ /// Assign an existing native socket to the socket.
+ /*
+ * This function opens the socket to hold an existing native socket.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param native_socket A native socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void assign(const protocol_type& protocol, const native_type& native_socket)
+ {
+ boost::system::error_code ec;
+ this->service.assign(this->implementation, protocol, native_socket, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Assign an existing native socket to the socket.
+ /*
+ * This function opens the socket to hold an existing native socket.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param native_socket A native socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code assign(const protocol_type& protocol,
+ const native_type& native_socket, boost::system::error_code& ec)
+ {
+ return this->service.assign(this->implementation,
+ protocol, native_socket, ec);
+ }
+
+ /// Determine whether the socket is open.
+ bool is_open() const
+ {
+ return this->service.is_open(this->implementation);
+ }
+
+ /// Close the socket.
+ /**
+ * This function is used to close the socket. Any asynchronous send, receive
+ * or connect operations will be cancelled immediately, and will complete
+ * with the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note For portable behaviour with respect to graceful closure of a
+ * connected socket, call shutdown() before closing the socket.
+ */
+ void close()
+ {
+ boost::system::error_code ec;
+ this->service.close(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Close the socket.
+ /**
+ * This function is used to close the socket. Any asynchronous send, receive
+ * or connect operations will be cancelled immediately, and will complete
+ * with the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::system::error_code ec;
+ * socket.close(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ *
+ * @note For portable behaviour with respect to graceful closure of a
+ * connected socket, call shutdown() before closing the socket.
+ */
+ boost::system::error_code close(boost::system::error_code& ec)
+ {
+ return this->service.close(this->implementation, ec);
+ }
+
+ /// Get the native socket representation.
+ /**
+ * This function may be used to obtain the underlying representation of the
+ * socket. This is intended to allow access to native socket functionality
+ * that is not otherwise provided.
+ */
+ native_type native()
+ {
+ return this->service.native(this->implementation);
+ }
+
+ /// Cancel all asynchronous operations associated with the socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note Calls to cancel() will always fail with
+ * boost::asio::error::operation_not_supported when run on Windows XP, Windows
+ * Server 2003, and earlier versions of Windows, unless
+ * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
+ * two issues that should be considered before enabling its use:
+ *
+ * @li It will only cancel asynchronous operations that were initiated in the
+ * current thread.
+ *
+ * @li It can appear to complete without error, but the request to cancel the
+ * unfinished operations may be silently ignored by the operating system.
+ * Whether it works or not seems to depend on the drivers that are installed.
+ *
+ * For portable cancellation, consider using one of the following
+ * alternatives:
+ *
+ * @li Disable asio's I/O completion port backend by defining
+ * BOOST_ASIO_DISABLE_IOCP.
+ *
+ * @li Use the close() function to simultaneously cancel the outstanding
+ * operations and close the socket.
+ *
+ * When running on Windows Vista, Windows Server 2008, and later, the
+ * CancelIoEx function is always used. This function does not have the
+ * problems described above.
+ */
+#if defined(BOOST_MSVC) && (BOOST_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
+ && !defined(BOOST_ASIO_ENABLE_CANCELIO)
+ __declspec(deprecated("By default, this function always fails with "
+ "operation_not_supported when used on Windows XP, Windows Server 2003, "
+ "or earlier. Consult documentation for details."))
+#endif
+ void cancel()
+ {
+ boost::system::error_code ec;
+ this->service.cancel(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Cancel all asynchronous operations associated with the socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note Calls to cancel() will always fail with
+ * boost::asio::error::operation_not_supported when run on Windows XP, Windows
+ * Server 2003, and earlier versions of Windows, unless
+ * BOOST_ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has
+ * two issues that should be considered before enabling its use:
+ *
+ * @li It will only cancel asynchronous operations that were initiated in the
+ * current thread.
+ *
+ * @li It can appear to complete without error, but the request to cancel the
+ * unfinished operations may be silently ignored by the operating system.
+ * Whether it works or not seems to depend on the drivers that are installed.
+ *
+ * For portable cancellation, consider using one of the following
+ * alternatives:
+ *
+ * @li Disable asio's I/O completion port backend by defining
+ * BOOST_ASIO_DISABLE_IOCP.
+ *
+ * @li Use the close() function to simultaneously cancel the outstanding
+ * operations and close the socket.
+ *
+ * When running on Windows Vista, Windows Server 2008, and later, the
+ * CancelIoEx function is always used. This function does not have the
+ * problems described above.
+ */
+#if defined(BOOST_MSVC) && (BOOST_MSVC >= 1400) \
+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \
+ && !defined(BOOST_ASIO_ENABLE_CANCELIO)
+ __declspec(deprecated("By default, this function always fails with "
+ "operation_not_supported when used on Windows XP, Windows Server 2003, "
+ "or earlier. Consult documentation for details."))
+#endif
+ boost::system::error_code cancel(boost::system::error_code& ec)
+ {
+ return this->service.cancel(this->implementation, ec);
+ }
+
+ /// Determine whether the socket is at the out-of-band data mark.
+ /**
+ * This function is used to check whether the socket input is currently
+ * positioned at the out-of-band data mark.
+ *
+ * @return A bool indicating whether the socket is at the out-of-band data
+ * mark.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ bool at_mark() const
+ {
+ boost::system::error_code ec;
+ bool b = this->service.at_mark(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ return b;
+ }
+
+ /// Determine whether the socket is at the out-of-band data mark.
+ /**
+ * This function is used to check whether the socket input is currently
+ * positioned at the out-of-band data mark.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return A bool indicating whether the socket is at the out-of-band data
+ * mark.
+ */
+ bool at_mark(boost::system::error_code& ec) const
+ {
+ return this->service.at_mark(this->implementation, ec);
+ }
+
+ /// Determine the number of bytes available for reading.
+ /**
+ * This function is used to determine the number of bytes that may be read
+ * without blocking.
+ *
+ * @return The number of bytes that may be read without blocking, or 0 if an
+ * error occurs.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ std::size_t available() const
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.available(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Determine the number of bytes available for reading.
+ /**
+ * This function is used to determine the number of bytes that may be read
+ * without blocking.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return The number of bytes that may be read without blocking, or 0 if an
+ * error occurs.
+ */
+ std::size_t available(boost::system::error_code& ec) const
+ {
+ return this->service.available(this->implementation, ec);
+ }
+
+ /// Bind the socket to the given local endpoint.
+ /**
+ * This function binds the socket to the specified endpoint on the local
+ * machine.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket will
+ * be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * socket.open(boost::asio::ip::tcp::v4());
+ * socket.bind(boost::asio::ip::tcp::endpoint(
+ * boost::asio::ip::tcp::v4(), 12345));
+ * @endcode
+ */
+ void bind(const endpoint_type& endpoint)
+ {
+ boost::system::error_code ec;
+ this->service.bind(this->implementation, endpoint, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Bind the socket to the given local endpoint.
+ /**
+ * This function binds the socket to the specified endpoint on the local
+ * machine.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket will
+ * be bound.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * socket.open(boost::asio::ip::tcp::v4());
+ * boost::system::error_code ec;
+ * socket.bind(boost::asio::ip::tcp::endpoint(
+ * boost::asio::ip::tcp::v4(), 12345), ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ boost::system::error_code bind(const endpoint_type& endpoint,
+ boost::system::error_code& ec)
+ {
+ return this->service.bind(this->implementation, endpoint, ec);
+ }
+
+ /// Connect the socket to the specified endpoint.
+ /**
+ * This function is used to connect a socket to the specified remote endpoint.
+ * The function call will block until the connection is successfully made or
+ * an error occurs.
+ *
+ * The socket is automatically opened if it is not already open. If the
+ * connect fails, and the socket was automatically opened, the socket is
+ * returned to the closed state.
+ *
+ * @param peer_endpoint The remote endpoint to which the socket will be
+ * connected.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::endpoint endpoint(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.connect(endpoint);
+ * @endcode
+ */
+ void connect(const endpoint_type& peer_endpoint)
+ {
+ boost::system::error_code ec;
+ if (!is_open())
+ {
+ this->service.open(this->implementation, peer_endpoint.protocol(), ec);
+ boost::asio::detail::throw_error(ec);
+ }
+ this->service.connect(this->implementation, peer_endpoint, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Connect the socket to the specified endpoint.
+ /**
+ * This function is used to connect a socket to the specified remote endpoint.
+ * The function call will block until the connection is successfully made or
+ * an error occurs.
+ *
+ * The socket is automatically opened if it is not already open. If the
+ * connect fails, and the socket was automatically opened, the socket is
+ * returned to the closed state.
+ *
+ * @param peer_endpoint The remote endpoint to which the socket will be
+ * connected.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::endpoint endpoint(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * boost::system::error_code ec;
+ * socket.connect(endpoint, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ boost::system::error_code connect(const endpoint_type& peer_endpoint,
+ boost::system::error_code& ec)
+ {
+ if (!is_open())
+ {
+ if (this->service.open(this->implementation,
+ peer_endpoint.protocol(), ec))
+ {
+ return ec;
+ }
+ }
+
+ return this->service.connect(this->implementation, peer_endpoint, ec);
+ }
+
+ /// Start an asynchronous connect.
+ /**
+ * This function is used to asynchronously connect a socket to the specified
+ * remote endpoint. The function call always returns immediately.
+ *
+ * The socket is automatically opened if it is not already open. If the
+ * connect fails, and the socket was automatically opened, the socket is
+ * returned to the closed state.
+ *
+ * @param peer_endpoint The remote endpoint to which the socket will be
+ * connected. Copies will be made of the endpoint object as required.
+ *
+ * @param handler The handler to be called when the connection operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * @code
+ * void connect_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Connect succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::endpoint endpoint(
+ * boost::asio::ip::address::from_string("1.2.3.4"), 12345);
+ * socket.async_connect(endpoint, connect_handler);
+ * @endcode
+ */
+ template <typename ConnectHandler>
+ void async_connect(const endpoint_type& peer_endpoint, ConnectHandler handler)
+ {
+ if (!is_open())
+ {
+ boost::system::error_code ec;
+ if (this->service.open(this->implementation,
+ peer_endpoint.protocol(), ec))
+ {
+ this->get_io_service().post(
+ boost::asio::detail::bind_handler(handler, ec));
+ return;
+ }
+ }
+
+ this->service.async_connect(this->implementation, peer_endpoint, handler);
+ }
+
+ /// Set an option on the socket.
+ /**
+ * This function is used to set an option on the socket.
+ *
+ * @param option The new option value to be set on the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa SettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Setting the IPPROTO_TCP/TCP_NODELAY option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::tcp::no_delay option(true);
+ * socket.set_option(option);
+ * @endcode
+ */
+ template <typename SettableSocketOption>
+ void set_option(const SettableSocketOption& option)
+ {
+ boost::system::error_code ec;
+ this->service.set_option(this->implementation, option, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Set an option on the socket.
+ /**
+ * This function is used to set an option on the socket.
+ *
+ * @param option The new option value to be set on the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa SettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Setting the IPPROTO_TCP/TCP_NODELAY option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::tcp::no_delay option(true);
+ * boost::system::error_code ec;
+ * socket.set_option(option, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename SettableSocketOption>
+ boost::system::error_code set_option(const SettableSocketOption& option,
+ boost::system::error_code& ec)
+ {
+ return this->service.set_option(this->implementation, option, ec);
+ }
+
+ /// Get an option from the socket.
+ /**
+ * This function is used to get the current value of an option on the socket.
+ *
+ * @param option The option value to be obtained from the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa GettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::tcp::socket::keep_alive option;
+ * socket.get_option(option);
+ * bool is_set = option.get();
+ * @endcode
+ */
+ template <typename GettableSocketOption>
+ void get_option(GettableSocketOption& option) const
+ {
+ boost::system::error_code ec;
+ this->service.get_option(this->implementation, option, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Get an option from the socket.
+ /**
+ * This function is used to get the current value of an option on the socket.
+ *
+ * @param option The option value to be obtained from the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa GettableSocketOption @n
+ * boost::asio::socket_base::broadcast @n
+ * boost::asio::socket_base::do_not_route @n
+ * boost::asio::socket_base::keep_alive @n
+ * boost::asio::socket_base::linger @n
+ * boost::asio::socket_base::receive_buffer_size @n
+ * boost::asio::socket_base::receive_low_watermark @n
+ * boost::asio::socket_base::reuse_address @n
+ * boost::asio::socket_base::send_buffer_size @n
+ * boost::asio::socket_base::send_low_watermark @n
+ * boost::asio::ip::multicast::join_group @n
+ * boost::asio::ip::multicast::leave_group @n
+ * boost::asio::ip::multicast::enable_loopback @n
+ * boost::asio::ip::multicast::outbound_interface @n
+ * boost::asio::ip::multicast::hops @n
+ * boost::asio::ip::tcp::no_delay
+ *
+ * @par Example
+ * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::tcp::socket::keep_alive option;
+ * boost::system::error_code ec;
+ * socket.get_option(option, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * bool is_set = option.get();
+ * @endcode
+ */
+ template <typename GettableSocketOption>
+ boost::system::error_code get_option(GettableSocketOption& option,
+ boost::system::error_code& ec) const
+ {
+ return this->service.get_option(this->implementation, option, ec);
+ }
+
+ /// Perform an IO control command on the socket.
+ /**
+ * This function is used to execute an IO control command on the socket.
+ *
+ * @param command The IO control command to be performed on the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::socket_base::bytes_readable @n
+ * boost::asio::socket_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::tcp::socket::bytes_readable command;
+ * socket.io_control(command);
+ * std::size_t bytes_readable = command.get();
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ void io_control(IoControlCommand& command)
+ {
+ boost::system::error_code ec;
+ this->service.io_control(this->implementation, command, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Perform an IO control command on the socket.
+ /**
+ * This function is used to execute an IO control command on the socket.
+ *
+ * @param command The IO control command to be performed on the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::socket_base::bytes_readable @n
+ * boost::asio::socket_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::tcp::socket::bytes_readable command;
+ * boost::system::error_code ec;
+ * socket.io_control(command, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * std::size_t bytes_readable = command.get();
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ boost::system::error_code io_control(IoControlCommand& command,
+ boost::system::error_code& ec)
+ {
+ return this->service.io_control(this->implementation, command, ec);
+ }
+
+ /// Get the local endpoint of the socket.
+ /**
+ * This function is used to obtain the locally bound endpoint of the socket.
+ *
+ * @returns An object that represents the local endpoint of the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint();
+ * @endcode
+ */
+ endpoint_type local_endpoint() const
+ {
+ boost::system::error_code ec;
+ endpoint_type ep = this->service.local_endpoint(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ return ep;
+ }
+
+ /// Get the local endpoint of the socket.
+ /**
+ * This function is used to obtain the locally bound endpoint of the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns An object that represents the local endpoint of the socket.
+ * Returns a default-constructed endpoint object if an error occurred.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::system::error_code ec;
+ * boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ endpoint_type local_endpoint(boost::system::error_code& ec) const
+ {
+ return this->service.local_endpoint(this->implementation, ec);
+ }
+
+ /// Get the remote endpoint of the socket.
+ /**
+ * This function is used to obtain the remote endpoint of the socket.
+ *
+ * @returns An object that represents the remote endpoint of the socket.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint();
+ * @endcode
+ */
+ endpoint_type remote_endpoint() const
+ {
+ boost::system::error_code ec;
+ endpoint_type ep = this->service.remote_endpoint(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ return ep;
+ }
+
+ /// Get the remote endpoint of the socket.
+ /**
+ * This function is used to obtain the remote endpoint of the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns An object that represents the remote endpoint of the socket.
+ * Returns a default-constructed endpoint object if an error occurred.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::system::error_code ec;
+ * boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ endpoint_type remote_endpoint(boost::system::error_code& ec) const
+ {
+ return this->service.remote_endpoint(this->implementation, ec);
+ }
+
+ /// Disable sends or receives on the socket.
+ /**
+ * This function is used to disable send operations, receive operations, or
+ * both.
+ *
+ * @param what Determines what types of operation will no longer be allowed.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * Shutting down the send side of the socket:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send);
+ * @endcode
+ */
+ void shutdown(shutdown_type what)
+ {
+ boost::system::error_code ec;
+ this->service.shutdown(this->implementation, what, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Disable sends or receives on the socket.
+ /**
+ * This function is used to disable send operations, receive operations, or
+ * both.
+ *
+ * @param what Determines what types of operation will no longer be allowed.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * Shutting down the send side of the socket:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::system::error_code ec;
+ * socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ boost::system::error_code shutdown(shutdown_type what,
+ boost::system::error_code& ec)
+ {
+ return this->service.shutdown(this->implementation, what, ec);
+ }
+
+protected:
+ /// Protected destructor to prevent deletion through this type.
+ ~basic_socket()
+ {
+ }
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_SOCKET_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/basic_socket_acceptor.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/basic_socket_acceptor.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,826 @@
+//
+// basic_socket_acceptor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_HPP
+#define BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/basic_socket.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/socket_acceptor_service.hpp>
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Provides the ability to accept new connections.
+/**
+ * The basic_socket_acceptor class template is used for accepting new socket
+ * connections.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Example
+ * Opening a socket acceptor with the SO_REUSEADDR option enabled:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
+ * acceptor.open(endpoint.protocol());
+ * acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ * acceptor.bind(endpoint);
+ * acceptor.listen();
+ * @endcode
+ */
+template <typename Protocol,
+ typename SocketAcceptorService = socket_acceptor_service<Protocol> >
+class basic_socket_acceptor
+ : public basic_io_object<SocketAcceptorService>,
+ public socket_base
+{
+public:
+ /// The native representation of an acceptor.
+ typedef typename SocketAcceptorService::native_type native_type;
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ /// Construct an acceptor without opening it.
+ /**
+ * This constructor creates an acceptor without opening it to listen for new
+ * connections. The open() function must be called before the acceptor can
+ * accept new socket connections.
+ *
+ * @param io_service The io_service object that the acceptor will use to
+ * dispatch handlers for any asynchronous operations performed on the
+ * acceptor.
+ */
+ explicit basic_socket_acceptor(boost::asio::io_service& io_service)
+ : basic_io_object<SocketAcceptorService>(io_service)
+ {
+ }
+
+ /// Construct an open acceptor.
+ /**
+ * This constructor creates an acceptor and automatically opens it.
+ *
+ * @param io_service The io_service object that the acceptor will use to
+ * dispatch handlers for any asynchronous operations performed on the
+ * acceptor.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_acceptor(boost::asio::io_service& io_service,
+ const protocol_type& protocol)
+ : basic_io_object<SocketAcceptorService>(io_service)
+ {
+ boost::system::error_code ec;
+ this->service.open(this->implementation, protocol, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Construct an acceptor opened on the given endpoint.
+ /**
+ * This constructor creates an acceptor and automatically opens it to listen
+ * for new connections on the specified endpoint.
+ *
+ * @param io_service The io_service object that the acceptor will use to
+ * dispatch handlers for any asynchronous operations performed on the
+ * acceptor.
+ *
+ * @param endpoint An endpoint on the local machine on which the acceptor
+ * will listen for new connections.
+ *
+ * @param reuse_addr Whether the constructor should set the socket option
+ * socket_base::reuse_address.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This constructor is equivalent to the following code:
+ * @code
+ * basic_socket_acceptor<Protocol> acceptor(io_service);
+ * acceptor.open(endpoint.protocol());
+ * if (reuse_addr)
+ * acceptor.set_option(socket_base::reuse_address(true));
+ * acceptor.bind(endpoint);
+ * acceptor.listen(listen_backlog);
+ * @endcode
+ */
+ basic_socket_acceptor(boost::asio::io_service& io_service,
+ const endpoint_type& endpoint, bool reuse_addr = true)
+ : basic_io_object<SocketAcceptorService>(io_service)
+ {
+ boost::system::error_code ec;
+ this->service.open(this->implementation, endpoint.protocol(), ec);
+ boost::asio::detail::throw_error(ec);
+ if (reuse_addr)
+ {
+ this->service.set_option(this->implementation,
+ socket_base::reuse_address(true), ec);
+ boost::asio::detail::throw_error(ec);
+ }
+ this->service.bind(this->implementation, endpoint, ec);
+ boost::asio::detail::throw_error(ec);
+ this->service.listen(this->implementation,
+ socket_base::max_connections, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Construct a basic_socket_acceptor on an existing native acceptor.
+ /**
+ * This constructor creates an acceptor object to hold an existing native
+ * acceptor.
+ *
+ * @param io_service The io_service object that the acceptor will use to
+ * dispatch handlers for any asynchronous operations performed on the
+ * acceptor.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_acceptor A native acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_socket_acceptor(boost::asio::io_service& io_service,
+ const protocol_type& protocol, const native_type& native_acceptor)
+ : basic_io_object<SocketAcceptorService>(io_service)
+ {
+ boost::system::error_code ec;
+ this->service.assign(this->implementation, protocol, native_acceptor, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Open the acceptor using the specified protocol.
+ /**
+ * This function opens the socket acceptor so that it will use the specified
+ * protocol.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * acceptor.open(boost::asio::ip::tcp::v4());
+ * @endcode
+ */
+ void open(const protocol_type& protocol = protocol_type())
+ {
+ boost::system::error_code ec;
+ this->service.open(this->implementation, protocol, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Open the acceptor using the specified protocol.
+ /**
+ * This function opens the socket acceptor so that it will use the specified
+ * protocol.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::system::error_code ec;
+ * acceptor.open(boost::asio::ip::tcp::v4(), ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ boost::system::error_code open(const protocol_type& protocol,
+ boost::system::error_code& ec)
+ {
+ return this->service.open(this->implementation, protocol, ec);
+ }
+
+ /// Assigns an existing native acceptor to the acceptor.
+ /*
+ * This function opens the acceptor to hold an existing native acceptor.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param native_acceptor A native acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void assign(const protocol_type& protocol, const native_type& native_acceptor)
+ {
+ boost::system::error_code ec;
+ this->service.assign(this->implementation, protocol, native_acceptor, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Assigns an existing native acceptor to the acceptor.
+ /*
+ * This function opens the acceptor to hold an existing native acceptor.
+ *
+ * @param protocol An object specifying which protocol is to be used.
+ *
+ * @param native_acceptor A native acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code assign(const protocol_type& protocol,
+ const native_type& native_acceptor, boost::system::error_code& ec)
+ {
+ return this->service.assign(this->implementation,
+ protocol, native_acceptor, ec);
+ }
+
+ /// Determine whether the acceptor is open.
+ bool is_open() const
+ {
+ return this->service.is_open(this->implementation);
+ }
+
+ /// Bind the acceptor to the given local endpoint.
+ /**
+ * This function binds the socket acceptor to the specified endpoint on the
+ * local machine.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket
+ * acceptor will be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * acceptor.open(boost::asio::ip::tcp::v4());
+ * acceptor.bind(boost::asio::ip::tcp::endpoint(12345));
+ * @endcode
+ */
+ void bind(const endpoint_type& endpoint)
+ {
+ boost::system::error_code ec;
+ this->service.bind(this->implementation, endpoint, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Bind the acceptor to the given local endpoint.
+ /**
+ * This function binds the socket acceptor to the specified endpoint on the
+ * local machine.
+ *
+ * @param endpoint An endpoint on the local machine to which the socket
+ * acceptor will be bound.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * acceptor.open(boost::asio::ip::tcp::v4());
+ * boost::system::error_code ec;
+ * acceptor.bind(boost::asio::ip::tcp::endpoint(12345), ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ boost::system::error_code bind(const endpoint_type& endpoint,
+ boost::system::error_code& ec)
+ {
+ return this->service.bind(this->implementation, endpoint, ec);
+ }
+
+ /// Place the acceptor into the state where it will listen for new
+ /// connections.
+ /**
+ * This function puts the socket acceptor into the state where it may accept
+ * new connections.
+ *
+ * @param backlog The maximum length of the queue of pending connections.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void listen(int backlog = socket_base::max_connections)
+ {
+ boost::system::error_code ec;
+ this->service.listen(this->implementation, backlog, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Place the acceptor into the state where it will listen for new
+ /// connections.
+ /**
+ * This function puts the socket acceptor into the state where it may accept
+ * new connections.
+ *
+ * @param backlog The maximum length of the queue of pending connections.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::system::error_code ec;
+ * acceptor.listen(boost::asio::socket_base::max_connections, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ boost::system::error_code listen(int backlog, boost::system::error_code& ec)
+ {
+ return this->service.listen(this->implementation, backlog, ec);
+ }
+
+ /// Close the acceptor.
+ /**
+ * This function is used to close the acceptor. Any asynchronous accept
+ * operations will be cancelled immediately.
+ *
+ * A subsequent call to open() is required before the acceptor can again be
+ * used to again perform socket accept operations.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void close()
+ {
+ boost::system::error_code ec;
+ this->service.close(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Close the acceptor.
+ /**
+ * This function is used to close the acceptor. Any asynchronous accept
+ * operations will be cancelled immediately.
+ *
+ * A subsequent call to open() is required before the acceptor can again be
+ * used to again perform socket accept operations.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::system::error_code ec;
+ * acceptor.close(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ boost::system::error_code close(boost::system::error_code& ec)
+ {
+ return this->service.close(this->implementation, ec);
+ }
+
+ /// Get the native acceptor representation.
+ /**
+ * This function may be used to obtain the underlying representation of the
+ * acceptor. This is intended to allow access to native acceptor functionality
+ * that is not otherwise provided.
+ */
+ native_type native()
+ {
+ return this->service.native(this->implementation);
+ }
+
+ /// Cancel all asynchronous operations associated with the acceptor.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void cancel()
+ {
+ boost::system::error_code ec;
+ this->service.cancel(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Cancel all asynchronous operations associated with the acceptor.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code cancel(boost::system::error_code& ec)
+ {
+ return this->service.cancel(this->implementation, ec);
+ }
+
+ /// Set an option on the acceptor.
+ /**
+ * This function is used to set an option on the acceptor.
+ *
+ * @param option The new option value to be set on the acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa SettableSocketOption @n
+ * boost::asio::socket_base::reuse_address
+ * boost::asio::socket_base::enable_connection_aborted
+ *
+ * @par Example
+ * Setting the SOL_SOCKET/SO_REUSEADDR option:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::acceptor::reuse_address option(true);
+ * acceptor.set_option(option);
+ * @endcode
+ */
+ template <typename SettableSocketOption>
+ void set_option(const SettableSocketOption& option)
+ {
+ boost::system::error_code ec;
+ this->service.set_option(this->implementation, option, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Set an option on the acceptor.
+ /**
+ * This function is used to set an option on the acceptor.
+ *
+ * @param option The new option value to be set on the acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa SettableSocketOption @n
+ * boost::asio::socket_base::reuse_address
+ * boost::asio::socket_base::enable_connection_aborted
+ *
+ * @par Example
+ * Setting the SOL_SOCKET/SO_REUSEADDR option:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::acceptor::reuse_address option(true);
+ * boost::system::error_code ec;
+ * acceptor.set_option(option, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename SettableSocketOption>
+ boost::system::error_code set_option(const SettableSocketOption& option,
+ boost::system::error_code& ec)
+ {
+ return this->service.set_option(this->implementation, option, ec);
+ }
+
+ /// Get an option from the acceptor.
+ /**
+ * This function is used to get the current value of an option on the
+ * acceptor.
+ *
+ * @param option The option value to be obtained from the acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa GettableSocketOption @n
+ * boost::asio::socket_base::reuse_address
+ *
+ * @par Example
+ * Getting the value of the SOL_SOCKET/SO_REUSEADDR option:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::acceptor::reuse_address option;
+ * acceptor.get_option(option);
+ * bool is_set = option.get();
+ * @endcode
+ */
+ template <typename GettableSocketOption>
+ void get_option(GettableSocketOption& option)
+ {
+ boost::system::error_code ec;
+ this->service.get_option(this->implementation, option, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Get an option from the acceptor.
+ /**
+ * This function is used to get the current value of an option on the
+ * acceptor.
+ *
+ * @param option The option value to be obtained from the acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa GettableSocketOption @n
+ * boost::asio::socket_base::reuse_address
+ *
+ * @par Example
+ * Getting the value of the SOL_SOCKET/SO_REUSEADDR option:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::acceptor::reuse_address option;
+ * boost::system::error_code ec;
+ * acceptor.get_option(option, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * bool is_set = option.get();
+ * @endcode
+ */
+ template <typename GettableSocketOption>
+ boost::system::error_code get_option(GettableSocketOption& option,
+ boost::system::error_code& ec)
+ {
+ return this->service.get_option(this->implementation, option, ec);
+ }
+
+ /// Get the local endpoint of the acceptor.
+ /**
+ * This function is used to obtain the locally bound endpoint of the acceptor.
+ *
+ * @returns An object that represents the local endpoint of the acceptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint();
+ * @endcode
+ */
+ endpoint_type local_endpoint() const
+ {
+ boost::system::error_code ec;
+ endpoint_type ep = this->service.local_endpoint(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ return ep;
+ }
+
+ /// Get the local endpoint of the acceptor.
+ /**
+ * This function is used to obtain the locally bound endpoint of the acceptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns An object that represents the local endpoint of the acceptor.
+ * Returns a default-constructed endpoint object if an error occurred and the
+ * error handler did not throw an exception.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::system::error_code ec;
+ * boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ endpoint_type local_endpoint(boost::system::error_code& ec) const
+ {
+ return this->service.local_endpoint(this->implementation, ec);
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer into the
+ * given socket. The function call will block until a new connection has been
+ * accepted successfully or an error occurs.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * acceptor.accept(socket);
+ * @endcode
+ */
+ template <typename SocketService>
+ void accept(basic_socket<protocol_type, SocketService>& peer)
+ {
+ boost::system::error_code ec;
+ this->service.accept(this->implementation, peer, 0, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer into the
+ * given socket. The function call will block until a new connection has been
+ * accepted successfully or an error occurs.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::soocket socket(io_service);
+ * boost::system::error_code ec;
+ * acceptor.accept(socket, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename SocketService>
+ boost::system::error_code accept(
+ basic_socket<protocol_type, SocketService>& peer,
+ boost::system::error_code& ec)
+ {
+ return this->service.accept(this->implementation, peer, 0, ec);
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection into a
+ * socket. The function call always returns immediately.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ * Ownership of the peer object is retained by the caller, which must
+ * guarantee that it is valid until the handler is called.
+ *
+ * @param handler The handler to be called when the accept operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * @code
+ * void accept_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Accept succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * acceptor.async_accept(socket, accept_handler);
+ * @endcode
+ */
+ template <typename SocketService, typename AcceptHandler>
+ void async_accept(basic_socket<protocol_type, SocketService>& peer,
+ AcceptHandler handler)
+ {
+ this->service.async_accept(this->implementation, peer, 0, handler);
+ }
+
+ /// Accept a new connection and obtain the endpoint of the peer
+ /**
+ * This function is used to accept a new connection from a peer into the
+ * given socket, and additionally provide the endpoint of the remote peer.
+ * The function call will block until a new connection has been accepted
+ * successfully or an error occurs.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ *
+ * @param peer_endpoint An endpoint object which will receive the endpoint of
+ * the remote peer.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * acceptor.accept(socket, endpoint);
+ * @endcode
+ */
+ template <typename SocketService>
+ void accept(basic_socket<protocol_type, SocketService>& peer,
+ endpoint_type& peer_endpoint)
+ {
+ boost::system::error_code ec;
+ this->service.accept(this->implementation, peer, &peer_endpoint, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Accept a new connection and obtain the endpoint of the peer
+ /**
+ * This function is used to accept a new connection from a peer into the
+ * given socket, and additionally provide the endpoint of the remote peer.
+ * The function call will block until a new connection has been accepted
+ * successfully or an error occurs.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ *
+ * @param peer_endpoint An endpoint object which will receive the endpoint of
+ * the remote peer.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * boost::system::error_code ec;
+ * acceptor.accept(socket, endpoint, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ template <typename SocketService>
+ boost::system::error_code accept(
+ basic_socket<protocol_type, SocketService>& peer,
+ endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ return this->service.accept(this->implementation, peer, &peer_endpoint, ec);
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection into a
+ * socket, and additionally obtain the endpoint of the remote peer. The
+ * function call always returns immediately.
+ *
+ * @param peer The socket into which the new connection will be accepted.
+ * Ownership of the peer object is retained by the caller, which must
+ * guarantee that it is valid until the handler is called.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written. Ownership of the peer_endpoint object is
+ * retained by the caller, which must guarantee that it is valid until the
+ * handler is called.
+ *
+ * @param handler The handler to be called when the accept operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ */
+ template <typename SocketService, typename AcceptHandler>
+ void async_accept(basic_socket<protocol_type, SocketService>& peer,
+ endpoint_type& peer_endpoint, AcceptHandler handler)
+ {
+ this->service.async_accept(this->implementation,
+ peer, &peer_endpoint, handler);
+ }
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/basic_socket_iostream.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/basic_socket_iostream.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,150 @@
+//
+// basic_socket_iostream.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BASIC_SOCKET_IOSTREAM_HPP
+#define BOOST_ASIO_BASIC_SOCKET_IOSTREAM_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/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 <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/basic_socket_streambuf.hpp>
+#include <boost/asio/stream_socket_service.hpp>
+
+#if !defined(BOOST_ASIO_SOCKET_IOSTREAM_MAX_ARITY)
+#define BOOST_ASIO_SOCKET_IOSTREAM_MAX_ARITY 5
+#endif // !defined(BOOST_ASIO_SOCKET_IOSTREAM_MAX_ARITY)
+
+// A macro that should expand to:
+// template <typename T1, ..., typename Tn>
+// explicit basic_socket_iostream(T1 x1, ..., Tn xn)
+// : basic_iostream<char>(&this->boost::base_from_member<
+// basic_socket_streambuf<Protocol, StreamSocketService> >::member)
+// {
+// if (rdbuf()->connect(x1, ..., xn) == 0)
+// this->setstate(std::ios_base::failbit);
+// }
+// This macro should only persist within this file.
+
+#define BOOST_ASIO_PRIVATE_CTR_DEF(z, n, data) \
+ template <BOOST_PP_ENUM_PARAMS(n, typename T)> \
+ explicit basic_socket_iostream(BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \
+ : std::basic_iostream<char>(&this->boost::base_from_member< \
+ basic_socket_streambuf<Protocol, StreamSocketService> >::member) \
+ { \
+ tie(this); \
+ if (rdbuf()->connect(BOOST_PP_ENUM_PARAMS(n, x)) == 0) \
+ this->setstate(std::ios_base::failbit); \
+ } \
+ /**/
+
+// A macro that should expand to:
+// template <typename T1, ..., typename Tn>
+// void connect(T1 x1, ..., Tn xn)
+// {
+// if (rdbuf()->connect(x1, ..., xn) == 0)
+// this->setstate(std::ios_base::failbit);
+// }
+// This macro should only persist within this file.
+
+#define BOOST_ASIO_PRIVATE_CONNECT_DEF(z, n, data) \
+ template <BOOST_PP_ENUM_PARAMS(n, typename T)> \
+ void connect(BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \
+ { \
+ if (rdbuf()->connect(BOOST_PP_ENUM_PARAMS(n, x)) == 0) \
+ this->setstate(std::ios_base::failbit); \
+ } \
+ /**/
+
+namespace boost {
+namespace asio {
+
+/// Iostream interface for a socket.
+template <typename Protocol,
+ typename StreamSocketService = stream_socket_service<Protocol> >
+class basic_socket_iostream
+ : public boost::base_from_member<
+ basic_socket_streambuf<Protocol, StreamSocketService> >,
+ public std::basic_iostream<char>
+{
+public:
+ /// Construct a basic_socket_iostream without establishing a connection.
+ basic_socket_iostream()
+ : std::basic_iostream<char>(&this->boost::base_from_member<
+ basic_socket_streambuf<Protocol, StreamSocketService> >::member)
+ {
+ tie(this);
+ }
+
+#if defined(GENERATING_DOCUMENTATION)
+ /// Establish a connection to an endpoint corresponding to a resolver query.
+ /**
+ * This constructor automatically establishes a connection based on the
+ * supplied resolver query parameters. The arguments are used to construct
+ * a resolver query object.
+ */
+ template <typename T1, ..., typename TN>
+ explicit basic_socket_iostream(T1 t1, ..., TN tn);
+#else
+ BOOST_PP_REPEAT_FROM_TO(
+ 1, BOOST_PP_INC(BOOST_ASIO_SOCKET_IOSTREAM_MAX_ARITY),
+ BOOST_ASIO_PRIVATE_CTR_DEF, _ )
+#endif
+
+#if defined(GENERATING_DOCUMENTATION)
+ /// Establish a connection to an endpoint corresponding to a resolver query.
+ /**
+ * This function automatically establishes a connection based on the supplied
+ * resolver query parameters. The arguments are used to construct a resolver
+ * query object.
+ */
+ template <typename T1, ..., typename TN>
+ void connect(T1 t1, ..., TN tn);
+#else
+ BOOST_PP_REPEAT_FROM_TO(
+ 1, BOOST_PP_INC(BOOST_ASIO_SOCKET_IOSTREAM_MAX_ARITY),
+ BOOST_ASIO_PRIVATE_CONNECT_DEF, _ )
+#endif
+
+ /// Close the connection.
+ void close()
+ {
+ if (rdbuf()->close() == 0)
+ this->setstate(std::ios_base::failbit);
+ }
+
+ /// Return a pointer to the underlying streambuf.
+ basic_socket_streambuf<Protocol, StreamSocketService>* rdbuf() const
+ {
+ return const_cast<basic_socket_streambuf<Protocol, StreamSocketService>*>(
+ &this->boost::base_from_member<
+ basic_socket_streambuf<Protocol, StreamSocketService> >::member);
+ }
+};
+
+} // namespace asio
+} // namespace boost
+
+#undef BOOST_ASIO_PRIVATE_CTR_DEF
+#undef BOOST_ASIO_PRIVATE_CONNECT_DEF
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_SOCKET_IOSTREAM_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/basic_socket_streambuf.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/basic_socket_streambuf.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,286 @@
+//
+// basic_socket_streambuf.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BASIC_SOCKET_STREAMBUF_HPP
+#define BOOST_ASIO_BASIC_SOCKET_STREAMBUF_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <streambuf>
+#include <boost/array.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 <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/basic_socket.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/stream_socket_service.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+#if !defined(BOOST_ASIO_SOCKET_STREAMBUF_MAX_ARITY)
+#define BOOST_ASIO_SOCKET_STREAMBUF_MAX_ARITY 5
+#endif // !defined(BOOST_ASIO_SOCKET_STREAMBUF_MAX_ARITY)
+
+// A macro that should expand to:
+// template <typename T1, ..., typename Tn>
+// basic_socket_streambuf<Protocol, StreamSocketService>* connect(
+// T1 x1, ..., Tn xn)
+// {
+// init_buffers();
+// boost::system::error_code ec;
+// this->basic_socket<Protocol, StreamSocketService>::close(ec);
+// typedef typename Protocol::resolver_query resolver_query;
+// resolver_query query(x1, ..., xn);
+// resolve_and_connect(query, ec);
+// return !ec ? this : 0;
+// }
+// This macro should only persist within this file.
+
+#define BOOST_ASIO_PRIVATE_CONNECT_DEF( z, n, data ) \
+ template <BOOST_PP_ENUM_PARAMS(n, typename T)> \
+ basic_socket_streambuf<Protocol, StreamSocketService>* connect( \
+ BOOST_PP_ENUM_BINARY_PARAMS(n, T, x)) \
+ { \
+ init_buffers(); \
+ boost::system::error_code ec; \
+ this->basic_socket<Protocol, StreamSocketService>::close(ec); \
+ typedef typename Protocol::resolver_query resolver_query; \
+ resolver_query query(BOOST_PP_ENUM_PARAMS(n, x)); \
+ resolve_and_connect(query, ec); \
+ return !ec ? this : 0; \
+ } \
+ /**/
+
+namespace boost {
+namespace asio {
+
+/// Iostream streambuf for a socket.
+template <typename Protocol,
+ typename StreamSocketService = stream_socket_service<Protocol> >
+class basic_socket_streambuf
+ : public std::streambuf,
+ private boost::base_from_member<io_service>,
+ public basic_socket<Protocol, StreamSocketService>
+{
+public:
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ /// Construct a basic_socket_streambuf without establishing a connection.
+ basic_socket_streambuf()
+ : basic_socket<Protocol, StreamSocketService>(
+ boost::base_from_member<boost::asio::io_service>::member),
+ unbuffered_(false)
+ {
+ init_buffers();
+ }
+
+ /// Destructor flushes buffered data.
+ virtual ~basic_socket_streambuf()
+ {
+ if (pptr() != pbase())
+ overflow(traits_type::eof());
+ }
+
+ /// Establish a connection.
+ /**
+ * This function establishes a connection to the specified endpoint.
+ *
+ * @return \c this if a connection was successfully established, a null
+ * pointer otherwise.
+ */
+ basic_socket_streambuf<Protocol, StreamSocketService>* connect(
+ const endpoint_type& endpoint)
+ {
+ init_buffers();
+ boost::system::error_code ec;
+ this->basic_socket<Protocol, StreamSocketService>::close(ec);
+ this->basic_socket<Protocol, StreamSocketService>::connect(endpoint, ec);
+ return !ec ? this : 0;
+ }
+
+#if defined(GENERATING_DOCUMENTATION)
+ /// Establish a connection.
+ /**
+ * This function automatically establishes a connection based on the supplied
+ * resolver query parameters. The arguments are used to construct a resolver
+ * query object.
+ *
+ * @return \c this if a connection was successfully established, a null
+ * pointer otherwise.
+ */
+ template <typename T1, ..., typename TN>
+ basic_socket_streambuf<Protocol, StreamSocketService>* connect(
+ T1 t1, ..., TN tn);
+#else
+ BOOST_PP_REPEAT_FROM_TO(
+ 1, BOOST_PP_INC(BOOST_ASIO_SOCKET_STREAMBUF_MAX_ARITY),
+ BOOST_ASIO_PRIVATE_CONNECT_DEF, _ )
+#endif
+
+ /// Close the connection.
+ /**
+ * @return \c this if a connection was successfully established, a null
+ * pointer otherwise.
+ */
+ basic_socket_streambuf<Protocol, StreamSocketService>* close()
+ {
+ boost::system::error_code ec;
+ sync();
+ this->basic_socket<Protocol, StreamSocketService>::close(ec);
+ if (!ec)
+ init_buffers();
+ return !ec ? this : 0;
+ }
+
+protected:
+ int_type underflow()
+ {
+ if (gptr() == egptr())
+ {
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = this->service.receive(
+ this->implementation,
+ boost::asio::buffer(boost::asio::buffer(get_buffer_) + putback_max),
+ 0, ec);
+ if (ec)
+ return traits_type::eof();
+ setg(get_buffer_.begin(), get_buffer_.begin() + putback_max,
+ get_buffer_.begin() + putback_max + bytes_transferred);
+ return traits_type::to_int_type(*gptr());
+ }
+ else
+ {
+ return traits_type::eof();
+ }
+ }
+
+ int_type overflow(int_type c)
+ {
+ if (unbuffered_)
+ {
+ if (traits_type::eq_int_type(c, traits_type::eof()))
+ {
+ // Nothing to do.
+ return traits_type::not_eof(c);
+ }
+ else
+ {
+ // Send the single character immediately.
+ boost::system::error_code ec;
+ char_type ch = traits_type::to_char_type(c);
+ this->service.send(this->implementation,
+ boost::asio::buffer(&ch, sizeof(char_type)), 0, ec);
+ if (ec)
+ return traits_type::eof();
+ return c;
+ }
+ }
+ else
+ {
+ // Send all data in the output buffer.
+ boost::asio::const_buffer buffer =
+ boost::asio::buffer(pbase(), pptr() - pbase());
+ while (boost::asio::buffer_size(buffer) > 0)
+ {
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = this->service.send(
+ this->implementation, boost::asio::buffer(buffer),
+ 0, ec);
+ if (ec)
+ return traits_type::eof();
+ buffer = buffer + bytes_transferred;
+ }
+ setp(put_buffer_.begin(), put_buffer_.end());
+
+ // If the new character is eof then our work here is done.
+ if (traits_type::eq_int_type(c, traits_type::eof()))
+ return traits_type::not_eof(c);
+
+ // Add the new character to the output buffer.
+ *pptr() = traits_type::to_char_type(c);
+ pbump(1);
+ return c;
+ }
+ }
+
+ int sync()
+ {
+ return overflow(traits_type::eof());
+ }
+
+ std::streambuf* setbuf(char_type* s, std::streamsize n)
+ {
+ if (pptr() == pbase() && s == 0 && n == 0)
+ {
+ unbuffered_ = true;
+ setp(0, 0);
+ return this;
+ }
+
+ return 0;
+ }
+
+private:
+ void init_buffers()
+ {
+ setg(get_buffer_.begin(),
+ get_buffer_.begin() + putback_max,
+ get_buffer_.begin() + putback_max);
+ if (unbuffered_)
+ setp(0, 0);
+ else
+ setp(put_buffer_.begin(), put_buffer_.end());
+ }
+
+ void resolve_and_connect(const typename Protocol::resolver_query& query,
+ boost::system::error_code& ec)
+ {
+ typedef typename Protocol::resolver resolver_type;
+ typedef typename Protocol::resolver_iterator iterator_type;
+ resolver_type resolver(
+ boost::base_from_member<boost::asio::io_service>::member);
+ iterator_type i = resolver.resolve(query, ec);
+ if (!ec)
+ {
+ iterator_type end;
+ ec = boost::asio::error::host_not_found;
+ while (ec && i != end)
+ {
+ this->basic_socket<Protocol, StreamSocketService>::close();
+ this->basic_socket<Protocol, StreamSocketService>::connect(*i, ec);
+ ++i;
+ }
+ }
+ }
+
+ enum { putback_max = 8 };
+ enum { buffer_size = 512 };
+ boost::array<char, buffer_size> get_buffer_;
+ boost::array<char, buffer_size> put_buffer_;
+ bool unbuffered_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#undef BOOST_ASIO_PRIVATE_CONNECT_DEF
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_SOCKET_STREAMBUF_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/basic_stream_socket.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/basic_stream_socket.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,720 @@
+//
+// basic_stream_socket.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BASIC_STREAM_SOCKET_HPP
+#define BOOST_ASIO_BASIC_STREAM_SOCKET_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/basic_socket.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/stream_socket_service.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Provides stream-oriented socket functionality.
+/**
+ * The basic_stream_socket class template provides asynchronous and blocking
+ * stream-oriented socket functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Concepts:
+ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
+ */
+template <typename Protocol,
+ typename StreamSocketService = stream_socket_service<Protocol> >
+class basic_stream_socket
+ : public basic_socket<Protocol, StreamSocketService>
+{
+public:
+ /// The native representation of a socket.
+ typedef typename StreamSocketService::native_type native_type;
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ /// Construct a basic_stream_socket without opening it.
+ /**
+ * This constructor creates a stream socket without opening it. The socket
+ * needs to be opened and then connected or accepted before data can be sent
+ * or received on it.
+ *
+ * @param io_service The io_service object that the stream socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ */
+ explicit basic_stream_socket(boost::asio::io_service& io_service)
+ : basic_socket<Protocol, StreamSocketService>(io_service)
+ {
+ }
+
+ /// Construct and open a basic_stream_socket.
+ /**
+ * This constructor creates and opens a stream socket. The socket needs to be
+ * connected or accepted before data can be sent or received on it.
+ *
+ * @param io_service The io_service object that the stream socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_stream_socket(boost::asio::io_service& io_service,
+ const protocol_type& protocol)
+ : basic_socket<Protocol, StreamSocketService>(io_service, protocol)
+ {
+ }
+
+ /// Construct a basic_stream_socket, opening it and binding it to the given
+ /// local endpoint.
+ /**
+ * This constructor creates a stream socket and automatically opens it bound
+ * to the specified endpoint on the local machine. The protocol used is the
+ * protocol associated with the given endpoint.
+ *
+ * @param io_service The io_service object that the stream socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param endpoint An endpoint on the local machine to which the stream
+ * socket will be bound.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_stream_socket(boost::asio::io_service& io_service,
+ const endpoint_type& endpoint)
+ : basic_socket<Protocol, StreamSocketService>(io_service, endpoint)
+ {
+ }
+
+ /// Construct a basic_stream_socket on an existing native socket.
+ /**
+ * This constructor creates a stream socket object to hold an existing native
+ * socket.
+ *
+ * @param io_service The io_service object that the stream socket will use to
+ * dispatch handlers for any asynchronous operations performed on the socket.
+ *
+ * @param protocol An object specifying protocol parameters to be used.
+ *
+ * @param native_socket The new underlying socket implementation.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_stream_socket(boost::asio::io_service& io_service,
+ const protocol_type& protocol, const native_type& native_socket)
+ : basic_socket<Protocol, StreamSocketService>(
+ io_service, protocol, native_socket)
+ {
+ }
+
+ /// Send some data on the socket.
+ /**
+ * This function is used to send data on the stream socket. The function
+ * call will block until one or more bytes of the data has been sent
+ * successfully, or an until error occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref write function if you need to ensure that all data
+ * is written before the blocking operation completes.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.send(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.send(
+ this->implementation, buffers, 0, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Send some data on the socket.
+ /**
+ * This function is used to send data on the stream socket. The function
+ * call will block until one or more bytes of the data has been sent
+ * successfully, or an until error occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @returns The number of bytes sent.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref write function if you need to ensure that all data
+ * is written before the blocking operation completes.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.send(boost::asio::buffer(data, size), 0);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.send(
+ this->implementation, buffers, flags, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Send some data on the socket.
+ /**
+ * This function is used to send data on the stream socket. The function
+ * call will block until one or more bytes of the data has been sent
+ * successfully, or an until error occurs.
+ *
+ * @param buffers One or more data buffers to be sent on the socket.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes sent. Returns 0 if an error occurred.
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref write function if you need to ensure that all data
+ * is written before the blocking operation completes.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return this->service.send(this->implementation, buffers, flags, ec);
+ }
+
+ /// Start an asynchronous send.
+ /**
+ * This function is used to asynchronously send data on the stream socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent on the socket. Although
+ * the buffers object may be copied as necessary, ownership of the underlying
+ * memory blocks is retained by the caller, which must guarantee that they
+ * remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref async_write function if you need to ensure that all
+ * data is written before the asynchronous operation completes.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_send(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_send(const ConstBufferSequence& buffers, WriteHandler handler)
+ {
+ this->service.async_send(this->implementation, buffers, 0, handler);
+ }
+
+ /// Start an asynchronous send.
+ /**
+ * This function is used to asynchronously send data on the stream socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be sent on the socket. Although
+ * the buffers object may be copied as necessary, ownership of the underlying
+ * memory blocks is retained by the caller, which must guarantee that they
+ * remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the send call is to be made.
+ *
+ * @param handler The handler to be called when the send operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes sent.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The send operation may not transmit all of the data to the peer.
+ * Consider using the @ref async_write function if you need to ensure that all
+ * data is written before the asynchronous operation completes.
+ *
+ * @par Example
+ * To send a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_send(boost::asio::buffer(data, size), 0, handler);
+ * @endcode
+ * See the @ref buffer documentation for information on sending multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_send(const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, WriteHandler handler)
+ {
+ this->service.async_send(this->implementation, buffers, flags, handler);
+ }
+
+ /// Receive some data on the socket.
+ /**
+ * This function is used to receive data on the stream socket. The function
+ * call will block until one or more bytes of data has been received
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that the
+ * requested amount of data is read before the blocking operation completes.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.receive(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.receive(this->implementation, buffers, 0, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Receive some data on the socket.
+ /**
+ * This function is used to receive data on the stream socket. The function
+ * call will block until one or more bytes of data has been received
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @returns The number of bytes received.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that the
+ * requested amount of data is read before the blocking operation completes.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.receive(boost::asio::buffer(data, size), 0);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.receive(
+ this->implementation, buffers, flags, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Receive some data on a connected socket.
+ /**
+ * This function is used to receive data on the stream socket. The function
+ * call will block until one or more bytes of data has been received
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes received. Returns 0 if an error occurred.
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that the
+ * requested amount of data is read before the blocking operation completes.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return this->service.receive(this->implementation, buffers, flags, ec);
+ }
+
+ /// Start an asynchronous receive.
+ /**
+ * This function is used to asynchronously receive data from the stream
+ * socket. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref async_read function if you need to ensure
+ * that the requested amount of data is received before the asynchronous
+ * operation completes.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.async_receive(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_receive(const MutableBufferSequence& buffers, ReadHandler handler)
+ {
+ this->service.async_receive(this->implementation, buffers, 0, handler);
+ }
+
+ /// Start an asynchronous receive.
+ /**
+ * This function is used to asynchronously receive data from the stream
+ * socket. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be received.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param flags Flags specifying how the receive call is to be made.
+ *
+ * @param handler The handler to be called when the receive operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes received.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The receive operation may not receive all of the requested number of
+ * bytes. Consider using the @ref async_read function if you need to ensure
+ * that the requested amount of data is received before the asynchronous
+ * operation completes.
+ *
+ * @par Example
+ * To receive into a single data buffer use the @ref buffer function as
+ * follows:
+ * @code
+ * socket.async_receive(boost::asio::buffer(data, size), 0, handler);
+ * @endcode
+ * See the @ref buffer documentation for information on receiving into
+ * multiple buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_receive(const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, ReadHandler handler)
+ {
+ this->service.async_receive(this->implementation, buffers, flags, handler);
+ }
+
+ /// Write some data to the socket.
+ /**
+ * This function is used to write data to the stream socket. The function call
+ * will block until one or more bytes of the data has been written
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more data buffers to be written to the socket.
+ *
+ * @returns The number of bytes written.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The write_some operation may not transmit all of the data to the
+ * peer. Consider using the @ref write function if you need to ensure that
+ * all data is written before the blocking operation completes.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.write_some(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.send(this->implementation, buffers, 0, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Write some data to the socket.
+ /**
+ * This function is used to write data to the stream socket. The function call
+ * will block until one or more bytes of the data has been written
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more data buffers to be written to the socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes written. Returns 0 if an error occurred.
+ *
+ * @note The write_some operation may not transmit all of the data to the
+ * peer. Consider using the @ref write function if you need to ensure that
+ * all data is written before the blocking operation completes.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return this->service.send(this->implementation, buffers, 0, ec);
+ }
+
+ /// Start an asynchronous write.
+ /**
+ * This function is used to asynchronously write data to the stream socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be written to the socket.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes written.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The write operation may not transmit all of the data to the peer.
+ * Consider using the @ref async_write function if you need to ensure that all
+ * data is written before the asynchronous operation completes.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_write_some(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_write_some(const ConstBufferSequence& buffers,
+ WriteHandler handler)
+ {
+ this->service.async_send(this->implementation, buffers, 0, handler);
+ }
+
+ /// Read some data from the socket.
+ /**
+ * This function is used to read data from the stream socket. The function
+ * call will block until one or more bytes of data has been read successfully,
+ * or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ *
+ * @returns The number of bytes read.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The read_some operation may not read all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that
+ * the requested amount of data is read before the blocking operation
+ * completes.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.read_some(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.receive(this->implementation, buffers, 0, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Read some data from the socket.
+ /**
+ * This function is used to read data from the stream socket. The function
+ * call will block until one or more bytes of data has been read successfully,
+ * or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes read. Returns 0 if an error occurred.
+ *
+ * @note The read_some operation may not read all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that
+ * the requested amount of data is read before the blocking operation
+ * completes.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return this->service.receive(this->implementation, buffers, 0, ec);
+ }
+
+ /// Start an asynchronous read.
+ /**
+ * This function is used to asynchronously read data from the stream socket.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes read.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The read operation may not read all of the requested number of bytes.
+ * Consider using the @ref async_read function if you need to ensure that the
+ * requested amount of data is read before the asynchronous operation
+ * completes.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code
+ * socket.async_read_some(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_read_some(const MutableBufferSequence& buffers,
+ ReadHandler handler)
+ {
+ this->service.async_receive(this->implementation, buffers, 0, handler);
+ }
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_STREAM_SOCKET_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/basic_streambuf.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/basic_streambuf.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,200 @@
+//
+// basic_streambuf.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BASIC_STREAMBUF_HPP
+#define BOOST_ASIO_BASIC_STREAMBUF_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <algorithm>
+#include <limits>
+#include <memory>
+#include <stdexcept>
+#include <streambuf>
+#include <vector>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Automatically resizable buffer class based on std::streambuf.
+template <typename Allocator = std::allocator<char> >
+class basic_streambuf
+ : public std::streambuf,
+ private noncopyable
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The type used to represent the get area as a list of buffers.
+ typedef implementation_defined const_buffers_type;
+
+ /// The type used to represent the put area as a list of buffers.
+ typedef implementation_defined mutable_buffers_type;
+#else
+ typedef boost::asio::const_buffers_1 const_buffers_type;
+ typedef boost::asio::mutable_buffers_1 mutable_buffers_type;
+#endif
+
+ /// Construct a buffer with a specified maximum size.
+ explicit basic_streambuf(
+ std::size_t max_size = (std::numeric_limits<std::size_t>::max)(),
+ const Allocator& allocator = Allocator())
+ : max_size_(max_size),
+ buffer_(allocator)
+ {
+ std::size_t pend = (std::min<std::size_t>)(max_size_, buffer_delta);
+ buffer_.resize((std::max<std::size_t>)(pend, 1));
+ setg(&buffer_[0], &buffer_[0], &buffer_[0]);
+ setp(&buffer_[0], &buffer_[0] + pend);
+ }
+
+ /// Return the size of the get area in characters.
+ std::size_t size() const
+ {
+ return pptr() - gptr();
+ }
+
+ /// Return the maximum size of the buffer.
+ std::size_t max_size() const
+ {
+ return max_size_;
+ }
+
+ /// Get a list of buffers that represents the get area.
+ const_buffers_type data() const
+ {
+ return boost::asio::buffer(boost::asio::const_buffer(gptr(),
+ (pptr() - gptr()) * sizeof(char_type)));
+ }
+
+ /// Get a list of buffers that represents the put area, with the given size.
+ mutable_buffers_type prepare(std::size_t size)
+ {
+ reserve(size);
+ return boost::asio::buffer(boost::asio::mutable_buffer(
+ pptr(), size * sizeof(char_type)));
+ }
+
+ /// Move the start of the put area by the specified number of characters.
+ void commit(std::size_t n)
+ {
+ if (pptr() + n > epptr())
+ n = epptr() - pptr();
+ pbump(static_cast<int>(n));
+ }
+
+ /// Move the start of the get area by the specified number of characters.
+ void consume(std::size_t n)
+ {
+ if (gptr() + n > pptr())
+ n = pptr() - gptr();
+ gbump(static_cast<int>(n));
+ }
+
+protected:
+ enum { buffer_delta = 128 };
+
+ int_type underflow()
+ {
+ if (gptr() < pptr())
+ {
+ setg(&buffer_[0], gptr(), pptr());
+ return traits_type::to_int_type(*gptr());
+ }
+ else
+ {
+ return traits_type::eof();
+ }
+ }
+
+ int_type overflow(int_type c)
+ {
+ if (!traits_type::eq_int_type(c, traits_type::eof()))
+ {
+ if (pptr() == epptr())
+ {
+ std::size_t buffer_size = pptr() - gptr();
+ if (buffer_size < max_size_ && max_size_ - buffer_size < buffer_delta)
+ {
+ reserve(max_size_ - buffer_size);
+ }
+ else
+ {
+ reserve(buffer_delta);
+ }
+ }
+
+ *pptr() = traits_type::to_char_type(c);
+ pbump(1);
+ return c;
+ }
+
+ return traits_type::not_eof(c);
+ }
+
+ void reserve(std::size_t n)
+ {
+ // Get current stream positions as offsets.
+ std::size_t gnext = gptr() - &buffer_[0];
+ std::size_t gend = egptr() - &buffer_[0];
+ std::size_t pnext = pptr() - &buffer_[0];
+ std::size_t pend = epptr() - &buffer_[0];
+
+ // Check if there is already enough space in the put area.
+ if (n <= pend - pnext)
+ {
+ return;
+ }
+
+ // Shift existing contents of get area to start of buffer.
+ if (gnext > 0)
+ {
+ std::rotate(&buffer_[0], &buffer_[0] + gnext, &buffer_[0] + pend);
+ gend -= gnext;
+ pnext -= gnext;
+ }
+
+ // Ensure buffer is large enough to hold at least the specified size.
+ if (n > pend - pnext)
+ {
+ if (n <= max_size_ && pnext <= max_size_ - n)
+ {
+ buffer_.resize((std::max<std::size_t>)(pnext + n, 1));
+ }
+ else
+ {
+ throw std::length_error("boost::asio::streambuf too long");
+ }
+ }
+
+ // Update stream positions.
+ setg(&buffer_[0], &buffer_[0], &buffer_[0] + gend);
+ setp(&buffer_[0] + pnext, &buffer_[0] + pnext + n);
+ }
+
+private:
+ std::size_t max_size_;
+ std::vector<char_type, Allocator> buffer_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BASIC_STREAMBUF_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/buffer.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/buffer.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,832 @@
+//
+// buffer.hpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BUFFER_HPP
+#define BOOST_ASIO_BUFFER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/array.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <string>
+#include <vector>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_MSVC)
+# if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0)
+# if !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
+# define BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+# endif // !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
+# endif // defined(_HAS_ITERATOR_DEBUGGING)
+#endif // defined(BOOST_MSVC)
+
+#if defined(__GNUC__)
+# if defined(_GLIBCXX_DEBUG)
+# if !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
+# define BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+# endif // !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
+# endif // defined(_GLIBCXX_DEBUG)
+#endif // defined(__GNUC__)
+
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+# include <boost/asio/detail/push_options.hpp>
+# include <boost/function.hpp>
+# include <boost/asio/detail/pop_options.hpp>
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+
+namespace boost {
+namespace asio {
+
+class mutable_buffer;
+class const_buffer;
+
+namespace detail {
+void* buffer_cast_helper(const mutable_buffer&);
+const void* buffer_cast_helper(const const_buffer&);
+std::size_t buffer_size_helper(const mutable_buffer&);
+std::size_t buffer_size_helper(const const_buffer&);
+} // namespace detail
+
+/// Holds a buffer that can be modified.
+/**
+ * The mutable_buffer class provides a safe representation of a buffer that can
+ * be modified. It does not own the underlying data, and so is cheap to copy or
+ * assign.
+ */
+class mutable_buffer
+{
+public:
+ /// Construct an empty buffer.
+ mutable_buffer()
+ : data_(0),
+ size_(0)
+ {
+ }
+
+ /// Construct a buffer to represent a given memory range.
+ mutable_buffer(void* data, std::size_t size)
+ : data_(data),
+ size_(size)
+ {
+ }
+
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ mutable_buffer(void* data, std::size_t size,
+ boost::function<void()> debug_check)
+ : data_(data),
+ size_(size),
+ debug_check_(debug_check)
+ {
+ }
+
+ const boost::function<void()>& get_debug_check() const
+ {
+ return debug_check_;
+ }
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+
+private:
+ friend void* boost::asio::detail::buffer_cast_helper(
+ const mutable_buffer& b);
+ friend std::size_t boost::asio::detail::buffer_size_helper(
+ const mutable_buffer& b);
+
+ void* data_;
+ std::size_t size_;
+
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ boost::function<void()> debug_check_;
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+};
+
+namespace detail {
+
+inline void* buffer_cast_helper(const mutable_buffer& b)
+{
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ if (b.size_ && b.debug_check_)
+ b.debug_check_();
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ return b.data_;
+}
+
+inline std::size_t buffer_size_helper(const mutable_buffer& b)
+{
+ return b.size_;
+}
+
+} // namespace detail
+
+/// Cast a non-modifiable buffer to a specified pointer to POD type.
+/**
+ * @relates mutable_buffer
+ */
+template <typename PointerToPodType>
+inline PointerToPodType buffer_cast(const mutable_buffer& b)
+{
+ return static_cast<PointerToPodType>(detail::buffer_cast_helper(b));
+}
+
+/// Get the number of bytes in a non-modifiable buffer.
+/**
+ * @relates mutable_buffer
+ */
+inline std::size_t buffer_size(const mutable_buffer& b)
+{
+ return detail::buffer_size_helper(b);
+}
+
+/// Create a new modifiable buffer that is offset from the start of another.
+/**
+ * @relates mutable_buffer
+ */
+inline mutable_buffer operator+(const mutable_buffer& b, std::size_t start)
+{
+ if (start > buffer_size(b))
+ return mutable_buffer();
+ char* new_data = buffer_cast<char*>(b) + start;
+ std::size_t new_size = buffer_size(b) - start;
+ return mutable_buffer(new_data, new_size
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ , b.get_debug_check()
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ );
+}
+
+/// Create a new modifiable buffer that is offset from the start of another.
+/**
+ * @relates mutable_buffer
+ */
+inline mutable_buffer operator+(std::size_t start, const mutable_buffer& b)
+{
+ if (start > buffer_size(b))
+ return mutable_buffer();
+ char* new_data = buffer_cast<char*>(b) + start;
+ std::size_t new_size = buffer_size(b) - start;
+ return mutable_buffer(new_data, new_size
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ , b.get_debug_check()
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ );
+}
+
+/// Adapts a single modifiable buffer so that it meets the requirements of the
+/// MutableBufferSequence concept.
+class mutable_buffers_1
+ : public mutable_buffer
+{
+public:
+ /// The type for each element in the list of buffers.
+ typedef mutable_buffer value_type;
+
+ /// A random-access iterator type that may be used to read elements.
+ typedef const mutable_buffer* const_iterator;
+
+ /// Construct to represent a single modifiable buffer.
+ explicit mutable_buffers_1(const mutable_buffer& b)
+ : mutable_buffer(b)
+ {
+ }
+
+ /// Get a random-access iterator to the first element.
+ const_iterator begin() const
+ {
+ return this;
+ }
+
+ /// Get a random-access iterator for one past the last element.
+ const_iterator end() const
+ {
+ return begin() + 1;
+ }
+};
+
+/// Holds a buffer that cannot be modified.
+/**
+ * The const_buffer class provides a safe representation of a buffer that cannot
+ * be modified. It does not own the underlying data, and so is cheap to copy or
+ * assign.
+ */
+class const_buffer
+{
+public:
+ /// Construct an empty buffer.
+ const_buffer()
+ : data_(0),
+ size_(0)
+ {
+ }
+
+ /// Construct a buffer to represent a given memory range.
+ const_buffer(const void* data, std::size_t size)
+ : data_(data),
+ size_(size)
+ {
+ }
+
+ /// Construct a non-modifiable buffer from a modifiable one.
+ const_buffer(const mutable_buffer& b)
+ : data_(boost::asio::detail::buffer_cast_helper(b)),
+ size_(boost::asio::detail::buffer_size_helper(b))
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ , debug_check_(b.get_debug_check())
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ {
+ }
+
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ const_buffer(const void* data, std::size_t size,
+ boost::function<void()> debug_check)
+ : data_(data),
+ size_(size),
+ debug_check_(debug_check)
+ {
+ }
+
+ const boost::function<void()>& get_debug_check() const
+ {
+ return debug_check_;
+ }
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+
+private:
+ friend const void* boost::asio::detail::buffer_cast_helper(
+ const const_buffer& b);
+ friend std::size_t boost::asio::detail::buffer_size_helper(
+ const const_buffer& b);
+
+ const void* data_;
+ std::size_t size_;
+
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ boost::function<void()> debug_check_;
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+};
+
+namespace detail {
+
+inline const void* buffer_cast_helper(const const_buffer& b)
+{
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ if (b.size_ && b.debug_check_)
+ b.debug_check_();
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ return b.data_;
+}
+
+inline std::size_t buffer_size_helper(const const_buffer& b)
+{
+ return b.size_;
+}
+
+} // namespace detail
+
+/// Cast a non-modifiable buffer to a specified pointer to POD type.
+/**
+ * @relates const_buffer
+ */
+template <typename PointerToPodType>
+inline PointerToPodType buffer_cast(const const_buffer& b)
+{
+ return static_cast<PointerToPodType>(detail::buffer_cast_helper(b));
+}
+
+/// Get the number of bytes in a non-modifiable buffer.
+/**
+ * @relates const_buffer
+ */
+inline std::size_t buffer_size(const const_buffer& b)
+{
+ return detail::buffer_size_helper(b);
+}
+
+/// Create a new non-modifiable buffer that is offset from the start of another.
+/**
+ * @relates const_buffer
+ */
+inline const_buffer operator+(const const_buffer& b, std::size_t start)
+{
+ if (start > buffer_size(b))
+ return const_buffer();
+ const char* new_data = buffer_cast<const char*>(b) + start;
+ std::size_t new_size = buffer_size(b) - start;
+ return const_buffer(new_data, new_size
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ , b.get_debug_check()
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ );
+}
+
+/// Create a new non-modifiable buffer that is offset from the start of another.
+/**
+ * @relates const_buffer
+ */
+inline const_buffer operator+(std::size_t start, const const_buffer& b)
+{
+ if (start > buffer_size(b))
+ return const_buffer();
+ const char* new_data = buffer_cast<const char*>(b) + start;
+ std::size_t new_size = buffer_size(b) - start;
+ return const_buffer(new_data, new_size
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ , b.get_debug_check()
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ );
+}
+
+/// Adapts a single non-modifiable buffer so that it meets the requirements of
+/// the ConstBufferSequence concept.
+class const_buffers_1
+ : public const_buffer
+{
+public:
+ /// The type for each element in the list of buffers.
+ typedef const_buffer value_type;
+
+ /// A random-access iterator type that may be used to read elements.
+ typedef const const_buffer* const_iterator;
+
+ /// Construct to represent a single non-modifiable buffer.
+ explicit const_buffers_1(const const_buffer& b)
+ : const_buffer(b)
+ {
+ }
+
+ /// Get a random-access iterator to the first element.
+ const_iterator begin() const
+ {
+ return this;
+ }
+
+ /// Get a random-access iterator for one past the last element.
+ const_iterator end() const
+ {
+ return begin() + 1;
+ }
+};
+
+/// An implementation of both the ConstBufferSequence and MutableBufferSequence
+/// concepts to represent a null buffer sequence.
+class null_buffers
+{
+public:
+ /// The type for each element in the list of buffers.
+ typedef mutable_buffer value_type;
+
+ /// A random-access iterator type that may be used to read elements.
+ typedef const mutable_buffer* const_iterator;
+
+ /// Get a random-access iterator to the first element.
+ const_iterator begin() const
+ {
+ return &buf_;
+ }
+
+ /// Get a random-access iterator for one past the last element.
+ const_iterator end() const
+ {
+ return &buf_;
+ }
+
+private:
+ mutable_buffer buf_;
+};
+
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+namespace detail {
+
+template <typename Iterator>
+class buffer_debug_check
+{
+public:
+ buffer_debug_check(Iterator iter)
+ : iter_(iter)
+ {
+ }
+
+ ~buffer_debug_check()
+ {
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+ // MSVC's string iterator checking may crash in a std::string::iterator
+ // object's destructor when the iterator points to an already-destroyed
+ // std::string object, unless the iterator is cleared first.
+ iter_ = Iterator();
+#endif // BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+ }
+
+ void operator()()
+ {
+ *iter_;
+ }
+
+private:
+ Iterator iter_;
+};
+
+} // namespace detail
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+
+/** @defgroup buffer boost::asio::buffer
+ *
+ * @brief The boost::asio::buffer function is used to create a buffer object to
+ * represent raw memory, an array of POD elements, or a vector of POD elements.
+ *
+ * The simplest use case involves reading or writing a single buffer of a
+ * specified size:
+ *
+ * @code sock.write(boost::asio::buffer(data, size)); @endcode
+ *
+ * In the above example, the return value of boost::asio::buffer meets the
+ * requirements of the ConstBufferSequence concept so that it may be directly
+ * passed to the socket's write function. A buffer created for modifiable
+ * memory also meets the requirements of the MutableBufferSequence concept.
+ *
+ * An individual buffer may be created from a builtin array, std::vector or
+ * boost::array of POD elements. This helps prevent buffer overruns by
+ * automatically determining the size of the buffer:
+ *
+ * @code char d1[128];
+ * size_t bytes_transferred = sock.read(boost::asio::buffer(d1));
+ *
+ * std::vector<char> d2(128);
+ * bytes_transferred = sock.read(boost::asio::buffer(d2));
+ *
+ * boost::array<char, 128> d3;
+ * bytes_transferred = sock.read(boost::asio::buffer(d3)); @endcode
+ *
+ * To read or write using multiple buffers (i.e. scatter-gather I/O), multiple
+ * buffer objects may be assigned into a container that supports the
+ * MutableBufferSequence (for read) or ConstBufferSequence (for write) concepts:
+ *
+ * @code
+ * char d1[128];
+ * std::vector<char> d2(128);
+ * boost::array<char, 128> d3;
+ *
+ * boost::array<mutable_buffer, 3> bufs1 = {
+ * boost::asio::buffer(d1),
+ * boost::asio::buffer(d2),
+ * boost::asio::buffer(d3) };
+ * bytes_transferred = sock.read(bufs1);
+ *
+ * std::vector<const_buffer> bufs2;
+ * bufs2.push_back(boost::asio::buffer(d1));
+ * bufs2.push_back(boost::asio::buffer(d2));
+ * bufs2.push_back(boost::asio::buffer(d3));
+ * bytes_transferred = sock.write(bufs2); @endcode
+ */
+/*@{*/
+
+/// Create a new modifiable buffer from an existing buffer.
+inline mutable_buffers_1 buffer(const mutable_buffer& b)
+{
+ return mutable_buffers_1(b);
+}
+
+/// Create a new modifiable buffer from an existing buffer.
+inline mutable_buffers_1 buffer(const mutable_buffer& b,
+ std::size_t max_size_in_bytes)
+{
+ return mutable_buffers_1(
+ mutable_buffer(buffer_cast<void*>(b),
+ buffer_size(b) < max_size_in_bytes
+ ? buffer_size(b) : max_size_in_bytes
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ , b.get_debug_check()
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ ));
+}
+
+/// Create a new non-modifiable buffer from an existing buffer.
+inline const_buffers_1 buffer(const const_buffer& b)
+{
+ return const_buffers_1(b);
+}
+
+/// Create a new non-modifiable buffer from an existing buffer.
+inline const_buffers_1 buffer(const const_buffer& b,
+ std::size_t max_size_in_bytes)
+{
+ return const_buffers_1(
+ const_buffer(buffer_cast<const void*>(b),
+ buffer_size(b) < max_size_in_bytes
+ ? buffer_size(b) : max_size_in_bytes
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ , b.get_debug_check()
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ ));
+}
+
+/// Create a new modifiable buffer that represents the given memory range.
+inline mutable_buffers_1 buffer(void* data, std::size_t size_in_bytes)
+{
+ return mutable_buffers_1(mutable_buffer(data, size_in_bytes));
+}
+
+/// Create a new non-modifiable buffer that represents the given memory range.
+inline const_buffers_1 buffer(const void* data,
+ std::size_t size_in_bytes)
+{
+ return const_buffers_1(const_buffer(data, size_in_bytes));
+}
+
+/// Create a new modifiable buffer that represents the given POD array.
+template <typename PodType, std::size_t N>
+inline mutable_buffers_1 buffer(PodType (&data)[N])
+{
+ return mutable_buffers_1(mutable_buffer(data, N * sizeof(PodType)));
+}
+
+/// Create a new modifiable buffer that represents the given POD array.
+template <typename PodType, std::size_t N>
+inline mutable_buffers_1 buffer(PodType (&data)[N],
+ std::size_t max_size_in_bytes)
+{
+ return mutable_buffers_1(
+ mutable_buffer(data,
+ N * sizeof(PodType) < max_size_in_bytes
+ ? N * sizeof(PodType) : max_size_in_bytes));
+}
+
+/// Create a new non-modifiable buffer that represents the given POD array.
+template <typename PodType, std::size_t N>
+inline const_buffers_1 buffer(const PodType (&data)[N])
+{
+ return const_buffers_1(const_buffer(data, N * sizeof(PodType)));
+}
+
+/// Create a new non-modifiable buffer that represents the given POD array.
+template <typename PodType, std::size_t N>
+inline const_buffers_1 buffer(const PodType (&data)[N],
+ std::size_t max_size_in_bytes)
+{
+ return const_buffers_1(
+ const_buffer(data,
+ N * sizeof(PodType) < max_size_in_bytes
+ ? N * sizeof(PodType) : max_size_in_bytes));
+}
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) \
+ || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
+
+// Borland C++ and Sun Studio think the overloads:
+//
+// unspecified buffer(boost::array<PodType, N>& array ...);
+//
+// and
+//
+// unspecified buffer(boost::array<const PodType, N>& array ...);
+//
+// are ambiguous. This will be worked around by using a buffer_types traits
+// class that contains typedefs for the appropriate buffer and container
+// classes, based on whether PodType is const or non-const.
+
+namespace detail {
+
+template <bool IsConst>
+struct buffer_types_base;
+
+template <>
+struct buffer_types_base<false>
+{
+ typedef mutable_buffer buffer_type;
+ typedef mutable_buffers_1 container_type;
+};
+
+template <>
+struct buffer_types_base<true>
+{
+ typedef const_buffer buffer_type;
+ typedef const_buffers_1 container_type;
+};
+
+template <typename PodType>
+struct buffer_types
+ : public buffer_types_base<boost::is_const<PodType>::value>
+{
+};
+
+} // namespace detail
+
+template <typename PodType, std::size_t N>
+inline typename detail::buffer_types<PodType>::container_type
+buffer(boost::array<PodType, N>& data)
+{
+ typedef typename boost::asio::detail::buffer_types<PodType>::buffer_type
+ buffer_type;
+ typedef typename boost::asio::detail::buffer_types<PodType>::container_type
+ container_type;
+ return container_type(
+ buffer_type(data.c_array(), data.size() * sizeof(PodType)));
+}
+
+template <typename PodType, std::size_t N>
+inline typename detail::buffer_types<PodType>::container_type
+buffer(boost::array<PodType, N>& data, std::size_t max_size_in_bytes)
+{
+ typedef typename boost::asio::detail::buffer_types<PodType>::buffer_type
+ buffer_type;
+ typedef typename boost::asio::detail::buffer_types<PodType>::container_type
+ container_type;
+ return container_type(
+ buffer_type(data.c_array(),
+ data.size() * sizeof(PodType) < max_size_in_bytes
+ ? data.size() * sizeof(PodType) : max_size_in_bytes));
+}
+
+#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
+ // || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
+
+/// Create a new modifiable buffer that represents the given POD array.
+template <typename PodType, std::size_t N>
+inline mutable_buffers_1 buffer(boost::array<PodType, N>& data)
+{
+ return mutable_buffers_1(
+ mutable_buffer(data.c_array(), data.size() * sizeof(PodType)));
+}
+
+/// Create a new modifiable buffer that represents the given POD array.
+template <typename PodType, std::size_t N>
+inline mutable_buffers_1 buffer(boost::array<PodType, N>& data,
+ std::size_t max_size_in_bytes)
+{
+ return mutable_buffers_1(
+ mutable_buffer(data.c_array(),
+ data.size() * sizeof(PodType) < max_size_in_bytes
+ ? data.size() * sizeof(PodType) : max_size_in_bytes));
+}
+
+/// Create a new non-modifiable buffer that represents the given POD array.
+template <typename PodType, std::size_t N>
+inline const_buffers_1 buffer(boost::array<const PodType, N>& data)
+{
+ return const_buffers_1(
+ const_buffer(data.data(), data.size() * sizeof(PodType)));
+}
+
+/// Create a new non-modifiable buffer that represents the given POD array.
+template <typename PodType, std::size_t N>
+inline const_buffers_1 buffer(boost::array<const PodType, N>& data,
+ std::size_t max_size_in_bytes)
+{
+ return const_buffers_1(
+ const_buffer(data.data(),
+ data.size() * sizeof(PodType) < max_size_in_bytes
+ ? data.size() * sizeof(PodType) : max_size_in_bytes));
+}
+
+#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
+ // || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
+
+/// Create a new non-modifiable buffer that represents the given POD array.
+template <typename PodType, std::size_t N>
+inline const_buffers_1 buffer(const boost::array<PodType, N>& data)
+{
+ return const_buffers_1(
+ const_buffer(data.data(), data.size() * sizeof(PodType)));
+}
+
+/// Create a new non-modifiable buffer that represents the given POD array.
+template <typename PodType, std::size_t N>
+inline const_buffers_1 buffer(const boost::array<PodType, N>& data,
+ std::size_t max_size_in_bytes)
+{
+ return const_buffers_1(
+ const_buffer(data.data(),
+ data.size() * sizeof(PodType) < max_size_in_bytes
+ ? data.size() * sizeof(PodType) : max_size_in_bytes));
+}
+
+/// Create a new modifiable buffer that represents the given POD vector.
+/**
+ * @note The buffer is invalidated by any vector operation that would also
+ * invalidate iterators.
+ */
+template <typename PodType, typename Allocator>
+inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data)
+{
+ return mutable_buffers_1(
+ mutable_buffer(&data[0], data.size() * sizeof(PodType)
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ , detail::buffer_debug_check<
+ typename std::vector<PodType, Allocator>::iterator
+ >(data.begin())
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ ));
+}
+
+/// Create a new modifiable buffer that represents the given POD vector.
+/**
+ * @note The buffer is invalidated by any vector operation that would also
+ * invalidate iterators.
+ */
+template <typename PodType, typename Allocator>
+inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data,
+ std::size_t max_size_in_bytes)
+{
+ return mutable_buffers_1(
+ mutable_buffer(&data[0],
+ data.size() * sizeof(PodType) < max_size_in_bytes
+ ? data.size() * sizeof(PodType) : max_size_in_bytes
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ , detail::buffer_debug_check<
+ typename std::vector<PodType, Allocator>::iterator
+ >(data.begin())
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ ));
+}
+
+/// Create a new non-modifiable buffer that represents the given POD vector.
+/**
+ * @note The buffer is invalidated by any vector operation that would also
+ * invalidate iterators.
+ */
+template <typename PodType, typename Allocator>
+inline const_buffers_1 buffer(
+ const std::vector<PodType, Allocator>& data)
+{
+ return const_buffers_1(
+ const_buffer(&data[0], data.size() * sizeof(PodType)
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ , detail::buffer_debug_check<
+ typename std::vector<PodType, Allocator>::const_iterator
+ >(data.begin())
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ ));
+}
+
+/// Create a new non-modifiable buffer that represents the given POD vector.
+/**
+ * @note The buffer is invalidated by any vector operation that would also
+ * invalidate iterators.
+ */
+template <typename PodType, typename Allocator>
+inline const_buffers_1 buffer(
+ const std::vector<PodType, Allocator>& data, std::size_t max_size_in_bytes)
+{
+ return const_buffers_1(
+ const_buffer(&data[0],
+ data.size() * sizeof(PodType) < max_size_in_bytes
+ ? data.size() * sizeof(PodType) : max_size_in_bytes
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ , detail::buffer_debug_check<
+ typename std::vector<PodType, Allocator>::const_iterator
+ >(data.begin())
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ ));
+}
+
+/// Create a new non-modifiable buffer that represents the given string.
+/**
+ * @note The buffer is invalidated by any non-const operation called on the
+ * given string object.
+ */
+inline const_buffers_1 buffer(const std::string& data)
+{
+ return const_buffers_1(const_buffer(data.data(), data.size()
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ , detail::buffer_debug_check<std::string::const_iterator>(data.begin())
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ ));
+}
+
+/// Create a new non-modifiable buffer that represents the given string.
+/**
+ * @note The buffer is invalidated by any non-const operation called on the
+ * given string object.
+ */
+inline const_buffers_1 buffer(const std::string& data,
+ std::size_t max_size_in_bytes)
+{
+ return const_buffers_1(
+ const_buffer(data.data(),
+ data.size() < max_size_in_bytes
+ ? data.size() : max_size_in_bytes
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ , detail::buffer_debug_check<std::string::const_iterator>(data.begin())
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ ));
+}
+
+/*@}*/
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BUFFER_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/buffered_read_stream.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/buffered_read_stream.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,416 @@
+//
+// buffered_read_stream.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BUFFERED_READ_STREAM_HPP
+#define BOOST_ASIO_BUFFERED_READ_STREAM_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <cstring>
+#include <boost/config.hpp>
+#include <boost/type_traits.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/buffered_read_stream_fwd.hpp>
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_resize_guard.hpp>
+#include <boost/asio/detail/buffered_stream_storage.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Adds buffering to the read-related operations of a stream.
+/**
+ * The buffered_read_stream class template can be used to add buffering to the
+ * synchronous and asynchronous read operations of a stream.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Concepts:
+ * AsyncReadStream, AsyncWriteStream, Stream, Sync_Read_Stream, SyncWriteStream.
+ */
+template <typename Stream>
+class buffered_read_stream
+ : private noncopyable
+{
+public:
+ /// The type of the next layer.
+ typedef typename boost::remove_reference<Stream>::type next_layer_type;
+
+ /// The type of the lowest layer.
+ typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
+
+#if defined(GENERATING_DOCUMENTATION)
+ /// The default buffer size.
+ static const std::size_t default_buffer_size = implementation_defined;
+#else
+ BOOST_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024);
+#endif
+
+ /// Construct, passing the specified argument to initialise the next layer.
+ template <typename Arg>
+ explicit buffered_read_stream(Arg& a)
+ : next_layer_(a),
+ storage_(default_buffer_size)
+ {
+ }
+
+ /// Construct, passing the specified argument to initialise the next layer.
+ template <typename Arg>
+ buffered_read_stream(Arg& a, std::size_t buffer_size)
+ : next_layer_(a),
+ storage_(buffer_size)
+ {
+ }
+
+ /// Get a reference to the next layer.
+ next_layer_type& next_layer()
+ {
+ return next_layer_;
+ }
+
+ /// Get a reference to the lowest layer.
+ lowest_layer_type& lowest_layer()
+ {
+ return next_layer_.lowest_layer();
+ }
+
+ /// (Deprecated: use get_io_service().) Get the io_service associated with
+ /// the object.
+ boost::asio::io_service& io_service()
+ {
+ return next_layer_.get_io_service();
+ }
+
+ /// Get the io_service associated with the object.
+ boost::asio::io_service& get_io_service()
+ {
+ return next_layer_.get_io_service();
+ }
+
+ /// Close the stream.
+ void close()
+ {
+ next_layer_.close();
+ }
+
+ /// Close the stream.
+ boost::system::error_code close(boost::system::error_code& ec)
+ {
+ return next_layer_.close(ec);
+ }
+
+ /// Write the given data to the stream. Returns the number of bytes written.
+ /// Throws an exception on failure.
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers)
+ {
+ return next_layer_.write_some(buffers);
+ }
+
+ /// Write the given data to the stream. Returns the number of bytes written,
+ /// or 0 if an error occurred.
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return next_layer_.write_some(buffers, ec);
+ }
+
+ /// Start an asynchronous write. The data being written must be valid for the
+ /// lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_write_some(const ConstBufferSequence& buffers,
+ WriteHandler handler)
+ {
+ next_layer_.async_write_some(buffers, handler);
+ }
+
+ /// Fill the buffer with some data. Returns the number of bytes placed in the
+ /// buffer as a result of the operation. Throws an exception on failure.
+ std::size_t fill()
+ {
+ detail::buffer_resize_guard<detail::buffered_stream_storage>
+ resize_guard(storage_);
+ std::size_t previous_size = storage_.size();
+ storage_.resize(storage_.capacity());
+ storage_.resize(previous_size + next_layer_.read_some(buffer(
+ storage_.data() + previous_size,
+ storage_.size() - previous_size)));
+ resize_guard.commit();
+ return storage_.size() - previous_size;
+ }
+
+ /// Fill the buffer with some data. Returns the number of bytes placed in the
+ /// buffer as a result of the operation, or 0 if an error occurred.
+ std::size_t fill(boost::system::error_code& ec)
+ {
+ detail::buffer_resize_guard<detail::buffered_stream_storage>
+ resize_guard(storage_);
+ std::size_t previous_size = storage_.size();
+ storage_.resize(storage_.capacity());
+ storage_.resize(previous_size + next_layer_.read_some(buffer(
+ storage_.data() + previous_size,
+ storage_.size() - previous_size),
+ ec));
+ resize_guard.commit();
+ return storage_.size() - previous_size;
+ }
+
+ template <typename ReadHandler>
+ class fill_handler
+ {
+ public:
+ fill_handler(boost::asio::io_service& io_service,
+ detail::buffered_stream_storage& storage,
+ std::size_t previous_size, ReadHandler handler)
+ : io_service_(io_service),
+ storage_(storage),
+ previous_size_(previous_size),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ storage_.resize(previous_size_ + bytes_transferred);
+ io_service_.dispatch(detail::bind_handler(
+ handler_, ec, bytes_transferred));
+ }
+
+ private:
+ boost::asio::io_service& io_service_;
+ detail::buffered_stream_storage& storage_;
+ std::size_t previous_size_;
+ ReadHandler handler_;
+ };
+
+ /// Start an asynchronous fill.
+ template <typename ReadHandler>
+ void async_fill(ReadHandler handler)
+ {
+ std::size_t previous_size = storage_.size();
+ storage_.resize(storage_.capacity());
+ next_layer_.async_read_some(
+ buffer(
+ storage_.data() + previous_size,
+ storage_.size() - previous_size),
+ fill_handler<ReadHandler>(get_io_service(),
+ storage_, previous_size, handler));
+ }
+
+ /// Read some data from the stream. Returns the number of bytes read. Throws
+ /// an exception on failure.
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers)
+ {
+ if (storage_.empty())
+ fill();
+ return copy(buffers);
+ }
+
+ /// Read some data from the stream. Returns the number of bytes read or 0 if
+ /// an error occurred.
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ ec = boost::system::error_code();
+ if (storage_.empty() && !fill(ec))
+ return 0;
+ return copy(buffers);
+ }
+
+ template <typename MutableBufferSequence, typename ReadHandler>
+ class read_some_handler
+ {
+ public:
+ read_some_handler(boost::asio::io_service& io_service,
+ detail::buffered_stream_storage& storage,
+ const MutableBufferSequence& buffers, ReadHandler handler)
+ : io_service_(io_service),
+ storage_(storage),
+ buffers_(buffers),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec, std::size_t)
+ {
+ if (ec || storage_.empty())
+ {
+ std::size_t length = 0;
+ io_service_.dispatch(detail::bind_handler(handler_, ec, length));
+ }
+ else
+ {
+ using namespace std; // For memcpy.
+
+ std::size_t bytes_avail = storage_.size();
+ std::size_t bytes_copied = 0;
+
+ typename MutableBufferSequence::const_iterator iter = buffers_.begin();
+ typename MutableBufferSequence::const_iterator end = buffers_.end();
+ for (; iter != end && bytes_avail > 0; ++iter)
+ {
+ std::size_t max_length = buffer_size(*iter);
+ std::size_t length = (max_length < bytes_avail)
+ ? max_length : bytes_avail;
+ memcpy(buffer_cast<void*>(*iter),
+ storage_.data() + bytes_copied, length);
+ bytes_copied += length;
+ bytes_avail -= length;
+ }
+
+ storage_.consume(bytes_copied);
+ io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied));
+ }
+ }
+
+ private:
+ boost::asio::io_service& io_service_;
+ detail::buffered_stream_storage& storage_;
+ MutableBufferSequence buffers_;
+ ReadHandler handler_;
+ };
+
+ /// Start an asynchronous read. The buffer into which the data will be read
+ /// must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_read_some(const MutableBufferSequence& buffers,
+ ReadHandler handler)
+ {
+ if (storage_.empty())
+ {
+ async_fill(read_some_handler<MutableBufferSequence, ReadHandler>(
+ get_io_service(), storage_, buffers, handler));
+ }
+ else
+ {
+ std::size_t length = copy(buffers);
+ get_io_service().post(detail::bind_handler(
+ handler, boost::system::error_code(), length));
+ }
+ }
+
+ /// Peek at the incoming data on the stream. Returns the number of bytes read.
+ /// Throws an exception on failure.
+ template <typename MutableBufferSequence>
+ std::size_t peek(const MutableBufferSequence& buffers)
+ {
+ if (storage_.empty())
+ fill();
+ return peek_copy(buffers);
+ }
+
+ /// Peek at the incoming data on the stream. Returns the number of bytes read,
+ /// or 0 if an error occurred.
+ template <typename MutableBufferSequence>
+ std::size_t peek(const MutableBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ ec = boost::system::error_code();
+ if (storage_.empty() && !fill(ec))
+ return 0;
+ return peek_copy(buffers);
+ }
+
+ /// Determine the amount of data that may be read without blocking.
+ std::size_t in_avail()
+ {
+ return storage_.size();
+ }
+
+ /// Determine the amount of data that may be read without blocking.
+ std::size_t in_avail(boost::system::error_code& ec)
+ {
+ ec = boost::system::error_code();
+ return storage_.size();
+ }
+
+private:
+ /// Copy data out of the internal buffer to the specified target buffer.
+ /// Returns the number of bytes copied.
+ template <typename MutableBufferSequence>
+ std::size_t copy(const MutableBufferSequence& buffers)
+ {
+ using namespace std; // For memcpy.
+
+ std::size_t bytes_avail = storage_.size();
+ std::size_t bytes_copied = 0;
+
+ typename MutableBufferSequence::const_iterator iter = buffers.begin();
+ typename MutableBufferSequence::const_iterator end = buffers.end();
+ for (; iter != end && bytes_avail > 0; ++iter)
+ {
+ std::size_t max_length = buffer_size(*iter);
+ std::size_t length = (max_length < bytes_avail)
+ ? max_length : bytes_avail;
+ memcpy(buffer_cast<void*>(*iter), storage_.data() + bytes_copied, length);
+ bytes_copied += length;
+ bytes_avail -= length;
+ }
+
+ storage_.consume(bytes_copied);
+ return bytes_copied;
+ }
+
+ /// Copy data from the internal buffer to the specified target buffer, without
+ /// removing the data from the internal buffer. Returns the number of bytes
+ /// copied.
+ template <typename MutableBufferSequence>
+ std::size_t peek_copy(const MutableBufferSequence& buffers)
+ {
+ using namespace std; // For memcpy.
+
+ std::size_t bytes_avail = storage_.size();
+ std::size_t bytes_copied = 0;
+
+ typename MutableBufferSequence::const_iterator iter = buffers.begin();
+ typename MutableBufferSequence::const_iterator end = buffers.end();
+ for (; iter != end && bytes_avail > 0; ++iter)
+ {
+ std::size_t max_length = buffer_size(*iter);
+ std::size_t length = (max_length < bytes_avail)
+ ? max_length : bytes_avail;
+ memcpy(buffer_cast<void*>(*iter), storage_.data() + bytes_copied, length);
+ bytes_copied += length;
+ bytes_avail -= length;
+ }
+
+ return bytes_copied;
+ }
+
+ /// The next layer.
+ Stream next_layer_;
+
+ // The data in the buffer.
+ detail::buffered_stream_storage storage_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BUFFERED_READ_STREAM_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/buffered_read_stream_fwd.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/buffered_read_stream_fwd.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,31 @@
+//
+// buffered_read_stream_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BUFFERED_READ_STREAM_FWD_HPP
+#define BOOST_ASIO_BUFFERED_READ_STREAM_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+template <typename Stream>
+class buffered_read_stream;
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BUFFERED_READ_STREAM_FWD_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/buffered_stream.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/buffered_stream.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,252 @@
+//
+// buffered_stream.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BUFFERED_STREAM_HPP
+#define BOOST_ASIO_BUFFERED_STREAM_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/buffered_read_stream.hpp>
+#include <boost/asio/buffered_write_stream.hpp>
+#include <boost/asio/buffered_stream_fwd.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Adds buffering to the read- and write-related operations of a stream.
+/**
+ * The buffered_stream class template can be used to add buffering to the
+ * synchronous and asynchronous read and write operations of a stream.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Concepts:
+ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
+ */
+template <typename Stream>
+class buffered_stream
+ : private noncopyable
+{
+public:
+ /// The type of the next layer.
+ typedef typename boost::remove_reference<Stream>::type next_layer_type;
+
+ /// The type of the lowest layer.
+ typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
+
+ /// Construct, passing the specified argument to initialise the next layer.
+ template <typename Arg>
+ explicit buffered_stream(Arg& a)
+ : inner_stream_impl_(a),
+ stream_impl_(inner_stream_impl_)
+ {
+ }
+
+ /// Construct, passing the specified argument to initialise the next layer.
+ template <typename Arg>
+ explicit buffered_stream(Arg& a, std::size_t read_buffer_size,
+ std::size_t write_buffer_size)
+ : inner_stream_impl_(a, write_buffer_size),
+ stream_impl_(inner_stream_impl_, read_buffer_size)
+ {
+ }
+
+ /// Get a reference to the next layer.
+ next_layer_type& next_layer()
+ {
+ return stream_impl_.next_layer().next_layer();
+ }
+
+ /// Get a reference to the lowest layer.
+ lowest_layer_type& lowest_layer()
+ {
+ return stream_impl_.lowest_layer();
+ }
+
+ /// (Deprecated: use get_io_service().) Get the io_service associated with
+ /// the object.
+ boost::asio::io_service& io_service()
+ {
+ return stream_impl_.get_io_service();
+ }
+
+ /// Get the io_service associated with the object.
+ boost::asio::io_service& get_io_service()
+ {
+ return stream_impl_.get_io_service();
+ }
+
+ /// Close the stream.
+ void close()
+ {
+ stream_impl_.close();
+ }
+
+ /// Close the stream.
+ boost::system::error_code close(boost::system::error_code& ec)
+ {
+ return stream_impl_.close(ec);
+ }
+
+ /// Flush all data from the buffer to the next layer. Returns the number of
+ /// bytes written to the next layer on the last write operation. Throws an
+ /// exception on failure.
+ std::size_t flush()
+ {
+ return stream_impl_.next_layer().flush();
+ }
+
+ /// Flush all data from the buffer to the next layer. Returns the number of
+ /// bytes written to the next layer on the last write operation, or 0 if an
+ /// error occurred.
+ std::size_t flush(boost::system::error_code& ec)
+ {
+ return stream_impl_.next_layer().flush(ec);
+ }
+
+ /// Start an asynchronous flush.
+ template <typename WriteHandler>
+ void async_flush(WriteHandler handler)
+ {
+ return stream_impl_.next_layer().async_flush(handler);
+ }
+
+ /// Write the given data to the stream. Returns the number of bytes written.
+ /// Throws an exception on failure.
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers)
+ {
+ return stream_impl_.write_some(buffers);
+ }
+
+ /// Write the given data to the stream. Returns the number of bytes written,
+ /// or 0 if an error occurred.
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return stream_impl_.write_some(buffers, ec);
+ }
+
+ /// Start an asynchronous write. The data being written must be valid for the
+ /// lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_write_some(const ConstBufferSequence& buffers,
+ WriteHandler handler)
+ {
+ stream_impl_.async_write_some(buffers, handler);
+ }
+
+ /// Fill the buffer with some data. Returns the number of bytes placed in the
+ /// buffer as a result of the operation. Throws an exception on failure.
+ std::size_t fill()
+ {
+ return stream_impl_.fill();
+ }
+
+ /// Fill the buffer with some data. Returns the number of bytes placed in the
+ /// buffer as a result of the operation, or 0 if an error occurred.
+ std::size_t fill(boost::system::error_code& ec)
+ {
+ return stream_impl_.fill(ec);
+ }
+
+ /// Start an asynchronous fill.
+ template <typename ReadHandler>
+ void async_fill(ReadHandler handler)
+ {
+ stream_impl_.async_fill(handler);
+ }
+
+ /// Read some data from the stream. Returns the number of bytes read. Throws
+ /// an exception on failure.
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers)
+ {
+ return stream_impl_.read_some(buffers);
+ }
+
+ /// Read some data from the stream. Returns the number of bytes read or 0 if
+ /// an error occurred.
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return stream_impl_.read_some(buffers, ec);
+ }
+
+ /// Start an asynchronous read. The buffer into which the data will be read
+ /// must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_read_some(const MutableBufferSequence& buffers,
+ ReadHandler handler)
+ {
+ stream_impl_.async_read_some(buffers, handler);
+ }
+
+ /// Peek at the incoming data on the stream. Returns the number of bytes read.
+ /// Throws an exception on failure.
+ template <typename MutableBufferSequence>
+ std::size_t peek(const MutableBufferSequence& buffers)
+ {
+ return stream_impl_.peek(buffers);
+ }
+
+ /// Peek at the incoming data on the stream. Returns the number of bytes read,
+ /// or 0 if an error occurred.
+ template <typename MutableBufferSequence>
+ std::size_t peek(const MutableBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return stream_impl_.peek(buffers, ec);
+ }
+
+ /// Determine the amount of data that may be read without blocking.
+ std::size_t in_avail()
+ {
+ return stream_impl_.in_avail();
+ }
+
+ /// Determine the amount of data that may be read without blocking.
+ std::size_t in_avail(boost::system::error_code& ec)
+ {
+ return stream_impl_.in_avail(ec);
+ }
+
+private:
+ // The buffered write stream.
+ typedef buffered_write_stream<Stream> write_stream_type;
+ write_stream_type inner_stream_impl_;
+
+ // The buffered read stream.
+ typedef buffered_read_stream<write_stream_type&> read_stream_type;
+ read_stream_type stream_impl_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BUFFERED_STREAM_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/buffered_stream_fwd.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/buffered_stream_fwd.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,31 @@
+//
+// buffered_stream_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BUFFERED_STREAM_FWD_HPP
+#define BOOST_ASIO_BUFFERED_STREAM_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+template <typename Stream>
+class buffered_stream;
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BUFFERED_STREAM_FWD_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/buffered_write_stream.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/buffered_write_stream.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,370 @@
+//
+// buffered_write_stream.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BUFFERED_WRITE_STREAM_HPP
+#define BOOST_ASIO_BUFFERED_WRITE_STREAM_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <cstring>
+#include <boost/config.hpp>
+#include <boost/type_traits.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/buffered_write_stream_fwd.hpp>
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/completion_condition.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/write.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffered_stream_storage.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Adds buffering to the write-related operations of a stream.
+/**
+ * The buffered_write_stream class template can be used to add buffering to the
+ * synchronous and asynchronous write operations of a stream.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Concepts:
+ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
+ */
+template <typename Stream>
+class buffered_write_stream
+ : private noncopyable
+{
+public:
+ /// The type of the next layer.
+ typedef typename boost::remove_reference<Stream>::type next_layer_type;
+
+ /// The type of the lowest layer.
+ typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
+
+#if defined(GENERATING_DOCUMENTATION)
+ /// The default buffer size.
+ static const std::size_t default_buffer_size = implementation_defined;
+#else
+ BOOST_STATIC_CONSTANT(std::size_t, default_buffer_size = 1024);
+#endif
+
+ /// Construct, passing the specified argument to initialise the next layer.
+ template <typename Arg>
+ explicit buffered_write_stream(Arg& a)
+ : next_layer_(a),
+ storage_(default_buffer_size)
+ {
+ }
+
+ /// Construct, passing the specified argument to initialise the next layer.
+ template <typename Arg>
+ buffered_write_stream(Arg& a, std::size_t buffer_size)
+ : next_layer_(a),
+ storage_(buffer_size)
+ {
+ }
+
+ /// Get a reference to the next layer.
+ next_layer_type& next_layer()
+ {
+ return next_layer_;
+ }
+
+ /// Get a reference to the lowest layer.
+ lowest_layer_type& lowest_layer()
+ {
+ return next_layer_.lowest_layer();
+ }
+
+ /// (Deprecated: use get_io_service().) Get the io_service associated with
+ /// the object.
+ boost::asio::io_service& io_service()
+ {
+ return next_layer_.get_io_service();
+ }
+
+ /// Get the io_service associated with the object.
+ boost::asio::io_service& get_io_service()
+ {
+ return next_layer_.get_io_service();
+ }
+
+ /// Close the stream.
+ void close()
+ {
+ next_layer_.close();
+ }
+
+ /// Close the stream.
+ boost::system::error_code close(boost::system::error_code& ec)
+ {
+ return next_layer_.close(ec);
+ }
+
+ /// Flush all data from the buffer to the next layer. Returns the number of
+ /// bytes written to the next layer on the last write operation. Throws an
+ /// exception on failure.
+ std::size_t flush()
+ {
+ std::size_t bytes_written = write(next_layer_,
+ buffer(storage_.data(), storage_.size()));
+ storage_.consume(bytes_written);
+ return bytes_written;
+ }
+
+ /// Flush all data from the buffer to the next layer. Returns the number of
+ /// bytes written to the next layer on the last write operation, or 0 if an
+ /// error occurred.
+ std::size_t flush(boost::system::error_code& ec)
+ {
+ std::size_t bytes_written = write(next_layer_,
+ buffer(storage_.data(), storage_.size()),
+ transfer_all(), ec);
+ storage_.consume(bytes_written);
+ return bytes_written;
+ }
+
+ template <typename WriteHandler>
+ class flush_handler
+ {
+ public:
+ flush_handler(boost::asio::io_service& io_service,
+ detail::buffered_stream_storage& storage, WriteHandler handler)
+ : io_service_(io_service),
+ storage_(storage),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_written)
+ {
+ storage_.consume(bytes_written);
+ io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_written));
+ }
+
+ private:
+ boost::asio::io_service& io_service_;
+ detail::buffered_stream_storage& storage_;
+ WriteHandler handler_;
+ };
+
+ /// Start an asynchronous flush.
+ template <typename WriteHandler>
+ void async_flush(WriteHandler handler)
+ {
+ async_write(next_layer_, buffer(storage_.data(), storage_.size()),
+ flush_handler<WriteHandler>(get_io_service(), storage_, handler));
+ }
+
+ /// Write the given data to the stream. Returns the number of bytes written.
+ /// Throws an exception on failure.
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers)
+ {
+ if (storage_.size() == storage_.capacity())
+ flush();
+ return copy(buffers);
+ }
+
+ /// Write the given data to the stream. Returns the number of bytes written,
+ /// or 0 if an error occurred and the error handler did not throw.
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ ec = boost::system::error_code();
+ if (storage_.size() == storage_.capacity() && !flush(ec))
+ return 0;
+ return copy(buffers);
+ }
+
+ template <typename ConstBufferSequence, typename WriteHandler>
+ class write_some_handler
+ {
+ public:
+ write_some_handler(boost::asio::io_service& io_service,
+ detail::buffered_stream_storage& storage,
+ const ConstBufferSequence& buffers, WriteHandler handler)
+ : io_service_(io_service),
+ storage_(storage),
+ buffers_(buffers),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec, std::size_t)
+ {
+ if (ec)
+ {
+ std::size_t length = 0;
+ io_service_.dispatch(detail::bind_handler(handler_, ec, length));
+ }
+ else
+ {
+ using namespace std; // For memcpy.
+
+ std::size_t orig_size = storage_.size();
+ std::size_t space_avail = storage_.capacity() - orig_size;
+ std::size_t bytes_copied = 0;
+
+ typename ConstBufferSequence::const_iterator iter = buffers_.begin();
+ typename ConstBufferSequence::const_iterator end = buffers_.end();
+ for (; iter != end && space_avail > 0; ++iter)
+ {
+ std::size_t bytes_avail = buffer_size(*iter);
+ std::size_t length = (bytes_avail < space_avail)
+ ? bytes_avail : space_avail;
+ storage_.resize(orig_size + bytes_copied + length);
+ memcpy(storage_.data() + orig_size + bytes_copied,
+ buffer_cast<const void*>(*iter), length);
+ bytes_copied += length;
+ space_avail -= length;
+ }
+
+ io_service_.dispatch(detail::bind_handler(handler_, ec, bytes_copied));
+ }
+ }
+
+ private:
+ boost::asio::io_service& io_service_;
+ detail::buffered_stream_storage& storage_;
+ ConstBufferSequence buffers_;
+ WriteHandler handler_;
+ };
+
+ /// Start an asynchronous write. The data being written must be valid for the
+ /// lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_write_some(const ConstBufferSequence& buffers,
+ WriteHandler handler)
+ {
+ if (storage_.size() == storage_.capacity())
+ {
+ async_flush(write_some_handler<ConstBufferSequence, WriteHandler>(
+ get_io_service(), storage_, buffers, handler));
+ }
+ else
+ {
+ std::size_t bytes_copied = copy(buffers);
+ get_io_service().post(detail::bind_handler(
+ handler, boost::system::error_code(), bytes_copied));
+ }
+ }
+
+ /// Read some data from the stream. Returns the number of bytes read. Throws
+ /// an exception on failure.
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers)
+ {
+ return next_layer_.read_some(buffers);
+ }
+
+ /// Read some data from the stream. Returns the number of bytes read or 0 if
+ /// an error occurred.
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return next_layer_.read_some(buffers, ec);
+ }
+
+ /// Start an asynchronous read. The buffer into which the data will be read
+ /// must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_read_some(const MutableBufferSequence& buffers,
+ ReadHandler handler)
+ {
+ next_layer_.async_read_some(buffers, handler);
+ }
+
+ /// Peek at the incoming data on the stream. Returns the number of bytes read.
+ /// Throws an exception on failure.
+ template <typename MutableBufferSequence>
+ std::size_t peek(const MutableBufferSequence& buffers)
+ {
+ return next_layer_.peek(buffers);
+ }
+
+ /// Peek at the incoming data on the stream. Returns the number of bytes read,
+ /// or 0 if an error occurred.
+ template <typename MutableBufferSequence>
+ std::size_t peek(const MutableBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return next_layer_.peek(buffers, ec);
+ }
+
+ /// Determine the amount of data that may be read without blocking.
+ std::size_t in_avail()
+ {
+ return next_layer_.in_avail();
+ }
+
+ /// Determine the amount of data that may be read without blocking.
+ std::size_t in_avail(boost::system::error_code& ec)
+ {
+ return next_layer_.in_avail(ec);
+ }
+
+private:
+ /// Copy data into the internal buffer from the specified source buffer.
+ /// Returns the number of bytes copied.
+ template <typename ConstBufferSequence>
+ std::size_t copy(const ConstBufferSequence& buffers)
+ {
+ using namespace std; // For memcpy.
+
+ std::size_t orig_size = storage_.size();
+ std::size_t space_avail = storage_.capacity() - orig_size;
+ std::size_t bytes_copied = 0;
+
+ typename ConstBufferSequence::const_iterator iter = buffers.begin();
+ typename ConstBufferSequence::const_iterator end = buffers.end();
+ for (; iter != end && space_avail > 0; ++iter)
+ {
+ std::size_t bytes_avail = buffer_size(*iter);
+ std::size_t length = (bytes_avail < space_avail)
+ ? bytes_avail : space_avail;
+ storage_.resize(orig_size + bytes_copied + length);
+ memcpy(storage_.data() + orig_size + bytes_copied,
+ buffer_cast<const void*>(*iter), length);
+ bytes_copied += length;
+ space_avail -= length;
+ }
+
+ return bytes_copied;
+ }
+
+ /// The next layer.
+ Stream next_layer_;
+
+ // The data in the buffer.
+ detail::buffered_stream_storage storage_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BUFFERED_WRITE_STREAM_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/buffered_write_stream_fwd.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/buffered_write_stream_fwd.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,31 @@
+//
+// buffered_write_stream_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BUFFERED_WRITE_STREAM_FWD_HPP
+#define BOOST_ASIO_BUFFERED_WRITE_STREAM_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+template <typename Stream>
+class buffered_write_stream;
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BUFFERED_WRITE_STREAM_FWD_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/buffers_iterator.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/buffers_iterator.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,320 @@
+//
+// buffers_iterator.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BUFFERS_ITERATOR_HPP
+#define BOOST_ASIO_BUFFERS_ITERATOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/add_const.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/buffer.hpp>
+
+namespace boost {
+namespace asio {
+
+namespace detail
+{
+ template <bool IsMutable>
+ struct buffers_iterator_types_helper;
+
+ template <>
+ struct buffers_iterator_types_helper<false>
+ {
+ typedef const_buffer buffer_type;
+ template <typename ByteType>
+ struct byte_type
+ {
+ typedef typename boost::add_const<ByteType>::type type;
+ };
+ };
+
+ template <>
+ struct buffers_iterator_types_helper<true>
+ {
+ typedef mutable_buffer buffer_type;
+ template <typename ByteType>
+ struct byte_type
+ {
+ typedef ByteType type;
+ };
+ };
+
+ template <typename BufferSequence, typename ByteType>
+ struct buffers_iterator_types
+ {
+ enum
+ {
+ is_mutable = boost::is_convertible<
+ typename BufferSequence::value_type, mutable_buffer>::value
+ };
+ typedef buffers_iterator_types_helper<is_mutable> helper;
+ typedef typename helper::buffer_type buffer_type;
+ typedef typename helper::template byte_type<ByteType>::type byte_type;
+ };
+}
+
+/// A random access iterator over the bytes in a buffer sequence.
+template <typename BufferSequence, typename ByteType = char>
+class buffers_iterator
+ : public boost::iterator_facade<
+ buffers_iterator<BufferSequence, ByteType>,
+ typename detail::buffers_iterator_types<
+ BufferSequence, ByteType>::byte_type,
+ boost::random_access_traversal_tag>
+{
+private:
+ typedef typename detail::buffers_iterator_types<
+ BufferSequence, ByteType>::buffer_type buffer_type;
+ typedef typename detail::buffers_iterator_types<
+ BufferSequence, ByteType>::byte_type byte_type;
+
+public:
+ /// Default constructor. Creates an iterator in an undefined state.
+ buffers_iterator()
+ : current_buffer_(),
+ current_buffer_position_(0),
+ begin_(),
+ current_(),
+ end_(),
+ position_(0)
+ {
+ }
+
+ /// Construct an iterator representing the beginning of the buffers' data.
+ static buffers_iterator begin(const BufferSequence& buffers)
+ {
+ buffers_iterator new_iter;
+ new_iter.begin_ = buffers.begin();
+ new_iter.current_ = buffers.begin();
+ new_iter.end_ = buffers.end();
+ while (new_iter.current_ != new_iter.end_)
+ {
+ new_iter.current_buffer_ = *new_iter.current_;
+ if (boost::asio::buffer_size(new_iter.current_buffer_) > 0)
+ break;
+ ++new_iter.current_;
+ }
+ return new_iter;
+ }
+
+ /// Construct an iterator representing the end of the buffers' data.
+ static buffers_iterator end(const BufferSequence& buffers)
+ {
+ buffers_iterator new_iter;
+ new_iter.begin_ = buffers.begin();
+ new_iter.current_ = buffers.begin();
+ new_iter.end_ = buffers.end();
+ while (new_iter.current_ != new_iter.end_)
+ {
+ buffer_type buffer = *new_iter.current_;
+ new_iter.position_ += boost::asio::buffer_size(buffer);
+ ++new_iter.current_;
+ }
+ return new_iter;
+ }
+
+private:
+ friend class boost::iterator_core_access;
+
+ // Dereference the iterator.
+ byte_type& dereference() const
+ {
+ return buffer_cast<byte_type*>(current_buffer_)[current_buffer_position_];
+ }
+
+ // Compare two iterators for equality.
+ bool equal(const buffers_iterator& other) const
+ {
+ return position_ == other.position_;
+ }
+
+ // Increment the iterator.
+ void increment()
+ {
+ BOOST_ASSERT(current_ != end_ && "iterator out of bounds");
+ ++position_;
+
+ // Check if the increment can be satisfied by the current buffer.
+ ++current_buffer_position_;
+ if (current_buffer_position_ != boost::asio::buffer_size(current_buffer_))
+ return;
+
+ // Find the next non-empty buffer.
+ ++current_;
+ current_buffer_position_ = 0;
+ while (current_ != end_)
+ {
+ current_buffer_ = *current_;
+ if (boost::asio::buffer_size(current_buffer_) > 0)
+ return;
+ ++current_;
+ }
+ }
+
+ // Decrement the iterator.
+ void decrement()
+ {
+ BOOST_ASSERT(position_ > 0 && "iterator out of bounds");
+ --position_;
+
+ // Check if the decrement can be satisfied by the current buffer.
+ if (current_buffer_position_ != 0)
+ {
+ --current_buffer_position_;
+ return;
+ }
+
+ // Find the previous non-empty buffer.
+ typename BufferSequence::const_iterator iter = current_;
+ while (iter != begin_)
+ {
+ --iter;
+ buffer_type buffer = *iter;
+ std::size_t buffer_size = boost::asio::buffer_size(buffer);
+ if (buffer_size > 0)
+ {
+ current_ = iter;
+ current_buffer_ = buffer;
+ current_buffer_position_ = buffer_size - 1;
+ return;
+ }
+ }
+ }
+
+ // Advance the iterator by the specified distance.
+ void advance(std::ptrdiff_t n)
+ {
+ if (n > 0)
+ {
+ BOOST_ASSERT(current_ != end_ && "iterator out of bounds");
+ for (;;)
+ {
+ std::ptrdiff_t current_buffer_balance
+ = boost::asio::buffer_size(current_buffer_)
+ - current_buffer_position_;
+
+ // Check if the advance can be satisfied by the current buffer.
+ if (current_buffer_balance > n)
+ {
+ position_ += n;
+ current_buffer_position_ += n;
+ return;
+ }
+
+ // Update position.
+ n -= current_buffer_balance;
+ position_ += current_buffer_balance;
+
+ // Move to next buffer. If it is empty then it will be skipped on the
+ // next iteration of this loop.
+ if (++current_ == end_)
+ {
+ BOOST_ASSERT(n == 0 && "iterator out of bounds");
+ current_buffer_ = buffer_type();
+ current_buffer_position_ = 0;
+ return;
+ }
+ current_buffer_ = *current_;
+ current_buffer_position_ = 0;
+ }
+ }
+ else if (n < 0)
+ {
+ std::size_t abs_n = -n;
+ BOOST_ASSERT(position_ >= abs_n && "iterator out of bounds");
+ for (;;)
+ {
+ // Check if the advance can be satisfied by the current buffer.
+ if (current_buffer_position_ >= abs_n)
+ {
+ position_ -= abs_n;
+ current_buffer_position_ -= abs_n;
+ return;
+ }
+
+ // Update position.
+ abs_n -= current_buffer_position_;
+ position_ -= current_buffer_position_;
+
+ // Check if we've reached the beginning of the buffers.
+ if (current_ == begin_)
+ {
+ BOOST_ASSERT(abs_n == 0 && "iterator out of bounds");
+ current_buffer_position_ = 0;
+ return;
+ }
+
+ // Find the previous non-empty buffer.
+ typename BufferSequence::const_iterator iter = current_;
+ while (iter != begin_)
+ {
+ --iter;
+ buffer_type buffer = *iter;
+ std::size_t buffer_size = boost::asio::buffer_size(buffer);
+ if (buffer_size > 0)
+ {
+ current_ = iter;
+ current_buffer_ = buffer;
+ current_buffer_position_ = buffer_size;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Determine the distance between two iterators.
+ std::ptrdiff_t distance_to(const buffers_iterator& other) const
+ {
+ return other.position_ - position_;
+ }
+
+ buffer_type current_buffer_;
+ std::size_t current_buffer_position_;
+ typename BufferSequence::const_iterator begin_;
+ typename BufferSequence::const_iterator current_;
+ typename BufferSequence::const_iterator end_;
+ std::size_t position_;
+};
+
+/// Construct an iterator representing the beginning of the buffers' data.
+template <typename BufferSequence>
+inline buffers_iterator<BufferSequence> buffers_begin(
+ const BufferSequence& buffers)
+{
+ return buffers_iterator<BufferSequence>::begin(buffers);
+}
+
+/// Construct an iterator representing the end of the buffers' data.
+template <typename BufferSequence>
+inline buffers_iterator<BufferSequence> buffers_end(
+ const BufferSequence& buffers)
+{
+ return buffers_iterator<BufferSequence>::end(buffers);
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BUFFERS_ITERATOR_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/completion_condition.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/completion_condition.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,147 @@
+//
+// completion_condition.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_COMPLETION_CONDITION_HPP
+#define BOOST_ASIO_COMPLETION_CONDITION_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+namespace boost {
+namespace asio {
+
+namespace detail {
+
+class transfer_all_t
+{
+public:
+ typedef bool result_type;
+
+ template <typename Error>
+ bool operator()(const Error& err, std::size_t)
+ {
+ return !!err;
+ }
+};
+
+class transfer_at_least_t
+{
+public:
+ typedef bool result_type;
+
+ explicit transfer_at_least_t(std::size_t minimum)
+ : minimum_(minimum)
+ {
+ }
+
+ template <typename Error>
+ bool operator()(const Error& err, std::size_t bytes_transferred)
+ {
+ return !!err || bytes_transferred >= minimum_;
+ }
+
+private:
+ std::size_t minimum_;
+};
+
+} // namespace detail
+
+/**
+ * @defgroup completion_condition Completion Condition Function Objects
+ *
+ * Function objects used for determining when a read or write operation should
+ * complete.
+ */
+/*@{*/
+
+/// Return a completion condition function object that indicates that a read or
+/// write operation should continue until all of the data has been transferred,
+/// or until an error occurs.
+/**
+ * This function is used to create an object, of unspecified type, that meets
+ * CompletionCondition requirements.
+ *
+ * @par Example
+ * Reading until a buffer is full:
+ * @code
+ * boost::array<char, 128> buf;
+ * boost::system::error_code ec;
+ * std::size_t n = boost::asio::read(
+ * sock, boost::asio::buffer(buf),
+ * boost::asio::transfer_all(), ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * else
+ * {
+ * // n == 128
+ * }
+ * @endcode
+ */
+#if defined(GENERATING_DOCUMENTATION)
+unspecified transfer_all();
+#else
+inline detail::transfer_all_t transfer_all()
+{
+ return detail::transfer_all_t();
+}
+#endif
+
+/// Return a completion condition function object that indicates that a read or
+/// write operation should continue until a minimum number of bytes has been
+/// transferred, or until an error occurs.
+/**
+ * This function is used to create an object, of unspecified type, that meets
+ * CompletionCondition requirements.
+ *
+ * @par Example
+ * Reading until a buffer is full or contains at least 64 bytes:
+ * @code
+ * boost::array<char, 128> buf;
+ * boost::system::error_code ec;
+ * std::size_t n = boost::asio::read(
+ * sock, boost::asio::buffer(buf),
+ * boost::asio::transfer_at_least(64), ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * else
+ * {
+ * // n >= 64 && n <= 128
+ * }
+ * @endcode
+ */
+#if defined(GENERATING_DOCUMENTATION)
+unspecified transfer_at_least(std::size_t minimum);
+#else
+inline detail::transfer_at_least_t transfer_at_least(std::size_t minimum)
+{
+ return detail::transfer_at_least_t(minimum);
+}
+#endif
+
+/*@}*/
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_COMPLETION_CONDITION_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/datagram_socket_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/datagram_socket_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,325 @@
+//
+// datagram_socket_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DATAGRAM_SOCKET_SERVICE_HPP
+#define BOOST_ASIO_DATAGRAM_SOCKET_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/epoll_reactor.hpp>
+#include <boost/asio/detail/kqueue_reactor.hpp>
+#include <boost/asio/detail/select_reactor.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/reactive_socket_service.hpp>
+#include <boost/asio/detail/win_iocp_socket_service.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Default service implementation for a datagram socket.
+template <typename Protocol>
+class datagram_socket_service
+#if defined(GENERATING_DOCUMENTATION)
+ : public boost::asio::io_service::service
+#else
+ : public boost::asio::detail::service_base<datagram_socket_service<Protocol> >
+#endif
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The unique service identifier.
+ static boost::asio::io_service::id id;
+#endif
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+private:
+ // The type of the platform-specific implementation.
+#if defined(BOOST_ASIO_HAS_IOCP)
+ typedef detail::win_iocp_socket_service<Protocol> service_impl_type;
+#elif defined(BOOST_ASIO_HAS_EPOLL)
+ typedef detail::reactive_socket_service<
+ Protocol, detail::epoll_reactor<false> > service_impl_type;
+#elif defined(BOOST_ASIO_HAS_KQUEUE)
+ typedef detail::reactive_socket_service<
+ Protocol, detail::kqueue_reactor<false> > service_impl_type;
+#elif defined(BOOST_ASIO_HAS_DEV_POLL)
+ typedef detail::reactive_socket_service<
+ Protocol, detail::dev_poll_reactor<false> > service_impl_type;
+#else
+ typedef detail::reactive_socket_service<
+ Protocol, detail::select_reactor<false> > service_impl_type;
+#endif
+
+public:
+ /// The type of a datagram socket.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined implementation_type;
+#else
+ typedef typename service_impl_type::implementation_type implementation_type;
+#endif
+
+ /// The native socket type.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_type;
+#else
+ typedef typename service_impl_type::native_type native_type;
+#endif
+
+ /// Construct a new datagram socket service for the specified io_service.
+ explicit datagram_socket_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ datagram_socket_service<Protocol> >(io_service),
+ service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ {
+ }
+
+ /// Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ /// Construct a new datagram socket implementation.
+ void construct(implementation_type& impl)
+ {
+ service_impl_.construct(impl);
+ }
+
+ /// Destroy a datagram socket implementation.
+ void destroy(implementation_type& impl)
+ {
+ service_impl_.destroy(impl);
+ }
+
+ // Open a new datagram socket implementation.
+ boost::system::error_code open(implementation_type& impl,
+ const protocol_type& protocol, boost::system::error_code& ec)
+ {
+ if (protocol.type() == SOCK_DGRAM)
+ service_impl_.open(impl, protocol, ec);
+ else
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+
+ /// Assign an existing native socket to a datagram socket.
+ boost::system::error_code assign(implementation_type& impl,
+ const protocol_type& protocol, const native_type& native_socket,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.assign(impl, protocol, native_socket, ec);
+ }
+
+ /// Determine whether the socket is open.
+ bool is_open(const implementation_type& impl) const
+ {
+ return service_impl_.is_open(impl);
+ }
+
+ /// Close a datagram socket implementation.
+ boost::system::error_code close(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.close(impl, ec);
+ }
+
+ /// Get the native socket implementation.
+ native_type native(implementation_type& impl)
+ {
+ return service_impl_.native(impl);
+ }
+
+ /// Cancel all asynchronous operations associated with the socket.
+ boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.cancel(impl, ec);
+ }
+
+ /// Determine whether the socket is at the out-of-band data mark.
+ bool at_mark(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.at_mark(impl, ec);
+ }
+
+ /// Determine the number of bytes available for reading.
+ std::size_t available(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.available(impl, ec);
+ }
+
+ // Bind the datagram socket to the specified local endpoint.
+ boost::system::error_code bind(implementation_type& impl,
+ const endpoint_type& endpoint, boost::system::error_code& ec)
+ {
+ return service_impl_.bind(impl, endpoint, ec);
+ }
+
+ /// Connect the datagram socket to the specified endpoint.
+ boost::system::error_code connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ return service_impl_.connect(impl, peer_endpoint, ec);
+ }
+
+ /// Start an asynchronous connect.
+ template <typename ConnectHandler>
+ void async_connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, ConnectHandler handler)
+ {
+ service_impl_.async_connect(impl, peer_endpoint, handler);
+ }
+
+ /// Set a socket option.
+ template <typename SettableSocketOption>
+ boost::system::error_code set_option(implementation_type& impl,
+ const SettableSocketOption& option, boost::system::error_code& ec)
+ {
+ return service_impl_.set_option(impl, option, ec);
+ }
+
+ /// Get a socket option.
+ template <typename GettableSocketOption>
+ boost::system::error_code get_option(const implementation_type& impl,
+ GettableSocketOption& option, boost::system::error_code& ec) const
+ {
+ return service_impl_.get_option(impl, option, ec);
+ }
+
+ /// Perform an IO control command on the socket.
+ template <typename IoControlCommand>
+ boost::system::error_code io_control(implementation_type& impl,
+ IoControlCommand& command, boost::system::error_code& ec)
+ {
+ return service_impl_.io_control(impl, command, ec);
+ }
+
+ /// Get the local endpoint.
+ endpoint_type local_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.local_endpoint(impl, ec);
+ }
+
+ /// Get the remote endpoint.
+ endpoint_type remote_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.remote_endpoint(impl, ec);
+ }
+
+ /// Disable sends or receives on the socket.
+ boost::system::error_code shutdown(implementation_type& impl,
+ socket_base::shutdown_type what, boost::system::error_code& ec)
+ {
+ return service_impl_.shutdown(impl, what, ec);
+ }
+
+ /// Send the given data to the peer.
+ template <typename ConstBufferSequence>
+ std::size_t send(implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return service_impl_.send(impl, buffers, flags, ec);
+ }
+
+ /// Start an asynchronous send.
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_send(implementation_type& impl, const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, WriteHandler handler)
+ {
+ service_impl_.async_send(impl, buffers, flags, handler);
+ }
+
+ /// Send a datagram to the specified endpoint.
+ template <typename ConstBufferSequence>
+ std::size_t send_to(implementation_type& impl,
+ const ConstBufferSequence& buffers, const endpoint_type& destination,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return service_impl_.send_to(impl, buffers, destination, flags, ec);
+ }
+
+ /// Start an asynchronous send.
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_send_to(implementation_type& impl,
+ const ConstBufferSequence& buffers, const endpoint_type& destination,
+ socket_base::message_flags flags, WriteHandler handler)
+ {
+ service_impl_.async_send_to(impl, buffers, destination, flags, handler);
+ }
+
+ /// Receive some data from the peer.
+ template <typename MutableBufferSequence>
+ std::size_t receive(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return service_impl_.receive(impl, buffers, flags, ec);
+ }
+
+ /// Start an asynchronous receive.
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_receive(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, ReadHandler handler)
+ {
+ service_impl_.async_receive(impl, buffers, flags, handler);
+ }
+
+ /// Receive a datagram with the endpoint of the sender.
+ template <typename MutableBufferSequence>
+ std::size_t receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return service_impl_.receive_from(impl, buffers, sender_endpoint, flags,
+ ec);
+ }
+
+ /// Start an asynchronous receive that will get the endpoint of the sender.
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, ReadHandler handler)
+ {
+ service_impl_.async_receive_from(impl, buffers, sender_endpoint, flags,
+ handler);
+ }
+
+private:
+ // The service that provides the platform-specific implementation.
+ service_impl_type& service_impl_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DATAGRAM_SOCKET_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/deadline_timer.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/deadline_timer.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,39 @@
+//
+// deadline_timer.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DEADLINE_TIMER_HPP
+#define BOOST_ASIO_DEADLINE_TIMER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/socket_types.hpp> // Must come before posix_time.
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/basic_deadline_timer.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Typedef for the typical usage of timer.
+typedef basic_deadline_timer<boost::posix_time::ptime> deadline_timer;
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DEADLINE_TIMER_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/deadline_timer_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/deadline_timer_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,170 @@
+//
+// deadline_timer_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DEADLINE_TIMER_SERVICE_HPP
+#define BOOST_ASIO_DEADLINE_TIMER_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/time_traits.hpp>
+#include <boost/asio/detail/deadline_timer_service.hpp>
+#include <boost/asio/detail/epoll_reactor.hpp>
+#include <boost/asio/detail/kqueue_reactor.hpp>
+#include <boost/asio/detail/select_reactor.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/win_iocp_io_service.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Default service implementation for a timer.
+template <typename TimeType,
+ typename TimeTraits = boost::asio::time_traits<TimeType> >
+class deadline_timer_service
+#if defined(GENERATING_DOCUMENTATION)
+ : public boost::asio::io_service::service
+#else
+ : public boost::asio::detail::service_base<
+ deadline_timer_service<TimeType, TimeTraits> >
+#endif
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The unique service identifier.
+ static boost::asio::io_service::id id;
+#endif
+
+ /// The time traits type.
+ typedef TimeTraits traits_type;
+
+ /// The time type.
+ typedef typename traits_type::time_type time_type;
+
+ /// The duration type.
+ typedef typename traits_type::duration_type duration_type;
+
+private:
+ // The type of the platform-specific implementation.
+#if defined(BOOST_ASIO_HAS_IOCP)
+ typedef detail::deadline_timer_service<
+ traits_type, detail::win_iocp_io_service> service_impl_type;
+#elif defined(BOOST_ASIO_HAS_EPOLL)
+ typedef detail::deadline_timer_service<
+ traits_type, detail::epoll_reactor<false> > service_impl_type;
+#elif defined(BOOST_ASIO_HAS_KQUEUE)
+ typedef detail::deadline_timer_service<
+ traits_type, detail::kqueue_reactor<false> > service_impl_type;
+#elif defined(BOOST_ASIO_HAS_DEV_POLL)
+ typedef detail::deadline_timer_service<
+ traits_type, detail::dev_poll_reactor<false> > service_impl_type;
+#else
+ typedef detail::deadline_timer_service<
+ traits_type, detail::select_reactor<false> > service_impl_type;
+#endif
+
+public:
+ /// The implementation type of the deadline timer.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined implementation_type;
+#else
+ typedef typename service_impl_type::implementation_type implementation_type;
+#endif
+
+ /// Construct a new timer service for the specified io_service.
+ explicit deadline_timer_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ deadline_timer_service<TimeType, TimeTraits> >(io_service),
+ service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ {
+ }
+
+ /// Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ /// Construct a new timer implementation.
+ void construct(implementation_type& impl)
+ {
+ service_impl_.construct(impl);
+ }
+
+ /// Destroy a timer implementation.
+ void destroy(implementation_type& impl)
+ {
+ service_impl_.destroy(impl);
+ }
+
+ /// Cancel any asynchronous wait operations associated with the timer.
+ std::size_t cancel(implementation_type& impl, boost::system::error_code& ec)
+ {
+ return service_impl_.cancel(impl, ec);
+ }
+
+ /// Get the expiry time for the timer as an absolute time.
+ time_type expires_at(const implementation_type& impl) const
+ {
+ return service_impl_.expires_at(impl);
+ }
+
+ /// Set the expiry time for the timer as an absolute time.
+ std::size_t expires_at(implementation_type& impl,
+ const time_type& expiry_time, boost::system::error_code& ec)
+ {
+ return service_impl_.expires_at(impl, expiry_time, ec);
+ }
+
+ /// Get the expiry time for the timer relative to now.
+ duration_type expires_from_now(const implementation_type& impl) const
+ {
+ return service_impl_.expires_from_now(impl);
+ }
+
+ /// Set the expiry time for the timer relative to now.
+ std::size_t expires_from_now(implementation_type& impl,
+ const duration_type& expiry_time, boost::system::error_code& ec)
+ {
+ return service_impl_.expires_from_now(impl, expiry_time, ec);
+ }
+
+ // Perform a blocking wait on the timer.
+ void wait(implementation_type& impl, boost::system::error_code& ec)
+ {
+ service_impl_.wait(impl, ec);
+ }
+
+ // Start an asynchronous wait on the timer.
+ template <typename WaitHandler>
+ void async_wait(implementation_type& impl, WaitHandler handler)
+ {
+ service_impl_.async_wait(impl, handler);
+ }
+
+private:
+ // The service that provides the platform-specific implementation.
+ service_impl_type& service_impl_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DEADLINE_TIMER_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/bind_handler.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/bind_handler.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,351 @@
+//
+// bind_handler.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_BIND_HANDLER_HPP
+#define BOOST_ASIO_DETAIL_BIND_HANDLER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Handler, typename Arg1>
+class binder1
+{
+public:
+ binder1(const Handler& handler, const Arg1& arg1)
+ : handler_(handler),
+ arg1_(arg1)
+ {
+ }
+
+ void operator()()
+ {
+ handler_(arg1_);
+ }
+
+ void operator()() const
+ {
+ handler_(arg1_);
+ }
+
+//private:
+ Handler handler_;
+ Arg1 arg1_;
+};
+
+template <typename Handler, typename Arg1>
+inline void* asio_handler_allocate(std::size_t size,
+ binder1<Handler, Arg1>* this_handler)
+{
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ binder1<Handler, Arg1>* this_handler)
+{
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+}
+
+template <typename Function, typename Handler, typename Arg1>
+inline void asio_handler_invoke(const Function& function,
+ binder1<Handler, Arg1>* this_handler)
+{
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1>
+inline binder1<Handler, Arg1> bind_handler(const Handler& handler,
+ const Arg1& arg1)
+{
+ return binder1<Handler, Arg1>(handler, arg1);
+}
+
+template <typename Handler, typename Arg1, typename Arg2>
+class binder2
+{
+public:
+ binder2(const Handler& handler, const Arg1& arg1, const Arg2& arg2)
+ : handler_(handler),
+ arg1_(arg1),
+ arg2_(arg2)
+ {
+ }
+
+ void operator()()
+ {
+ handler_(arg1_, arg2_);
+ }
+
+ void operator()() const
+ {
+ handler_(arg1_, arg2_);
+ }
+
+//private:
+ Handler handler_;
+ Arg1 arg1_;
+ Arg2 arg2_;
+};
+
+template <typename Handler, typename Arg1, typename Arg2>
+inline void* asio_handler_allocate(std::size_t size,
+ binder2<Handler, Arg1, Arg2>* this_handler)
+{
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ binder2<Handler, Arg1, Arg2>* this_handler)
+{
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+}
+
+template <typename Function, typename Handler, typename Arg1, typename Arg2>
+inline void asio_handler_invoke(const Function& function,
+ binder2<Handler, Arg1, Arg2>* this_handler)
+{
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2>
+inline binder2<Handler, Arg1, Arg2> bind_handler(const Handler& handler,
+ const Arg1& arg1, const Arg2& arg2)
+{
+ return binder2<Handler, Arg1, Arg2>(handler, arg1, arg2);
+}
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
+class binder3
+{
+public:
+ binder3(const Handler& handler, const Arg1& arg1, const Arg2& arg2,
+ const Arg3& arg3)
+ : handler_(handler),
+ arg1_(arg1),
+ arg2_(arg2),
+ arg3_(arg3)
+ {
+ }
+
+ void operator()()
+ {
+ handler_(arg1_, arg2_, arg3_);
+ }
+
+ void operator()() const
+ {
+ handler_(arg1_, arg2_, arg3_);
+ }
+
+//private:
+ Handler handler_;
+ Arg1 arg1_;
+ Arg2 arg2_;
+ Arg3 arg3_;
+};
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
+inline void* asio_handler_allocate(std::size_t size,
+ binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
+{
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
+{
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+}
+
+template <typename Function, typename Handler, typename Arg1, typename Arg2,
+ typename Arg3>
+inline void asio_handler_invoke(const Function& function,
+ binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
+{
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
+inline binder3<Handler, Arg1, Arg2, Arg3> bind_handler(const Handler& handler,
+ const Arg1& arg1, const Arg2& arg2, const Arg3& arg3)
+{
+ return binder3<Handler, Arg1, Arg2, Arg3>(handler, arg1, arg2, arg3);
+}
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4>
+class binder4
+{
+public:
+ binder4(const Handler& handler, const Arg1& arg1, const Arg2& arg2,
+ const Arg3& arg3, const Arg4& arg4)
+ : handler_(handler),
+ arg1_(arg1),
+ arg2_(arg2),
+ arg3_(arg3),
+ arg4_(arg4)
+ {
+ }
+
+ void operator()()
+ {
+ handler_(arg1_, arg2_, arg3_, arg4_);
+ }
+
+ void operator()() const
+ {
+ handler_(arg1_, arg2_, arg3_, arg4_);
+ }
+
+//private:
+ Handler handler_;
+ Arg1 arg1_;
+ Arg2 arg2_;
+ Arg3 arg3_;
+ Arg4 arg4_;
+};
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4>
+inline void* asio_handler_allocate(std::size_t size,
+ binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
+{
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
+{
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+}
+
+template <typename Function, typename Handler, typename Arg1, typename Arg2,
+ typename Arg3, typename Arg4>
+inline void asio_handler_invoke(const Function& function,
+ binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
+{
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4>
+inline binder4<Handler, Arg1, Arg2, Arg3, Arg4> bind_handler(
+ const Handler& handler, const Arg1& arg1, const Arg2& arg2,
+ const Arg3& arg3, const Arg4& arg4)
+{
+ return binder4<Handler, Arg1, Arg2, Arg3, Arg4>(handler, arg1, arg2, arg3,
+ arg4);
+}
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5>
+class binder5
+{
+public:
+ binder5(const Handler& handler, const Arg1& arg1, const Arg2& arg2,
+ const Arg3& arg3, const Arg4& arg4, const Arg5& arg5)
+ : handler_(handler),
+ arg1_(arg1),
+ arg2_(arg2),
+ arg3_(arg3),
+ arg4_(arg4),
+ arg5_(arg5)
+ {
+ }
+
+ void operator()()
+ {
+ handler_(arg1_, arg2_, arg3_, arg4_, arg5_);
+ }
+
+ void operator()() const
+ {
+ handler_(arg1_, arg2_, arg3_, arg4_, arg5_);
+ }
+
+//private:
+ Handler handler_;
+ Arg1 arg1_;
+ Arg2 arg2_;
+ Arg3 arg3_;
+ Arg4 arg4_;
+ Arg5 arg5_;
+};
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5>
+inline void* asio_handler_allocate(std::size_t size,
+ binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
+{
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
+{
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+}
+
+template <typename Function, typename Handler, typename Arg1, typename Arg2,
+ typename Arg3, typename Arg4, typename Arg5>
+inline void asio_handler_invoke(const Function& function,
+ binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
+{
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
+ typename Arg4, typename Arg5>
+inline binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5> bind_handler(
+ const Handler& handler, const Arg1& arg1, const Arg2& arg2,
+ const Arg3& arg3, const Arg4& arg4, const Arg5& arg5)
+{
+ return binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>(handler, arg1, arg2,
+ arg3, arg4, arg5);
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_BIND_HANDLER_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/buffer_resize_guard.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/buffer_resize_guard.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,72 @@
+//
+// buffer_resize_guard.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP
+#define BOOST_ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <limits>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// Helper class to manage buffer resizing in an exception safe way.
+template <typename Buffer>
+class buffer_resize_guard
+{
+public:
+ // Constructor.
+ buffer_resize_guard(Buffer& buffer)
+ : buffer_(buffer),
+ old_size_(buffer.size())
+ {
+ }
+
+ // Destructor rolls back the buffer resize unless commit was called.
+ ~buffer_resize_guard()
+ {
+ if (old_size_
+ != std::numeric_limits<size_t>::max BOOST_PREVENT_MACRO_SUBSTITUTION())
+ {
+ buffer_.resize(old_size_);
+ }
+ }
+
+ // Commit the resize transaction.
+ void commit()
+ {
+ old_size_
+ = std::numeric_limits<size_t>::max BOOST_PREVENT_MACRO_SUBSTITUTION();
+ }
+
+private:
+ // The buffer being managed.
+ Buffer& buffer_;
+
+ // The size of the buffer at the time the guard was constructed.
+ size_t old_size_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/buffered_stream_storage.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/buffered_stream_storage.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,129 @@
+//
+// buffered_stream_storage.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP
+#define BOOST_ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <cassert>
+#include <cstddef>
+#include <cstring>
+#include <vector>
+#include <boost/asio/detail/pop_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class buffered_stream_storage
+{
+public:
+ // The type of the bytes stored in the buffer.
+ typedef unsigned char byte_type;
+
+ // The type used for offsets into the buffer.
+ typedef std::size_t size_type;
+
+ // Constructor.
+ explicit buffered_stream_storage(std::size_t capacity)
+ : begin_offset_(0),
+ end_offset_(0),
+ buffer_(capacity)
+ {
+ }
+
+ /// Clear the buffer.
+ void clear()
+ {
+ begin_offset_ = 0;
+ end_offset_ = 0;
+ }
+
+ // Return a pointer to the beginning of the unread data.
+ byte_type* data()
+ {
+ return &buffer_[0] + begin_offset_;
+ }
+
+ // Return a pointer to the beginning of the unread data.
+ const byte_type* data() const
+ {
+ return &buffer_[0] + begin_offset_;
+ }
+
+ // Is there no unread data in the buffer.
+ bool empty() const
+ {
+ return begin_offset_ == end_offset_;
+ }
+
+ // Return the amount of unread data the is in the buffer.
+ size_type size() const
+ {
+ return end_offset_ - begin_offset_;
+ }
+
+ // Resize the buffer to the specified length.
+ void resize(size_type length)
+ {
+ assert(length <= capacity());
+ if (begin_offset_ + length <= capacity())
+ {
+ end_offset_ = begin_offset_ + length;
+ }
+ else
+ {
+ using namespace std; // For memmove.
+ memmove(&buffer_[0], &buffer_[0] + begin_offset_, size());
+ end_offset_ = length;
+ begin_offset_ = 0;
+ }
+ }
+
+ // Return the maximum size for data in the buffer.
+ size_type capacity() const
+ {
+ return buffer_.size();
+ }
+
+ // Consume multiple bytes from the beginning of the buffer.
+ void consume(size_type count)
+ {
+ assert(begin_offset_ + count <= end_offset_);
+ begin_offset_ += count;
+ if (empty())
+ clear();
+ }
+
+private:
+ // The offset to the beginning of the unread data.
+ size_type begin_offset_;
+
+ // The offset to the end of the unread data.
+ size_type end_offset_;
+
+ // The data in the buffer.
+ std::vector<byte_type> buffer_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/call_stack.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/call_stack.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,92 @@
+//
+// call_stack.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_CALL_STACK_HPP
+#define BOOST_ASIO_DETAIL_CALL_STACK_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/tss_ptr.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// Helper class to determine whether or not the current thread is inside an
+// invocation of io_service::run() for a specified io_service object.
+template <typename Owner>
+class call_stack
+{
+public:
+ // Context class automatically pushes an owner on to the stack.
+ class context
+ : private noncopyable
+ {
+ public:
+ // Push the owner on to the stack.
+ explicit context(Owner* d)
+ : owner_(d),
+ next_(call_stack<Owner>::top_)
+ {
+ call_stack<Owner>::top_ = this;
+ }
+
+ // Pop the owner from the stack.
+ ~context()
+ {
+ call_stack<Owner>::top_ = next_;
+ }
+
+ private:
+ friend class call_stack<Owner>;
+
+ // The owner associated with the context.
+ Owner* owner_;
+
+ // The next element in the stack.
+ context* next_;
+ };
+
+ friend class context;
+
+ // Determine whether the specified owner is on the stack.
+ static bool contains(Owner* d)
+ {
+ context* elem = top_;
+ while (elem)
+ {
+ if (elem->owner_ == d)
+ return true;
+ elem = elem->next_;
+ }
+ return false;
+ }
+
+private:
+ // The top of the stack of calls for the current thread.
+ static tss_ptr<context> top_;
+};
+
+template <typename Owner>
+tss_ptr<typename call_stack<Owner>::context>
+call_stack<Owner>::top_;
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_CALL_STACK_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/const_buffers_iterator.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/const_buffers_iterator.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,153 @@
+//
+// const_buffers_iterator.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP
+#define BOOST_ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/buffer.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// A proxy iterator for a sub-range in a list of buffers.
+template <typename ConstBufferSequence>
+class const_buffers_iterator
+ : public boost::iterator_facade<const_buffers_iterator<ConstBufferSequence>,
+ const char, boost::bidirectional_traversal_tag>
+{
+public:
+ // Default constructor creates an iterator in an undefined state.
+ const_buffers_iterator()
+ {
+ }
+
+ // Create an iterator for the specified position.
+ const_buffers_iterator(const ConstBufferSequence& buffers,
+ std::size_t position)
+ : begin_(buffers.begin()),
+ current_(buffers.begin()),
+ end_(buffers.end()),
+ position_(0)
+ {
+ while (current_ != end_)
+ {
+ current_buffer_ = *current_;
+ std::size_t buffer_size = boost::asio::buffer_size(current_buffer_);
+ if (position - position_ < buffer_size)
+ {
+ current_buffer_position_ = position - position_;
+ position_ = position;
+ return;
+ }
+ position_ += buffer_size;
+ ++current_;
+ }
+ current_buffer_ = boost::asio::const_buffer();
+ current_buffer_position_ = 0;
+ }
+
+ std::size_t position() const
+ {
+ return position_;
+ }
+
+private:
+ friend class boost::iterator_core_access;
+
+ void increment()
+ {
+ if (current_ == end_)
+ return;
+
+ ++position_;
+
+ ++current_buffer_position_;
+ if (current_buffer_position_ != boost::asio::buffer_size(current_buffer_))
+ return;
+
+ ++current_;
+ current_buffer_position_ = 0;
+ while (current_ != end_)
+ {
+ current_buffer_ = *current_;
+ if (boost::asio::buffer_size(current_buffer_) > 0)
+ return;
+ ++current_;
+ }
+ }
+
+ void decrement()
+ {
+ if (position_ == 0)
+ return;
+
+ --position_;
+
+ if (current_buffer_position_ != 0)
+ {
+ --current_buffer_position_;
+ return;
+ }
+
+ typename ConstBufferSequence::const_iterator iter = current_;
+ while (iter != begin_)
+ {
+ --iter;
+ boost::asio::const_buffer buffer = *iter;
+ std::size_t buffer_size = boost::asio::buffer_size(buffer);
+ if (buffer_size > 0)
+ {
+ current_ = iter;
+ current_buffer_ = buffer;
+ current_buffer_position_ = buffer_size - 1;
+ return;
+ }
+ }
+ }
+
+ bool equal(const const_buffers_iterator& other) const
+ {
+ return position_ == other.position_;
+ }
+
+ const char& dereference() const
+ {
+ return boost::asio::buffer_cast<const char*>(
+ current_buffer_)[current_buffer_position_];
+ }
+
+ boost::asio::const_buffer current_buffer_;
+ std::size_t current_buffer_position_;
+ typename ConstBufferSequence::const_iterator begin_;
+ typename ConstBufferSequence::const_iterator current_;
+ typename ConstBufferSequence::const_iterator end_;
+ std::size_t position_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/consuming_buffers.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/consuming_buffers.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,227 @@
+//
+// consuming_buffers.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_HPP
+#define BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <algorithm>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/buffer.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// A proxy iterator for a sub-range in a list of buffers.
+template <typename Buffer, typename Buffer_Iterator>
+class consuming_buffers_iterator
+ : public boost::iterator_facade<
+ consuming_buffers_iterator<Buffer, Buffer_Iterator>,
+ const Buffer, boost::forward_traversal_tag>
+{
+public:
+ // Default constructor creates an end iterator.
+ consuming_buffers_iterator()
+ : at_end_(true)
+ {
+ }
+
+ // Construct with a buffer for the first entry and an iterator
+ // range for the remaining entries.
+ consuming_buffers_iterator(bool at_end, const Buffer& first,
+ Buffer_Iterator begin_remainder, Buffer_Iterator end_remainder)
+ : at_end_(at_end),
+ first_(buffer(first, max_size)),
+ begin_remainder_(begin_remainder),
+ end_remainder_(end_remainder),
+ offset_(0)
+ {
+ }
+
+private:
+ friend class boost::iterator_core_access;
+
+ enum { max_size = 65536 };
+
+ void increment()
+ {
+ if (!at_end_)
+ {
+ if (begin_remainder_ == end_remainder_
+ || offset_ + buffer_size(first_) >= max_size)
+ {
+ at_end_ = true;
+ }
+ else
+ {
+ offset_ += buffer_size(first_);
+ first_ = buffer(*begin_remainder_++, max_size - offset_);
+ }
+ }
+ }
+
+ bool equal(const consuming_buffers_iterator& other) const
+ {
+ if (at_end_ && other.at_end_)
+ return true;
+ return !at_end_ && !other.at_end_
+ && buffer_cast<const void*>(first_)
+ == buffer_cast<const void*>(other.first_)
+ && buffer_size(first_) == buffer_size(other.first_)
+ && begin_remainder_ == other.begin_remainder_
+ && end_remainder_ == other.end_remainder_;
+ }
+
+ const Buffer& dereference() const
+ {
+ return first_;
+ }
+
+ bool at_end_;
+ Buffer first_;
+ Buffer_Iterator begin_remainder_;
+ Buffer_Iterator end_remainder_;
+ std::size_t offset_;
+};
+
+// A proxy for a sub-range in a list of buffers.
+template <typename Buffer, typename Buffers>
+class consuming_buffers
+{
+public:
+ // The type for each element in the list of buffers.
+ typedef Buffer value_type;
+
+ // A forward-only iterator type that may be used to read elements.
+ typedef consuming_buffers_iterator<Buffer, typename Buffers::const_iterator>
+ const_iterator;
+
+ // Construct to represent the entire list of buffers.
+ consuming_buffers(const Buffers& buffers)
+ : buffers_(buffers),
+ at_end_(buffers_.begin() == buffers_.end()),
+ first_(*buffers_.begin()),
+ begin_remainder_(buffers_.begin())
+ {
+ if (!at_end_)
+ ++begin_remainder_;
+ }
+
+ // Copy constructor.
+ consuming_buffers(const consuming_buffers& other)
+ : buffers_(other.buffers_),
+ at_end_(other.at_end_),
+ first_(other.first_),
+ begin_remainder_(buffers_.begin())
+ {
+ typename Buffers::const_iterator first = other.buffers_.begin();
+ typename Buffers::const_iterator second = other.begin_remainder_;
+ std::advance(begin_remainder_, std::distance(first, second));
+ }
+
+ // Assignment operator.
+ consuming_buffers& operator=(const consuming_buffers& other)
+ {
+ buffers_ = other.buffers_;
+ at_end_ = other.at_end_;
+ first_ = other.first_;
+ begin_remainder_ = buffers_.begin();
+ typename Buffers::const_iterator first = other.buffers_.begin();
+ typename Buffers::const_iterator second = other.begin_remainder_;
+ std::advance(begin_remainder_, std::distance(first, second));
+ return *this;
+ }
+
+ // Get a forward-only iterator to the first element.
+ const_iterator begin() const
+ {
+ return const_iterator(at_end_, first_, begin_remainder_, buffers_.end());
+ }
+
+ // Get a forward-only iterator for one past the last element.
+ const_iterator end() const
+ {
+ return const_iterator();
+ }
+
+ // Consume the specified number of bytes from the buffers.
+ void consume(std::size_t size)
+ {
+ // Remove buffers from the start until the specified size is reached.
+ while (size > 0 && !at_end_)
+ {
+ if (buffer_size(first_) <= size)
+ {
+ size -= buffer_size(first_);
+ if (begin_remainder_ == buffers_.end())
+ at_end_ = true;
+ else
+ first_ = *begin_remainder_++;
+ }
+ else
+ {
+ first_ = first_ + size;
+ size = 0;
+ }
+ }
+
+ // Remove any more empty buffers at the start.
+ while (!at_end_ && buffer_size(first_) == 0)
+ {
+ if (begin_remainder_ == buffers_.end())
+ at_end_ = true;
+ else
+ first_ = *begin_remainder_++;
+ }
+ }
+
+private:
+ Buffers buffers_;
+ bool at_end_;
+ Buffer first_;
+ typename Buffers::const_iterator begin_remainder_;
+};
+
+// Specialisation for null_buffers to ensure that the null_buffers type is
+// always passed through to the underlying read or write operation.
+template <typename Buffer>
+class consuming_buffers<Buffer, boost::asio::null_buffers>
+ : public boost::asio::null_buffers
+{
+public:
+ consuming_buffers(const boost::asio::null_buffers&)
+ {
+ // No-op.
+ }
+
+ void consume(std::size_t)
+ {
+ // No-op.
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_CONSUMING_BUFFERS_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/deadline_timer_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/deadline_timer_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,202 @@
+//
+// deadline_timer_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP
+#define BOOST_ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/handler_base_from_member.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/timer_queue.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Time_Traits, typename Timer_Scheduler>
+class deadline_timer_service
+ : public boost::asio::detail::service_base<
+ deadline_timer_service<Time_Traits, Timer_Scheduler> >
+{
+public:
+ // The time type.
+ typedef typename Time_Traits::time_type time_type;
+
+ // The duration type.
+ typedef typename Time_Traits::duration_type duration_type;
+
+ // The implementation type of the timer. This type is dependent on the
+ // underlying implementation of the timer service.
+ struct implementation_type
+ : private boost::asio::detail::noncopyable
+ {
+ time_type expiry;
+ bool might_have_pending_waits;
+ };
+
+ // Constructor.
+ deadline_timer_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ deadline_timer_service<Time_Traits, Timer_Scheduler> >(io_service),
+ scheduler_(boost::asio::use_service<Timer_Scheduler>(io_service))
+ {
+ scheduler_.add_timer_queue(timer_queue_);
+ }
+
+ // Destructor.
+ ~deadline_timer_service()
+ {
+ scheduler_.remove_timer_queue(timer_queue_);
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ // Construct a new timer implementation.
+ void construct(implementation_type& impl)
+ {
+ impl.expiry = time_type();
+ impl.might_have_pending_waits = false;
+ }
+
+ // Destroy a timer implementation.
+ void destroy(implementation_type& impl)
+ {
+ boost::system::error_code ec;
+ cancel(impl, ec);
+ }
+
+ // Cancel any asynchronous wait operations associated with the timer.
+ std::size_t cancel(implementation_type& impl, boost::system::error_code& ec)
+ {
+ if (!impl.might_have_pending_waits)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+ std::size_t count = scheduler_.cancel_timer(timer_queue_, &impl);
+ impl.might_have_pending_waits = false;
+ ec = boost::system::error_code();
+ return count;
+ }
+
+ // Get the expiry time for the timer as an absolute time.
+ time_type expires_at(const implementation_type& impl) const
+ {
+ return impl.expiry;
+ }
+
+ // Set the expiry time for the timer as an absolute time.
+ std::size_t expires_at(implementation_type& impl,
+ const time_type& expiry_time, boost::system::error_code& ec)
+ {
+ std::size_t count = cancel(impl, ec);
+ impl.expiry = expiry_time;
+ ec = boost::system::error_code();
+ return count;
+ }
+
+ // Get the expiry time for the timer relative to now.
+ duration_type expires_from_now(const implementation_type& impl) const
+ {
+ return Time_Traits::subtract(expires_at(impl), Time_Traits::now());
+ }
+
+ // Set the expiry time for the timer relative to now.
+ std::size_t expires_from_now(implementation_type& impl,
+ const duration_type& expiry_time, boost::system::error_code& ec)
+ {
+ return expires_at(impl,
+ Time_Traits::add(Time_Traits::now(), expiry_time), ec);
+ }
+
+ // Perform a blocking wait on the timer.
+ void wait(implementation_type& impl, boost::system::error_code& ec)
+ {
+ time_type now = Time_Traits::now();
+ while (Time_Traits::less_than(now, impl.expiry))
+ {
+ boost::posix_time::time_duration timeout =
+ Time_Traits::to_posix_duration(Time_Traits::subtract(impl.expiry, now));
+ ::timeval tv;
+ tv.tv_sec = timeout.total_seconds();
+ tv.tv_usec = timeout.total_microseconds() % 1000000;
+ boost::system::error_code ec;
+ socket_ops::select(0, 0, 0, 0, &tv, ec);
+ now = Time_Traits::now();
+ }
+ ec = boost::system::error_code();
+ }
+
+ template <typename Handler>
+ class wait_handler :
+ public handler_base_from_member<Handler>
+ {
+ public:
+ wait_handler(boost::asio::io_service& io_service, Handler handler)
+ : handler_base_from_member<Handler>(handler),
+ io_service_(io_service),
+ work_(io_service)
+ {
+ }
+
+ void operator()(const boost::system::error_code& result)
+ {
+ io_service_.post(detail::bind_handler(this->handler_, result));
+ }
+
+ private:
+ boost::asio::io_service& io_service_;
+ boost::asio::io_service::work work_;
+ };
+
+ // Start an asynchronous wait on the timer.
+ template <typename Handler>
+ void async_wait(implementation_type& impl, Handler handler)
+ {
+ impl.might_have_pending_waits = true;
+ scheduler_.schedule_timer(timer_queue_, impl.expiry,
+ wait_handler<Handler>(this->get_io_service(), handler), &impl);
+ }
+
+private:
+ // The queue of timers.
+ timer_queue<Time_Traits> timer_queue_;
+
+ // The object that schedules and executes timers. Usually a reactor.
+ Timer_Scheduler& scheduler_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/descriptor_ops.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/descriptor_ops.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,140 @@
+//
+// descriptor_ops.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_DESCRIPTOR_OPS_HPP
+#define BOOST_ASIO_DETAIL_DESCRIPTOR_OPS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <cerrno>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+namespace boost {
+namespace asio {
+namespace detail {
+namespace descriptor_ops {
+
+inline void clear_error(boost::system::error_code& ec)
+{
+ errno = 0;
+ ec = boost::system::error_code();
+}
+
+template <typename ReturnType>
+inline ReturnType error_wrapper(ReturnType return_value,
+ boost::system::error_code& ec)
+{
+ ec = boost::system::error_code(errno,
+ boost::asio::error::get_system_category());
+ return return_value;
+}
+
+inline int open(const char* path, int flags, boost::system::error_code& ec)
+{
+ clear_error(ec);
+ return error_wrapper(::open(path, flags), ec);
+}
+
+inline int close(int d, boost::system::error_code& ec)
+{
+ clear_error(ec);
+ return error_wrapper(::close(d), ec);
+}
+
+typedef iovec buf;
+
+inline void init_buf(buf& b, void* data, size_t size)
+{
+ b.iov_base = data;
+ b.iov_len = size;
+}
+
+inline void init_buf(buf& b, const void* data, size_t size)
+{
+ b.iov_base = const_cast<void*>(data);
+ b.iov_len = size;
+}
+
+inline int scatter_read(int d, buf* bufs, size_t count,
+ boost::system::error_code& ec)
+{
+ clear_error(ec);
+ return error_wrapper(::readv(d, bufs, static_cast<int>(count)), ec);
+}
+
+inline int gather_write(int d, const buf* bufs, size_t count,
+ boost::system::error_code& ec)
+{
+ clear_error(ec);
+ return error_wrapper(::writev(d, bufs, static_cast<int>(count)), ec);
+}
+
+inline int ioctl(int d, long cmd, ioctl_arg_type* arg,
+ boost::system::error_code& ec)
+{
+ clear_error(ec);
+ return error_wrapper(::ioctl(d, cmd, arg), ec);
+}
+
+inline int fcntl(int d, long cmd, boost::system::error_code& ec)
+{
+ clear_error(ec);
+ return error_wrapper(::fcntl(d, cmd), ec);
+}
+
+inline int fcntl(int d, long cmd, long arg, boost::system::error_code& ec)
+{
+ clear_error(ec);
+ return error_wrapper(::fcntl(d, cmd, arg), ec);
+}
+
+inline int poll_read(int d, boost::system::error_code& ec)
+{
+ clear_error(ec);
+ pollfd fds;
+ fds.fd = d;
+ fds.events = POLLIN;
+ fds.revents = 0;
+ clear_error(ec);
+ return error_wrapper(::poll(&fds, 1, -1), ec);
+}
+
+inline int poll_write(int d, boost::system::error_code& ec)
+{
+ clear_error(ec);
+ pollfd fds;
+ fds.fd = d;
+ fds.events = POLLOUT;
+ fds.revents = 0;
+ clear_error(ec);
+ return error_wrapper(::poll(&fds, 1, -1), ec);
+}
+
+} // namespace descriptor_ops
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_DESCRIPTOR_OPS_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/dev_poll_reactor.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/dev_poll_reactor.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,666 @@
+//
+// dev_poll_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_HPP
+#define BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/dev_poll_reactor_fwd.hpp>
+
+#if defined(BOOST_ASIO_HAS_DEV_POLL)
+
+#include <boost/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 <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/hash_map.hpp>
+#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/task_io_service.hpp>
+#include <boost/asio/detail/thread.hpp>
+#include <boost/asio/detail/reactor_op_queue.hpp>
+#include <boost/asio/detail/select_interrupter.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/signal_blocker.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/timer_queue.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <bool Own_Thread>
+class dev_poll_reactor
+ : public boost::asio::detail::service_base<dev_poll_reactor<Own_Thread> >
+{
+public:
+ // Per-descriptor data.
+ struct per_descriptor_data
+ {
+ };
+
+ // Constructor.
+ dev_poll_reactor(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ dev_poll_reactor<Own_Thread> >(io_service),
+ mutex_(),
+ dev_poll_fd_(do_dev_poll_create()),
+ wait_in_progress_(false),
+ interrupter_(),
+ read_op_queue_(),
+ write_op_queue_(),
+ except_op_queue_(),
+ pending_cancellations_(),
+ stop_thread_(false),
+ thread_(0),
+ shutdown_(false)
+ {
+ // Start the reactor's internal thread only if needed.
+ if (Own_Thread)
+ {
+ boost::asio::detail::signal_blocker sb;
+ thread_ = new boost::asio::detail::thread(
+ bind_handler(&dev_poll_reactor::call_run_thread, this));
+ }
+
+ // 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));
+ }
+
+ // Destructor.
+ ~dev_poll_reactor()
+ {
+ shutdown_service();
+ ::close(dev_poll_fd_);
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ shutdown_ = true;
+ stop_thread_ = true;
+ lock.unlock();
+
+ if (thread_)
+ {
+ interrupter_.interrupt();
+ thread_->join();
+ delete thread_;
+ thread_ = 0;
+ }
+
+ read_op_queue_.destroy_operations();
+ write_op_queue_.destroy_operations();
+ except_op_queue_.destroy_operations();
+
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ timer_queues_[i]->destroy_timers();
+ timer_queues_.clear();
+ }
+
+ // Register a socket with the reactor. Returns 0 on success, system error
+ // code on failure.
+ int register_descriptor(socket_type, per_descriptor_data&)
+ {
+ return 0;
+ }
+
+ // Start a new read operation. The handler object will be invoked when the
+ // given descriptor is ready to be read, or an error has occurred.
+ template <typename Handler>
+ void start_read_op(socket_type descriptor, per_descriptor_data&,
+ Handler handler, bool allow_speculative_read = true)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ if (shutdown_)
+ return;
+
+ if (allow_speculative_read)
+ {
+ if (!read_op_queue_.has_operation(descriptor))
+ {
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
+ return;
+ }
+ }
+ }
+
+ if (read_op_queue_.enqueue_operation(descriptor, handler))
+ {
+ ::pollfd& ev = add_pending_event_change(descriptor);
+ ev.events = POLLIN | POLLERR | POLLHUP;
+ if (write_op_queue_.has_operation(descriptor))
+ ev.events |= POLLOUT;
+ if (except_op_queue_.has_operation(descriptor))
+ ev.events |= POLLPRI;
+ interrupter_.interrupt();
+ }
+ }
+
+ // Start a new write operation. The handler object will be invoked when the
+ // given descriptor is ready to be written, or an error has occurred.
+ template <typename Handler>
+ void start_write_op(socket_type descriptor, per_descriptor_data&,
+ Handler handler, bool allow_speculative_write = true)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ if (shutdown_)
+ return;
+
+ if (allow_speculative_write)
+ {
+ if (!write_op_queue_.has_operation(descriptor))
+ {
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
+ return;
+ }
+ }
+ }
+
+ if (write_op_queue_.enqueue_operation(descriptor, handler))
+ {
+ ::pollfd& ev = add_pending_event_change(descriptor);
+ ev.events = POLLOUT | POLLERR | POLLHUP;
+ if (read_op_queue_.has_operation(descriptor))
+ ev.events |= POLLIN;
+ if (except_op_queue_.has_operation(descriptor))
+ ev.events |= POLLPRI;
+ interrupter_.interrupt();
+ }
+ }
+
+ // Start a new exception operation. The handler object will be invoked when
+ // the given descriptor has exception information, or an error has occurred.
+ template <typename Handler>
+ void start_except_op(socket_type descriptor,
+ per_descriptor_data&, Handler handler)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ if (shutdown_)
+ return;
+
+ if (except_op_queue_.enqueue_operation(descriptor, handler))
+ {
+ ::pollfd& ev = add_pending_event_change(descriptor);
+ ev.events = POLLPRI | POLLERR | POLLHUP;
+ if (read_op_queue_.has_operation(descriptor))
+ ev.events |= POLLIN;
+ if (write_op_queue_.has_operation(descriptor))
+ ev.events |= POLLOUT;
+ interrupter_.interrupt();
+ }
+ }
+
+ // Start a new write operation. The handler object will be invoked when the
+ // information available, or an error has occurred.
+ template <typename Handler>
+ void start_connect_op(socket_type descriptor,
+ per_descriptor_data&, Handler handler)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ if (shutdown_)
+ return;
+
+ if (write_op_queue_.enqueue_operation(descriptor, handler))
+ {
+ ::pollfd& ev = add_pending_event_change(descriptor);
+ ev.events = POLLOUT | POLLERR | POLLHUP;
+ if (read_op_queue_.has_operation(descriptor))
+ ev.events |= POLLIN;
+ if (except_op_queue_.has_operation(descriptor))
+ ev.events |= POLLPRI;
+ interrupter_.interrupt();
+ }
+ }
+
+ // 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&)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ cancel_ops_unlocked(descriptor);
+ }
+
+ // 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&)
+ {
+ boost::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);
+ }
+
+ // Add a new timer queue to the reactor.
+ template <typename Time_Traits>
+ void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ timer_queues_.push_back(&timer_queue);
+ }
+
+ // Remove a timer queue from the reactor.
+ template <typename Time_Traits>
+ void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ {
+ if (timer_queues_[i] == &timer_queue)
+ {
+ timer_queues_.erase(timer_queues_.begin() + i);
+ return;
+ }
+ }
+ }
+
+ // Schedule a timer in the given timer queue to expire at the specified
+ // absolute time. The handler object will be invoked when the timer expires.
+ template <typename Time_Traits, typename Handler>
+ void schedule_timer(timer_queue<Time_Traits>& timer_queue,
+ const typename Time_Traits::time_type& time, Handler handler, void* token)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ if (!shutdown_)
+ if (timer_queue.enqueue_timer(time, handler, token))
+ interrupter_.interrupt();
+ }
+
+ // Cancel the timer associated with the given token. Returns the number of
+ // handlers that have been posted or dispatched.
+ template <typename Time_Traits>
+ std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ std::size_t n = timer_queue.cancel_timer(token);
+ if (n > 0)
+ interrupter_.interrupt();
+ return n;
+ }
+
+private:
+ friend class task_io_service<dev_poll_reactor<Own_Thread> >;
+
+ // Run /dev/poll once until interrupted or events are ready to be dispatched.
+ void run(bool block)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ // Dispatch any operation cancellations that were made while the select
+ // loop was not running.
+ read_op_queue_.perform_cancellations();
+ write_op_queue_.perform_cancellations();
+ except_op_queue_.perform_cancellations();
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ timer_queues_[i]->dispatch_cancellations();
+
+ // Check if the thread is supposed to stop.
+ if (stop_thread_)
+ {
+ complete_operations_and_timers(lock);
+ return;
+ }
+
+ // We can return immediately if there's no work to do and the reactor is
+ // not supposed to block.
+ if (!block && read_op_queue_.empty() && write_op_queue_.empty()
+ && except_op_queue_.empty() && all_timer_queues_are_empty())
+ {
+ complete_operations_and_timers(lock);
+ return;
+ }
+
+ // Write the pending event registration changes to the /dev/poll descriptor.
+ std::size_t events_size = sizeof(::pollfd) * pending_event_changes_.size();
+ errno = 0;
+ int result = ::write(dev_poll_fd_,
+ &pending_event_changes_[0], events_size);
+ if (result != static_cast<int>(events_size))
+ {
+ for (std::size_t i = 0; i < pending_event_changes_.size(); ++i)
+ {
+ int descriptor = pending_event_changes_[i].fd;
+ boost::system::error_code ec = boost::system::error_code(
+ errno, boost::asio::error::get_system_category());
+ read_op_queue_.perform_all_operations(descriptor, ec);
+ write_op_queue_.perform_all_operations(descriptor, ec);
+ except_op_queue_.perform_all_operations(descriptor, ec);
+ }
+ }
+ pending_event_changes_.clear();
+ pending_event_change_index_.clear();
+
+ int timeout = block ? get_timeout() : 0;
+ wait_in_progress_ = true;
+ 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();
+ wait_in_progress_ = false;
+
+ // Block signals while performing operations.
+ boost::asio::detail::signal_blocker sb;
+
+ // 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;
+ boost::system::error_code ec;
+
+ // 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 = except_op_queue_.perform_operation(descriptor, ec);
+ else
+ more_except = except_op_queue_.has_operation(descriptor);
+
+ if (events[i].events & (POLLIN | POLLERR | POLLHUP))
+ more_reads = read_op_queue_.perform_operation(descriptor, ec);
+ else
+ more_reads = read_op_queue_.has_operation(descriptor);
+
+ if (events[i].events & (POLLOUT | POLLERR | POLLHUP))
+ more_writes = write_op_queue_.perform_operation(descriptor, ec);
+ else
+ more_writes = write_op_queue_.has_operation(descriptor);
+
+ if ((events[i].events == POLLHUP)
+ && !more_except && !more_reads && !more_writes)
+ {
+ // If we have only an POLLHUP event and no operations associated
+ // with the descriptor then we need to delete the descriptor from
+ // /dev/poll. The poll operation might produce POLLHUP events even
+ // if they are not specifically requested, 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))
+ {
+ ec = boost::system::error_code(errno,
+ boost::asio::error::get_system_category());
+ read_op_queue_.perform_all_operations(descriptor, ec);
+ write_op_queue_.perform_all_operations(descriptor, ec);
+ except_op_queue_.perform_all_operations(descriptor, ec);
+ }
+ }
+ }
+ }
+ read_op_queue_.perform_cancellations();
+ write_op_queue_.perform_cancellations();
+ except_op_queue_.perform_cancellations();
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ {
+ timer_queues_[i]->dispatch_timers();
+ timer_queues_[i]->dispatch_cancellations();
+ }
+
+ // Issue any pending cancellations.
+ for (size_t i = 0; i < pending_cancellations_.size(); ++i)
+ cancel_ops_unlocked(pending_cancellations_[i]);
+ pending_cancellations_.clear();
+
+ complete_operations_and_timers(lock);
+ }
+
+ // Run the select loop in the thread.
+ void run_thread()
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ while (!stop_thread_)
+ {
+ lock.unlock();
+ run(true);
+ lock.lock();
+ }
+ }
+
+ // Entry point for the select loop thread.
+ static void call_run_thread(dev_poll_reactor* reactor)
+ {
+ reactor->run_thread();
+ }
+
+ // Interrupt the select loop.
+ void interrupt()
+ {
+ interrupter_.interrupt();
+ }
+
+ // 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(
+ boost::system::system_error(
+ boost::system::error_code(errno,
+ boost::asio::error::get_system_category()),
+ "/dev/poll"));
+ }
+ return fd;
+ }
+
+ // Check if all timer queues are empty.
+ bool all_timer_queues_are_empty() const
+ {
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ if (!timer_queues_[i]->empty())
+ return false;
+ return true;
+ }
+
+ // 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()
+ {
+ if (all_timer_queues_are_empty())
+ return -1;
+
+ // 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.
+ boost::posix_time::time_duration minimum_wait_duration
+ = boost::posix_time::minutes(5);
+
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ {
+ boost::posix_time::time_duration wait_duration
+ = timer_queues_[i]->wait_duration();
+ if (wait_duration < minimum_wait_duration)
+ minimum_wait_duration = wait_duration;
+ }
+
+ if (minimum_wait_duration > boost::posix_time::time_duration())
+ {
+ int milliseconds = minimum_wait_duration.total_milliseconds();
+ return milliseconds > 0 ? milliseconds : 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ // 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)
+ {
+ bool interrupt = read_op_queue_.cancel_operations(descriptor);
+ interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt;
+ interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt;
+ if (interrupt)
+ interrupter_.interrupt();
+ }
+
+ // Clean up operations and timers. We must not hold the lock since the
+ // destructors may make calls back into this reactor. We make a copy of the
+ // vector of timer queues since the original may be modified while the lock
+ // is not held.
+ void complete_operations_and_timers(
+ boost::asio::detail::mutex::scoped_lock& lock)
+ {
+ timer_queues_for_cleanup_ = timer_queues_;
+ lock.unlock();
+ read_op_queue_.complete_operations();
+ write_op_queue_.complete_operations();
+ except_op_queue_.complete_operations();
+ for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i)
+ timer_queues_for_cleanup_[i]->complete_timers();
+ }
+
+ // 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];
+ }
+ }
+
+ // Mutex to protect access to internal data.
+ boost::asio::detail::mutex mutex_;
+
+ // The /dev/poll file descriptor.
+ int dev_poll_fd_;
+
+ // Vector of /dev/poll events waiting to be written to the descriptor.
+ std::vector< ::pollfd> pending_event_changes_;
+
+ // Hash map to associate a descriptor with a pending event change index.
+ hash_map<int, std::size_t> pending_event_change_index_;
+
+ // Whether the DP_POLL operation is currently in progress
+ bool wait_in_progress_;
+
+ // The interrupter is used to break a blocking DP_POLL operation.
+ select_interrupter interrupter_;
+
+ // The queue of read operations.
+ reactor_op_queue<socket_type> read_op_queue_;
+
+ // The queue of write operations.
+ reactor_op_queue<socket_type> write_op_queue_;
+
+ // The queue of except operations.
+ reactor_op_queue<socket_type> except_op_queue_;
+
+ // The timer queues.
+ std::vector<timer_queue_base*> timer_queues_;
+
+ // A copy of the timer queues, used when cleaning up timers. The copy is
+ // stored as a class data member to avoid unnecessary memory allocation.
+ std::vector<timer_queue_base*> timer_queues_for_cleanup_;
+
+ // The descriptors that are pending cancellation.
+ std::vector<socket_type> pending_cancellations_;
+
+ // Does the reactor loop thread need to stop.
+ bool stop_thread_;
+
+ // The thread that is running the reactor loop.
+ boost::asio::detail::thread* thread_;
+
+ // Whether the service has been shut down.
+ bool shutdown_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_DEV_POLL)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/dev_poll_reactor_fwd.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/dev_poll_reactor_fwd.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,42 @@
+//
+// dev_poll_reactor_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP
+#define BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#if !defined(BOOST_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 BOOST_ASIO_HAS_DEV_POLL 1
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <bool Own_Thread>
+class dev_poll_reactor;
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(__sun)
+#endif // !defined(BOOST_ASIO_DISABLE_DEV_POLL)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_DEV_POLL_REACTOR_FWD_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/epoll_reactor.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/epoll_reactor.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,722 @@
+//
+// epoll_reactor.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_EPOLL_REACTOR_HPP
+#define BOOST_ASIO_DETAIL_EPOLL_REACTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/epoll_reactor_fwd.hpp>
+
+#if defined(BOOST_ASIO_HAS_EPOLL)
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <vector>
+#include <sys/epoll.h>
+#include <boost/config.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/hash_map.hpp>
+#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/task_io_service.hpp>
+#include <boost/asio/detail/thread.hpp>
+#include <boost/asio/detail/reactor_op_queue.hpp>
+#include <boost/asio/detail/select_interrupter.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/signal_blocker.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/timer_queue.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <bool Own_Thread>
+class epoll_reactor
+ : public boost::asio::detail::service_base<epoll_reactor<Own_Thread> >
+{
+public:
+ // Per-descriptor data.
+ struct per_descriptor_data
+ {
+ bool allow_speculative_read;
+ bool allow_speculative_write;
+ };
+
+ // Constructor.
+ epoll_reactor(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<epoll_reactor<Own_Thread> >(io_service),
+ mutex_(),
+ epoll_fd_(do_epoll_create()),
+ wait_in_progress_(false),
+ interrupter_(),
+ read_op_queue_(),
+ write_op_queue_(),
+ except_op_queue_(),
+ pending_cancellations_(),
+ stop_thread_(false),
+ thread_(0),
+ shutdown_(false),
+ need_epoll_wait_(true)
+ {
+ // Start the reactor's internal thread only if needed.
+ if (Own_Thread)
+ {
+ boost::asio::detail::signal_blocker sb;
+ thread_ = new boost::asio::detail::thread(
+ bind_handler(&epoll_reactor::call_run_thread, this));
+ }
+
+ // Add the interrupter's descriptor to epoll.
+ epoll_event ev = { 0, { 0 } };
+ ev.events = EPOLLIN | EPOLLERR;
+ ev.data.fd = interrupter_.read_descriptor();
+ epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev);
+ }
+
+ // Destructor.
+ ~epoll_reactor()
+ {
+ shutdown_service();
+ close(epoll_fd_);
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ shutdown_ = true;
+ stop_thread_ = true;
+ lock.unlock();
+
+ if (thread_)
+ {
+ interrupter_.interrupt();
+ thread_->join();
+ delete thread_;
+ thread_ = 0;
+ }
+
+ read_op_queue_.destroy_operations();
+ write_op_queue_.destroy_operations();
+ except_op_queue_.destroy_operations();
+
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ timer_queues_[i]->destroy_timers();
+ timer_queues_.clear();
+ }
+
+ // 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)
+ {
+ // No need to lock according to epoll documentation.
+
+ descriptor_data.allow_speculative_read = true;
+ descriptor_data.allow_speculative_write = true;
+
+ epoll_event ev = { 0, { 0 } };
+ ev.events = 0;
+ ev.data.fd = descriptor;
+ int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
+ if (result != 0)
+ return errno;
+ return 0;
+ }
+
+ // Start a new read operation. The handler object will be invoked when the
+ // given descriptor is ready to be read, or an error has occurred.
+ template <typename Handler>
+ void start_read_op(socket_type descriptor,
+ per_descriptor_data& descriptor_data,
+ Handler handler, bool allow_speculative_read = true)
+ {
+ if (allow_speculative_read && descriptor_data.allow_speculative_read)
+ {
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
+ return;
+ }
+
+ // We only get one shot at a speculative read in this function.
+ allow_speculative_read = false;
+ }
+
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ if (shutdown_)
+ return;
+
+ if (!allow_speculative_read)
+ need_epoll_wait_ = true;
+ else if (!read_op_queue_.has_operation(descriptor))
+ {
+ // Speculative reads are ok as there are no queued read operations.
+ descriptor_data.allow_speculative_read = true;
+
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
+ return;
+ }
+ }
+
+ // Speculative reads are not ok as there will be queued read operations.
+ descriptor_data.allow_speculative_read = false;
+
+ if (read_op_queue_.enqueue_operation(descriptor, handler))
+ {
+ epoll_event ev = { 0, { 0 } };
+ ev.events = EPOLLIN | EPOLLERR | EPOLLHUP;
+ if (write_op_queue_.has_operation(descriptor))
+ ev.events |= EPOLLOUT;
+ if (except_op_queue_.has_operation(descriptor))
+ ev.events |= EPOLLPRI;
+ ev.data.fd = descriptor;
+
+ int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
+ if (result != 0 && errno == ENOENT)
+ result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
+ if (result != 0)
+ {
+ boost::system::error_code ec(errno,
+ boost::asio::error::get_system_category());
+ read_op_queue_.perform_all_operations(descriptor, ec);
+ }
+ }
+ }
+
+ // Start a new write operation. The handler object will be invoked when the
+ // given descriptor is ready to be written, or an error has occurred.
+ template <typename Handler>
+ void start_write_op(socket_type descriptor,
+ per_descriptor_data& descriptor_data,
+ Handler handler, bool allow_speculative_write = true)
+ {
+ if (allow_speculative_write && descriptor_data.allow_speculative_write)
+ {
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
+ return;
+ }
+
+ // We only get one shot at a speculative write in this function.
+ allow_speculative_write = false;
+ }
+
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ if (shutdown_)
+ return;
+
+ if (!allow_speculative_write)
+ need_epoll_wait_ = true;
+ else if (!write_op_queue_.has_operation(descriptor))
+ {
+ // Speculative writes are ok as there are no queued write operations.
+ descriptor_data.allow_speculative_write = true;
+
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
+ return;
+ }
+ }
+
+ // Speculative writes are not ok as there will be queued write operations.
+ descriptor_data.allow_speculative_write = false;
+
+ if (write_op_queue_.enqueue_operation(descriptor, handler))
+ {
+ epoll_event ev = { 0, { 0 } };
+ ev.events = EPOLLOUT | EPOLLERR | EPOLLHUP;
+ if (read_op_queue_.has_operation(descriptor))
+ ev.events |= EPOLLIN;
+ if (except_op_queue_.has_operation(descriptor))
+ ev.events |= EPOLLPRI;
+ ev.data.fd = descriptor;
+
+ int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
+ if (result != 0 && errno == ENOENT)
+ result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
+ if (result != 0)
+ {
+ boost::system::error_code ec(errno,
+ boost::asio::error::get_system_category());
+ write_op_queue_.perform_all_operations(descriptor, ec);
+ }
+ }
+ }
+
+ // Start a new exception operation. The handler object will be invoked when
+ // the given descriptor has exception information, or an error has occurred.
+ template <typename Handler>
+ void start_except_op(socket_type descriptor,
+ per_descriptor_data&, Handler handler)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ if (shutdown_)
+ return;
+
+ if (except_op_queue_.enqueue_operation(descriptor, handler))
+ {
+ epoll_event ev = { 0, { 0 } };
+ ev.events = EPOLLPRI | EPOLLERR | EPOLLHUP;
+ if (read_op_queue_.has_operation(descriptor))
+ ev.events |= EPOLLIN;
+ if (write_op_queue_.has_operation(descriptor))
+ ev.events |= EPOLLOUT;
+ ev.data.fd = descriptor;
+
+ int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
+ if (result != 0 && errno == ENOENT)
+ result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
+ if (result != 0)
+ {
+ boost::system::error_code ec(errno,
+ boost::asio::error::get_system_category());
+ except_op_queue_.perform_all_operations(descriptor, ec);
+ }
+ }
+ }
+
+ // Start a new write operation. The handler object will be invoked when the
+ // given descriptor is ready for writing or an error has occurred. Speculative
+ // writes are not allowed.
+ template <typename Handler>
+ void start_connect_op(socket_type descriptor,
+ per_descriptor_data& descriptor_data, Handler handler)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ if (shutdown_)
+ return;
+
+ // Speculative writes are not ok as there will be queued write operations.
+ descriptor_data.allow_speculative_write = false;
+
+ if (write_op_queue_.enqueue_operation(descriptor, handler))
+ {
+ epoll_event ev = { 0, { 0 } };
+ ev.events = EPOLLOUT | EPOLLERR | EPOLLHUP;
+ if (read_op_queue_.has_operation(descriptor))
+ ev.events |= EPOLLIN;
+ if (except_op_queue_.has_operation(descriptor))
+ ev.events |= EPOLLPRI;
+ ev.data.fd = descriptor;
+
+ int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
+ if (result != 0 && errno == ENOENT)
+ result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
+ if (result != 0)
+ {
+ boost::system::error_code ec(errno,
+ boost::asio::error::get_system_category());
+ write_op_queue_.perform_all_operations(descriptor, ec);
+ }
+ }
+ }
+
+ // 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&)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ cancel_ops_unlocked(descriptor);
+ }
+
+ // 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&)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ // Remove the descriptor from epoll.
+ epoll_event ev = { 0, { 0 } };
+ epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev);
+
+ // Cancel any outstanding operations associated with the descriptor.
+ cancel_ops_unlocked(descriptor);
+ }
+
+ // Add a new timer queue to the reactor.
+ template <typename Time_Traits>
+ void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ timer_queues_.push_back(&timer_queue);
+ }
+
+ // Remove a timer queue from the reactor.
+ template <typename Time_Traits>
+ void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ {
+ if (timer_queues_[i] == &timer_queue)
+ {
+ timer_queues_.erase(timer_queues_.begin() + i);
+ return;
+ }
+ }
+ }
+
+ // Schedule a timer in the given timer queue to expire at the specified
+ // absolute time. The handler object will be invoked when the timer expires.
+ template <typename Time_Traits, typename Handler>
+ void schedule_timer(timer_queue<Time_Traits>& timer_queue,
+ const typename Time_Traits::time_type& time, Handler handler, void* token)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ if (!shutdown_)
+ if (timer_queue.enqueue_timer(time, handler, token))
+ interrupter_.interrupt();
+ }
+
+ // Cancel the timer associated with the given token. Returns the number of
+ // handlers that have been posted or dispatched.
+ template <typename Time_Traits>
+ std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ std::size_t n = timer_queue.cancel_timer(token);
+ if (n > 0)
+ interrupter_.interrupt();
+ return n;
+ }
+
+private:
+ friend class task_io_service<epoll_reactor<Own_Thread> >;
+
+ // Run epoll once until interrupted or events are ready to be dispatched.
+ void run(bool block)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ // Dispatch any operation cancellations that were made while the select
+ // loop was not running.
+ read_op_queue_.perform_cancellations();
+ write_op_queue_.perform_cancellations();
+ except_op_queue_.perform_cancellations();
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ timer_queues_[i]->dispatch_cancellations();
+
+ // Check if the thread is supposed to stop.
+ if (stop_thread_)
+ {
+ complete_operations_and_timers(lock);
+ return;
+ }
+
+ // We can return immediately if there's no work to do and the reactor is
+ // not supposed to block.
+ if (!block && read_op_queue_.empty() && write_op_queue_.empty()
+ && except_op_queue_.empty() && all_timer_queues_are_empty())
+ {
+ complete_operations_and_timers(lock);
+ return;
+ }
+
+ int timeout = block ? get_timeout() : 0;
+ wait_in_progress_ = true;
+ lock.unlock();
+
+ // Block on the epoll descriptor.
+ epoll_event events[128];
+ int num_events = (block || need_epoll_wait_)
+ ? epoll_wait(epoll_fd_, events, 128, timeout)
+ : 0;
+
+ lock.lock();
+ wait_in_progress_ = false;
+
+ // Block signals while performing operations.
+ boost::asio::detail::signal_blocker sb;
+
+ // Dispatch the waiting events.
+ for (int i = 0; i < num_events; ++i)
+ {
+ int descriptor = events[i].data.fd;
+ if (descriptor == interrupter_.read_descriptor())
+ {
+ interrupter_.reset();
+ }
+ else
+ {
+ bool more_reads = false;
+ bool more_writes = false;
+ bool more_except = false;
+ boost::system::error_code ec;
+
+ // Exception operations must be processed first to ensure that any
+ // out-of-band data is read before normal data.
+ if (events[i].events & (EPOLLPRI | EPOLLERR | EPOLLHUP))
+ more_except = except_op_queue_.perform_operation(descriptor, ec);
+ else
+ more_except = except_op_queue_.has_operation(descriptor);
+
+ if (events[i].events & (EPOLLIN | EPOLLERR | EPOLLHUP))
+ more_reads = read_op_queue_.perform_operation(descriptor, ec);
+ else
+ more_reads = read_op_queue_.has_operation(descriptor);
+
+ if (events[i].events & (EPOLLOUT | EPOLLERR | EPOLLHUP))
+ more_writes = write_op_queue_.perform_operation(descriptor, ec);
+ else
+ more_writes = write_op_queue_.has_operation(descriptor);
+
+ if ((events[i].events == EPOLLHUP)
+ && !more_except && !more_reads && !more_writes)
+ {
+ // If we have only an EPOLLHUP event and no operations associated
+ // with the descriptor then we need to delete the descriptor from
+ // epoll. The epoll_wait system call will produce EPOLLHUP events
+ // even if they are not specifically requested, so if we do not
+ // remove the descriptor we can end up in a tight loop of repeated
+ // calls to epoll_wait.
+ epoll_event ev = { 0, { 0 } };
+ epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev);
+ }
+ else
+ {
+ epoll_event ev = { 0, { 0 } };
+ ev.events = EPOLLERR | EPOLLHUP;
+ if (more_reads)
+ ev.events |= EPOLLIN;
+ if (more_writes)
+ ev.events |= EPOLLOUT;
+ if (more_except)
+ ev.events |= EPOLLPRI;
+ ev.data.fd = descriptor;
+ int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
+ if (result != 0 && errno == ENOENT)
+ result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);
+ if (result != 0)
+ {
+ ec = boost::system::error_code(errno,
+ boost::asio::error::get_system_category());
+ read_op_queue_.perform_all_operations(descriptor, ec);
+ write_op_queue_.perform_all_operations(descriptor, ec);
+ except_op_queue_.perform_all_operations(descriptor, ec);
+ }
+ }
+ }
+ }
+ read_op_queue_.perform_cancellations();
+ write_op_queue_.perform_cancellations();
+ except_op_queue_.perform_cancellations();
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ {
+ timer_queues_[i]->dispatch_timers();
+ timer_queues_[i]->dispatch_cancellations();
+ }
+
+ // Issue any pending cancellations.
+ for (size_t i = 0; i < pending_cancellations_.size(); ++i)
+ cancel_ops_unlocked(pending_cancellations_[i]);
+ pending_cancellations_.clear();
+
+ // Determine whether epoll_wait should be called when the reactor next runs.
+ need_epoll_wait_ = !read_op_queue_.empty()
+ || !write_op_queue_.empty() || !except_op_queue_.empty();
+
+ complete_operations_and_timers(lock);
+ }
+
+ // Run the select loop in the thread.
+ void run_thread()
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ while (!stop_thread_)
+ {
+ lock.unlock();
+ run(true);
+ lock.lock();
+ }
+ }
+
+ // Entry point for the select loop thread.
+ static void call_run_thread(epoll_reactor* reactor)
+ {
+ reactor->run_thread();
+ }
+
+ // Interrupt the select loop.
+ void interrupt()
+ {
+ interrupter_.interrupt();
+ }
+
+ // The hint to pass to epoll_create to size its data structures.
+ enum { epoll_size = 20000 };
+
+ // 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(
+ boost::system::system_error(
+ boost::system::error_code(errno,
+ boost::asio::error::get_system_category()),
+ "epoll"));
+ }
+ return fd;
+ }
+
+ // Check if all timer queues are empty.
+ bool all_timer_queues_are_empty() const
+ {
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ if (!timer_queues_[i]->empty())
+ return false;
+ return true;
+ }
+
+ // 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()
+ {
+ if (all_timer_queues_are_empty())
+ return -1;
+
+ // 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.
+ boost::posix_time::time_duration minimum_wait_duration
+ = boost::posix_time::minutes(5);
+
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ {
+ boost::posix_time::time_duration wait_duration
+ = timer_queues_[i]->wait_duration();
+ if (wait_duration < minimum_wait_duration)
+ minimum_wait_duration = wait_duration;
+ }
+
+ if (minimum_wait_duration > boost::posix_time::time_duration())
+ {
+ int milliseconds = minimum_wait_duration.total_milliseconds();
+ return milliseconds > 0 ? milliseconds : 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ // 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 epoll_reactor's mutex.
+ void cancel_ops_unlocked(socket_type descriptor)
+ {
+ bool interrupt = read_op_queue_.cancel_operations(descriptor);
+ interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt;
+ interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt;
+ if (interrupt)
+ interrupter_.interrupt();
+ }
+
+ // Clean up operations and timers. We must not hold the lock since the
+ // destructors may make calls back into this reactor. We make a copy of the
+ // vector of timer queues since the original may be modified while the lock
+ // is not held.
+ void complete_operations_and_timers(
+ boost::asio::detail::mutex::scoped_lock& lock)
+ {
+ timer_queues_for_cleanup_ = timer_queues_;
+ lock.unlock();
+ read_op_queue_.complete_operations();
+ write_op_queue_.complete_operations();
+ except_op_queue_.complete_operations();
+ for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i)
+ timer_queues_for_cleanup_[i]->complete_timers();
+ }
+
+ // Mutex to protect access to internal data.
+ boost::asio::detail::mutex mutex_;
+
+ // The epoll file descriptor.
+ int epoll_fd_;
+
+ // Whether the epoll_wait call is currently in progress
+ bool wait_in_progress_;
+
+ // The interrupter is used to break a blocking epoll_wait call.
+ select_interrupter interrupter_;
+
+ // The queue of read operations.
+ reactor_op_queue<socket_type> read_op_queue_;
+
+ // The queue of write operations.
+ reactor_op_queue<socket_type> write_op_queue_;
+
+ // The queue of except operations.
+ reactor_op_queue<socket_type> except_op_queue_;
+
+ // The timer queues.
+ std::vector<timer_queue_base*> timer_queues_;
+
+ // A copy of the timer queues, used when cleaning up timers. The copy is
+ // stored as a class data member to avoid unnecessary memory allocation.
+ std::vector<timer_queue_base*> timer_queues_for_cleanup_;
+
+ // The descriptors that are pending cancellation.
+ std::vector<socket_type> pending_cancellations_;
+
+ // Does the reactor loop thread need to stop.
+ bool stop_thread_;
+
+ // The thread that is running the reactor loop.
+ boost::asio::detail::thread* thread_;
+
+ // Whether the service has been shut down.
+ bool shutdown_;
+
+ // Whether we need to call epoll_wait the next time the reactor is run.
+ bool need_epoll_wait_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_EPOLL)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_EPOLL_REACTOR_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/epoll_reactor_fwd.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/epoll_reactor_fwd.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,49 @@
+//
+// epoll_reactor_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP
+#define BOOST_ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#if !defined(BOOST_ASIO_DISABLE_EPOLL)
+#if defined(__linux__) // This service is only supported on Linux.
+
+#include <boost/asio/detail/push_options.hpp>
+#include <linux/version.h>
+#include <boost/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 BOOST_ASIO_HAS_EPOLL 1
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <bool Own_Thread>
+class epoll_reactor;
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // LINUX_VERSION_CODE >= KERNEL_VERSION (2,5,45)
+#endif // defined(__linux__)
+#endif // !defined(BOOST_ASIO_DISABLE_EPOLL)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/event.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/event.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,52 @@
+//
+// event.hpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_EVENT_HPP
+#define BOOST_ASIO_DETAIL_EVENT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if !defined(BOOST_HAS_THREADS)
+# include <boost/asio/detail/null_event.hpp>
+#elif defined(BOOST_WINDOWS)
+# include <boost/asio/detail/win_event.hpp>
+#elif defined(BOOST_HAS_PTHREADS)
+# include <boost/asio/detail/posix_event.hpp>
+#else
+# error Only Windows and POSIX are supported!
+#endif
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+#if !defined(BOOST_HAS_THREADS)
+typedef null_event event;
+#elif defined(BOOST_WINDOWS)
+typedef win_event event;
+#elif defined(BOOST_HAS_PTHREADS)
+typedef posix_event event;
+#endif
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_EVENT_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/fd_set_adapter.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/fd_set_adapter.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,43 @@
+//
+// fd_set_adapter.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_FD_SET_ADAPTER_HPP
+#define BOOST_ASIO_DETAIL_FD_SET_ADAPTER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/posix_fd_set_adapter.hpp>
+#include <boost/asio/detail/win_fd_set_adapter.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+typedef win_fd_set_adapter fd_set_adapter;
+#else
+typedef posix_fd_set_adapter fd_set_adapter;
+#endif
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_FD_SET_ADAPTER_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/handler_alloc_helpers.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/handler_alloc_helpers.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,258 @@
+//
+// handler_alloc_helpers.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP
+#define BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/handler_alloc_hook.hpp>
+#include <boost/asio/detail/noncopyable.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
+// boost_asio_handler_alloc_helpers namespace is defined here for that purpose.
+namespace boost_asio_handler_alloc_helpers {
+
+template <typename Handler>
+inline void* allocate(std::size_t s, Handler* h)
+{
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ return ::operator new(s);
+#else
+ using namespace boost::asio;
+ return asio_handler_allocate(s, h);
+#endif
+}
+
+template <typename Handler>
+inline void deallocate(void* p, std::size_t s, Handler* h)
+{
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ ::operator delete(p);
+#else
+ using namespace boost::asio;
+ asio_handler_deallocate(p, s, h);
+#endif
+}
+
+} // namespace boost_asio_handler_alloc_helpers
+
+namespace boost {
+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>(
+ boost_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_)
+ boost_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();
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer_, value_size, &handler_);
+ pointer_ = 0;
+ }
+ }
+
+private:
+ handler_type& handler_;
+ pointer_type pointer_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/handler_base_from_member.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/handler_base_from_member.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,78 @@
+//
+// handler_base_from_member.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP
+#define BOOST_ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// Base class for classes that need a handler data member. Forwards the custom
+// allocation and invocation hooks to the contained handler.
+template <typename Handler>
+class handler_base_from_member
+{
+public:
+ handler_base_from_member(Handler handler)
+ : handler_(handler)
+ {
+ }
+
+//protected:
+ Handler handler_;
+
+protected:
+ // Protected destructor to prevent deletion through this type.
+ ~handler_base_from_member()
+ {
+ }
+};
+
+template <typename Handler>
+inline void* asio_handler_allocate(std::size_t size,
+ handler_base_from_member<Handler>* this_handler)
+{
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+}
+
+template <typename Handler>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ handler_base_from_member<Handler>* this_handler)
+{
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+}
+
+template <typename Function, typename Handler>
+inline void asio_handler_invoke(const Function& function,
+ handler_base_from_member<Handler>* this_handler)
+{
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_HANDLER_BASE_FROM_MEMBER_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/handler_invoke_helpers.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/handler_invoke_helpers.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,47 @@
+//
+// handler_invoke_helpers.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP
+#define BOOST_ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/handler_invoke_hook.hpp>
+
+// Calls to asio_handler_invoke must be made from a namespace that does not
+// contain overloads of this function. The boost_asio_handler_invoke_helpers
+// namespace is defined here for that purpose.
+namespace boost_asio_handler_invoke_helpers {
+
+template <typename Function, typename Context>
+inline void invoke(const Function& function, Context* context)
+{
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+ Function tmp(function);
+ tmp();
+#else
+ using namespace boost::asio;
+ asio_handler_invoke(function, context);
+#endif
+}
+
+} // namespace boost_asio_handler_invoke_helpers
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/handler_queue.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/handler_queue.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,231 @@
+//
+// handler_queue.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_HANDLER_QUEUE_HPP
+#define BOOST_ASIO_DETAIL_HANDLER_QUEUE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class handler_queue
+ : private noncopyable
+{
+public:
+ // Base class for handlers in the queue.
+ class handler
+ : private noncopyable
+ {
+ public:
+ void invoke()
+ {
+ invoke_func_(this);
+ }
+
+ void destroy()
+ {
+ destroy_func_(this);
+ }
+
+ protected:
+ typedef void (*invoke_func_type)(handler*);
+ typedef void (*destroy_func_type)(handler*);
+
+ handler(invoke_func_type invoke_func,
+ destroy_func_type destroy_func)
+ : next_(0),
+ invoke_func_(invoke_func),
+ destroy_func_(destroy_func)
+ {
+ }
+
+ ~handler()
+ {
+ }
+
+ private:
+ friend class handler_queue;
+ handler* next_;
+ invoke_func_type invoke_func_;
+ destroy_func_type destroy_func_;
+ };
+
+ // Smart point to manager handler lifetimes.
+ class scoped_ptr
+ : private noncopyable
+ {
+ public:
+ explicit scoped_ptr(handler* h)
+ : handler_(h)
+ {
+ }
+
+ ~scoped_ptr()
+ {
+ if (handler_)
+ handler_->destroy();
+ }
+
+ handler* get() const
+ {
+ return handler_;
+ }
+
+ handler* release()
+ {
+ handler* tmp = handler_;
+ handler_ = 0;
+ return tmp;
+ }
+
+ private:
+ handler* handler_;
+ };
+
+ // Constructor.
+ handler_queue()
+ : front_(0),
+ back_(0)
+ {
+ }
+
+ // Wrap a handler to be pushed into the queue.
+ template <typename Handler>
+ static handler* wrap(Handler h)
+ {
+ // Allocate and construct an object to wrap the handler.
+ typedef handler_wrapper<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(h);
+ handler_ptr<alloc_traits> ptr(raw_ptr, h);
+ return ptr.release();
+ }
+
+ // Get the handler at the front of the queue.
+ handler* front()
+ {
+ return front_;
+ }
+
+ // Pop a handler from the front of the queue.
+ void pop()
+ {
+ if (front_)
+ {
+ handler* tmp = front_;
+ front_ = front_->next_;
+ if (front_ == 0)
+ back_ = 0;
+ tmp->next_= 0;
+ }
+ }
+
+ // Push a handler on to the back of the queue.
+ void push(handler* h)
+ {
+ h->next_ = 0;
+ if (back_)
+ {
+ back_->next_ = h;
+ back_ = h;
+ }
+ else
+ {
+ front_ = back_ = h;
+ }
+ }
+
+ // Whether the queue is empty.
+ bool empty() const
+ {
+ return front_ == 0;
+ }
+
+private:
+ // Template wrapper for handlers.
+ template <typename Handler>
+ class handler_wrapper
+ : public handler
+ {
+ public:
+ handler_wrapper(Handler h)
+ : handler(
+ &handler_wrapper<Handler>::do_call,
+ &handler_wrapper<Handler>::do_destroy),
+ handler_(h)
+ {
+ }
+
+ static void do_call(handler* base)
+ {
+ // Take ownership of the handler object.
+ typedef handler_wrapper<Handler> this_type;
+ this_type* h(static_cast<this_type*>(base));
+ typedef handler_alloc_traits<Handler, this_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(h->handler_, h);
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made.
+ Handler handler(h->handler_);
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+
+ // Make the upcall.
+ boost_asio_handler_invoke_helpers::invoke(handler, &handler);
+ }
+
+ static void do_destroy(handler* base)
+ {
+ // Take ownership of the handler object.
+ typedef handler_wrapper<Handler> this_type;
+ this_type* h(static_cast<this_type*>(base));
+ typedef handler_alloc_traits<Handler, this_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(h->handler_, h);
+
+ // 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_);
+ (void)handler;
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+ }
+
+ private:
+ Handler handler_;
+ };
+
+ // The front of the queue.
+ handler* front_;
+
+ // The back of the queue.
+ handler* back_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_HANDLER_QUEUE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/hash_map.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/hash_map.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,239 @@
+//
+// hash_map.hpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_HASH_MAP_HPP
+#define BOOST_ASIO_DETAIL_HASH_MAP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cassert>
+#include <list>
+#include <utility>
+#include <boost/functional/hash.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename T>
+inline std::size_t calculate_hash_value(const T& t)
+{
+ return boost::hash_value(t);
+}
+
+#if defined(_WIN64)
+inline std::size_t calculate_hash_value(SOCKET s)
+{
+ return static_cast<std::size_t>(s);
+}
+#endif // defined(_WIN64)
+
+// Note: assumes K and V are POD types.
+template <typename K, typename V>
+class hash_map
+ : private noncopyable
+{
+public:
+ // The type of a value in the map.
+ typedef std::pair<K, V> value_type;
+
+ // The type of a non-const iterator over the hash map.
+ typedef typename std::list<value_type>::iterator iterator;
+
+ // The type of a const iterator over the hash map.
+ typedef typename std::list<value_type>::const_iterator const_iterator;
+
+ // Constructor.
+ hash_map()
+ {
+ // Initialise all buckets to empty.
+ for (size_t i = 0; i < num_buckets; ++i)
+ buckets_[i].first = buckets_[i].last = values_.end();
+ }
+
+ // Get an iterator for the beginning of the map.
+ iterator begin()
+ {
+ return values_.begin();
+ }
+
+ // Get an iterator for the beginning of the map.
+ const_iterator begin() const
+ {
+ return values_.begin();
+ }
+
+ // Get an iterator for the end of the map.
+ iterator end()
+ {
+ return values_.end();
+ }
+
+ // Get an iterator for the end of the map.
+ const_iterator end() const
+ {
+ return values_.end();
+ }
+
+ // Check whether the map is empty.
+ bool empty() const
+ {
+ return values_.empty();
+ }
+
+ // Find an entry in the map.
+ iterator find(const K& k)
+ {
+ size_t bucket = calculate_hash_value(k) % num_buckets;
+ iterator it = buckets_[bucket].first;
+ if (it == values_.end())
+ return values_.end();
+ iterator end = buckets_[bucket].last;
+ ++end;
+ while (it != end)
+ {
+ if (it->first == k)
+ return it;
+ ++it;
+ }
+ return values_.end();
+ }
+
+ // Find an entry in the map.
+ const_iterator find(const K& k) const
+ {
+ size_t bucket = calculate_hash_value(k) % num_buckets;
+ const_iterator it = buckets_[bucket].first;
+ if (it == values_.end())
+ return it;
+ const_iterator end = buckets_[bucket].last;
+ ++end;
+ while (it != end)
+ {
+ if (it->first == k)
+ return it;
+ ++it;
+ }
+ return values_.end();
+ }
+
+ // Insert a new entry into the map.
+ std::pair<iterator, bool> insert(const value_type& v)
+ {
+ size_t bucket = calculate_hash_value(v.first) % num_buckets;
+ iterator it = buckets_[bucket].first;
+ if (it == values_.end())
+ {
+ buckets_[bucket].first = buckets_[bucket].last =
+ values_insert(values_.end(), v);
+ return std::pair<iterator, bool>(buckets_[bucket].last, true);
+ }
+ iterator end = buckets_[bucket].last;
+ ++end;
+ while (it != end)
+ {
+ if (it->first == v.first)
+ return std::pair<iterator, bool>(it, false);
+ ++it;
+ }
+ buckets_[bucket].last = values_insert(end, v);
+ return std::pair<iterator, bool>(buckets_[bucket].last, true);
+ }
+
+ // Erase an entry from the map.
+ void erase(iterator it)
+ {
+ assert(it != values_.end());
+
+ size_t bucket = calculate_hash_value(it->first) % num_buckets;
+ bool is_first = (it == buckets_[bucket].first);
+ bool is_last = (it == buckets_[bucket].last);
+ if (is_first && is_last)
+ buckets_[bucket].first = buckets_[bucket].last = values_.end();
+ else if (is_first)
+ ++buckets_[bucket].first;
+ else if (is_last)
+ --buckets_[bucket].last;
+
+ values_erase(it);
+ }
+
+ // Remove all entries from the map.
+ void clear()
+ {
+ // Clear the values.
+ values_.clear();
+
+ // Initialise all buckets to empty.
+ for (size_t i = 0; i < num_buckets; ++i)
+ buckets_[i].first = buckets_[i].last = values_.end();
+ }
+
+private:
+ // Insert an element into the values list by splicing from the spares list,
+ // if a spare is available, and otherwise by inserting a new element.
+ iterator values_insert(iterator it, const value_type& v)
+ {
+ if (spares_.empty())
+ {
+ return values_.insert(it, v);
+ }
+ else
+ {
+ spares_.front() = v;
+ values_.splice(it, spares_, spares_.begin());
+ return --it;
+ }
+ }
+
+ // Erase an element from the values list by splicing it to the spares list.
+ void values_erase(iterator it)
+ {
+ *it = value_type();
+ spares_.splice(spares_.begin(), values_, it);
+ }
+
+ // The list of all values in the hash map.
+ std::list<value_type> values_;
+
+ // The list of spare nodes waiting to be recycled. Assumes that POD types only
+ // are stored in the hash map.
+ std::list<value_type> spares_;
+
+ // The type for a bucket in the hash table.
+ struct bucket_type
+ {
+ iterator first;
+ iterator last;
+ };
+
+ // The number of buckets in the hash.
+ enum { num_buckets = 1021 };
+
+ // The buckets in the hash.
+ bucket_type buckets_[num_buckets];
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_HASH_MAP_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/indirect_handler_queue.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/indirect_handler_queue.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,293 @@
+//
+// indirect_handler_queue.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP
+#define BOOST_ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1310)
+extern "C" void _ReadWriteBarrier();
+# pragma intrinsic(_ReadWriteBarrier)
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1310)
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class indirect_handler_queue
+ : private noncopyable
+{
+public:
+ class handler;
+
+ // Element for a node in the queue.
+ class node
+ {
+ public:
+ node()
+ : version_(0),
+ handler_(0),
+ next_(0)
+ {
+ }
+
+ private:
+ friend class indirect_handler_queue;
+ unsigned long version_;
+ handler* handler_;
+ node* next_;
+ };
+
+ // Base class for handlers in the queue.
+ class handler
+ : private noncopyable
+ {
+ public:
+ void invoke()
+ {
+ invoke_func_(this);
+ }
+
+ void destroy()
+ {
+ destroy_func_(this);
+ }
+
+ protected:
+ typedef void (*invoke_func_type)(handler*);
+ typedef void (*destroy_func_type)(handler*);
+
+ handler(invoke_func_type invoke_func,
+ destroy_func_type destroy_func)
+ : node_(new node),
+ invoke_func_(invoke_func),
+ destroy_func_(destroy_func)
+ {
+ }
+
+ ~handler()
+ {
+ if (node_)
+ delete node_;
+ }
+
+ private:
+ friend class indirect_handler_queue;
+ node* node_;
+ invoke_func_type invoke_func_;
+ destroy_func_type destroy_func_;
+ };
+
+ // Smart point to manager handler lifetimes.
+ class scoped_ptr
+ : private noncopyable
+ {
+ public:
+ explicit scoped_ptr(handler* h)
+ : handler_(h)
+ {
+ }
+
+ ~scoped_ptr()
+ {
+ if (handler_)
+ handler_->destroy();
+ }
+
+ handler* get() const
+ {
+ return handler_;
+ }
+
+ handler* release()
+ {
+ handler* tmp = handler_;
+ handler_ = 0;
+ return tmp;
+ }
+
+ private:
+ handler* handler_;
+ };
+
+ // Constructor.
+ indirect_handler_queue()
+ : front_(new node),
+ back_(front_),
+ next_version_(1)
+ {
+ }
+
+ // Destructor.
+ ~indirect_handler_queue()
+ {
+ while (front_)
+ {
+ node* tmp = front_;
+ front_ = front_->next_;
+ delete tmp;
+ }
+ }
+
+ // Wrap a handler to be pushed into the queue.
+ template <typename Handler>
+ static handler* wrap(Handler h)
+ {
+ // Allocate and construct an object to wrap the handler.
+ typedef handler_wrapper<Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(h);
+ handler_ptr<alloc_traits> ptr(raw_ptr, h);
+ return ptr.release();
+ }
+
+ // Determine whether the queue has something ready to pop.
+ bool poppable()
+ {
+ return front_->next_ != 0;
+ }
+
+ // The version number at the front of the queue.
+ unsigned long front_version()
+ {
+ return front_->version_;
+ }
+
+ // The version number at the back of the queue.
+ unsigned long back_version()
+ {
+ return back_->version_;
+ }
+
+ // Pop a handler from the front of the queue.
+ handler* pop()
+ {
+ node* n = front_;
+ node* new_front = n->next_;
+ if (new_front)
+ {
+ handler* h = new_front->handler_;
+ h->node_ = n;
+ new_front->handler_ = 0;
+ front_ = new_front;
+ return h;
+ }
+ return 0;
+ }
+
+ // Push a handler on to the back of the queue.
+ void push(handler* h)
+ {
+ node* n = h->node_;
+ h->node_ = 0;
+ n->version_ = next_version_;
+ next_version_ += 2;
+ n->handler_ = h;
+ n->next_ = 0;
+ memory_barrier();
+ back_->next_ = n;
+ back_ = n;
+ }
+
+private:
+ // Template wrapper for handlers.
+ template <typename Handler>
+ class handler_wrapper
+ : public handler
+ {
+ public:
+ handler_wrapper(Handler h)
+ : handler(
+ &handler_wrapper<Handler>::do_call,
+ &handler_wrapper<Handler>::do_destroy),
+ handler_(h)
+ {
+ }
+
+ static void do_call(handler* base)
+ {
+ // Take ownership of the handler object.
+ typedef handler_wrapper<Handler> this_type;
+ this_type* h(static_cast<this_type*>(base));
+ typedef handler_alloc_traits<Handler, this_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(h->handler_, h);
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made.
+ Handler handler(h->handler_);
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+
+ // Make the upcall.
+ boost_asio_handler_invoke_helpers::invoke(handler, &handler);
+ }
+
+ static void do_destroy(handler* base)
+ {
+ // Take ownership of the handler object.
+ typedef handler_wrapper<Handler> this_type;
+ this_type* h(static_cast<this_type*>(base));
+ typedef handler_alloc_traits<Handler, this_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(h->handler_, h);
+
+ // 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_);
+ (void)handler;
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+ }
+
+ private:
+ Handler handler_;
+ };
+
+ // Helper function to create a memory barrier.
+ static void memory_barrier()
+ {
+#if defined(_GLIBCXX_WRITE_MEM_BARRIER)
+ _GLIBCXX_WRITE_MEM_BARRIER;
+#elif defined(_MSC_VER) && (_MSC_VER >= 1310)
+ _ReadWriteBarrier();
+#else
+# error memory barrier required
+#endif
+ }
+
+ // The front of the queue.
+ node* front_;
+
+ // The back of the queue.
+ node* back_;
+
+ // The next version counter to be assigned to a node.
+ unsigned long next_version_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_INDIRECT_HANDLER_QUEUE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/io_control.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/io_control.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,139 @@
+//
+// io_control.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_IO_CONTROL_HPP
+#define BOOST_ASIO_DETAIL_IO_CONTROL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/socket_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+namespace io_control {
+
+// IO control command for non-blocking I/O.
+class non_blocking_io
+{
+public:
+ // Default constructor.
+ non_blocking_io()
+ : value_(0)
+ {
+ }
+
+ // Construct with a specific command value.
+ non_blocking_io(bool value)
+ : value_(value ? 1 : 0)
+ {
+ }
+
+ // Get the name of the IO control command.
+ int name() const
+ {
+ return FIONBIO;
+ }
+
+ // Set the value of the I/O control command.
+ void set(bool value)
+ {
+ value_ = value ? 1 : 0;
+ }
+
+ // Get the current value of the I/O control command.
+ bool get() const
+ {
+ return value_ != 0;
+ }
+
+ // Get the address of the command data.
+ detail::ioctl_arg_type* data()
+ {
+ return &value_;
+ }
+
+ // Get the address of the command data.
+ const detail::ioctl_arg_type* data() const
+ {
+ return &value_;
+ }
+
+private:
+ detail::ioctl_arg_type value_;
+};
+
+// I/O control command for getting number of bytes available.
+class bytes_readable
+{
+public:
+ // Default constructor.
+ bytes_readable()
+ : value_(0)
+ {
+ }
+
+ // Construct with a specific command value.
+ bytes_readable(std::size_t value)
+ : value_(static_cast<detail::ioctl_arg_type>(value))
+ {
+ }
+
+ // Get the name of the IO control command.
+ int name() const
+ {
+ return FIONREAD;
+ }
+
+ // Set the value of the I/O control command.
+ void set(std::size_t value)
+ {
+ value_ = static_cast<detail::ioctl_arg_type>(value);
+ }
+
+ // Get the current value of the I/O control command.
+ std::size_t get() const
+ {
+ return static_cast<std::size_t>(value_);
+ }
+
+ // Get the address of the command data.
+ detail::ioctl_arg_type* data()
+ {
+ return &value_;
+ }
+
+ // Get the address of the command data.
+ const detail::ioctl_arg_type* data() const
+ {
+ return &value_;
+ }
+
+private:
+ detail::ioctl_arg_type value_;
+};
+
+} // namespace io_control
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_IO_CONTROL_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/kqueue_reactor.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/kqueue_reactor.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,704 @@
+//
+// kqueue_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 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 BOOST_ASIO_DETAIL_KQUEUE_REACTOR_HPP
+#define BOOST_ASIO_DETAIL_KQUEUE_REACTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/kqueue_reactor_fwd.hpp>
+
+#if defined(BOOST_ASIO_HAS_KQUEUE)
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <vector>
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#include <boost/config.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/task_io_service.hpp>
+#include <boost/asio/detail/thread.hpp>
+#include <boost/asio/detail/reactor_op_queue.hpp>
+#include <boost/asio/detail/select_interrupter.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/signal_blocker.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/timer_queue.hpp>
+
+// Older versions of Mac OS X may not define EV_OOBAND.
+#if !defined(EV_OOBAND)
+# define EV_OOBAND EV_FLAG1
+#endif // !defined(EV_OOBAND)
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <bool Own_Thread>
+class kqueue_reactor
+ : public boost::asio::detail::service_base<kqueue_reactor<Own_Thread> >
+{
+public:
+ // Per-descriptor data.
+ struct per_descriptor_data
+ {
+ bool allow_speculative_read;
+ bool allow_speculative_write;
+ };
+
+ // Constructor.
+ kqueue_reactor(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ kqueue_reactor<Own_Thread> >(io_service),
+ mutex_(),
+ kqueue_fd_(do_kqueue_create()),
+ wait_in_progress_(false),
+ interrupter_(),
+ read_op_queue_(),
+ write_op_queue_(),
+ except_op_queue_(),
+ pending_cancellations_(),
+ stop_thread_(false),
+ thread_(0),
+ shutdown_(false),
+ need_kqueue_wait_(true)
+ {
+ // Start the reactor's internal thread only if needed.
+ if (Own_Thread)
+ {
+ boost::asio::detail::signal_blocker sb;
+ thread_ = new boost::asio::detail::thread(
+ bind_handler(&kqueue_reactor::call_run_thread, this));
+ }
+
+ // Add the interrupter's descriptor to the kqueue.
+ struct kevent event;
+ EV_SET(&event, interrupter_.read_descriptor(),
+ EVFILT_READ, EV_ADD, 0, 0, 0);
+ ::kevent(kqueue_fd_, &event, 1, 0, 0, 0);
+ }
+
+ // Destructor.
+ ~kqueue_reactor()
+ {
+ shutdown_service();
+ close(kqueue_fd_);
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ shutdown_ = true;
+ stop_thread_ = true;
+ lock.unlock();
+
+ if (thread_)
+ {
+ interrupter_.interrupt();
+ thread_->join();
+ delete thread_;
+ thread_ = 0;
+ }
+
+ read_op_queue_.destroy_operations();
+ write_op_queue_.destroy_operations();
+ except_op_queue_.destroy_operations();
+
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ timer_queues_[i]->destroy_timers();
+ timer_queues_.clear();
+ }
+
+ // Register a socket with the reactor. Returns 0 on success, system error
+ // code on failure.
+ int register_descriptor(socket_type, per_descriptor_data& descriptor_data)
+ {
+ descriptor_data.allow_speculative_read = true;
+ descriptor_data.allow_speculative_write = true;
+
+ return 0;
+ }
+
+ // Start a new read operation. The handler object will be invoked when the
+ // given descriptor is ready to be read, or an error has occurred.
+ template <typename Handler>
+ void start_read_op(socket_type descriptor,
+ per_descriptor_data& descriptor_data, Handler handler,
+ bool allow_speculative_read = true)
+ {
+ if (allow_speculative_read && descriptor_data.allow_speculative_read)
+ {
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
+ return;
+ }
+
+ // We only get one shot at a speculative read in this function.
+ allow_speculative_read = false;
+ }
+
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ if (shutdown_)
+ return;
+
+ if (!allow_speculative_read)
+ need_kqueue_wait_ = true;
+ else if (!read_op_queue_.has_operation(descriptor))
+ {
+ // Speculative reads are ok as there are no queued read operations.
+ descriptor_data.allow_speculative_read = true;
+
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
+ return;
+ }
+ }
+
+ // Speculative reads are not ok as there will be queued read operations.
+ descriptor_data.allow_speculative_read = false;
+
+ if (read_op_queue_.enqueue_operation(descriptor, handler))
+ {
+ struct kevent event;
+ EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0);
+ if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
+ {
+ boost::system::error_code ec(errno,
+ boost::asio::error::get_system_category());
+ read_op_queue_.perform_all_operations(descriptor, ec);
+ }
+ }
+ }
+
+ // Start a new write operation. The handler object will be invoked when the
+ // given descriptor is ready to be written, or an error has occurred.
+ template <typename Handler>
+ void start_write_op(socket_type descriptor,
+ per_descriptor_data& descriptor_data, Handler handler,
+ bool allow_speculative_write = true)
+ {
+ if (allow_speculative_write && descriptor_data.allow_speculative_write)
+ {
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
+ return;
+ }
+
+ // We only get one shot at a speculative write in this function.
+ allow_speculative_write = false;
+ }
+
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ if (shutdown_)
+ return;
+
+ if (!allow_speculative_write)
+ need_kqueue_wait_ = true;
+ else if (!write_op_queue_.has_operation(descriptor))
+ {
+ // Speculative writes are ok as there are no queued write operations.
+ descriptor_data.allow_speculative_write = true;
+
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = 0;
+ if (handler.perform(ec, bytes_transferred))
+ {
+ handler.complete(ec, bytes_transferred);
+ return;
+ }
+ }
+
+ // Speculative writes are not ok as there will be queued write operations.
+ descriptor_data.allow_speculative_write = false;
+
+ if (write_op_queue_.enqueue_operation(descriptor, handler))
+ {
+ struct kevent event;
+ EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0);
+ if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
+ {
+ boost::system::error_code ec(errno,
+ boost::asio::error::get_system_category());
+ write_op_queue_.perform_all_operations(descriptor, ec);
+ }
+ }
+ }
+
+ // Start a new exception operation. The handler object will be invoked when
+ // the given descriptor has exception information, or an error has occurred.
+ template <typename Handler>
+ void start_except_op(socket_type descriptor,
+ per_descriptor_data&, Handler handler)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ if (shutdown_)
+ return;
+
+ if (except_op_queue_.enqueue_operation(descriptor, handler))
+ {
+ struct kevent event;
+ if (read_op_queue_.has_operation(descriptor))
+ EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0);
+ else
+ EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0);
+ if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
+ {
+ boost::system::error_code ec(errno,
+ boost::asio::error::get_system_category());
+ except_op_queue_.perform_all_operations(descriptor, ec);
+ }
+ }
+ }
+
+ // Start a new write operation. The handler object will be invoked when the
+ // given descriptor is ready to be written, or an error has occurred.
+ template <typename Handler>
+ void start_connect_op(socket_type descriptor,
+ per_descriptor_data& descriptor_data, Handler handler)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ if (shutdown_)
+ return;
+
+ // Speculative writes are not ok as there will be queued write operations.
+ descriptor_data.allow_speculative_write = false;
+
+ if (write_op_queue_.enqueue_operation(descriptor, handler))
+ {
+ struct kevent event;
+ EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0);
+ if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
+ {
+ boost::system::error_code ec(errno,
+ boost::asio::error::get_system_category());
+ write_op_queue_.perform_all_operations(descriptor, ec);
+ }
+ }
+ }
+
+ // 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&)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ cancel_ops_unlocked(descriptor);
+ }
+
+ // 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&)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ // Remove the descriptor from kqueue.
+ struct kevent event[2];
+ EV_SET(&event[0], descriptor, EVFILT_READ, EV_DELETE, 0, 0, 0);
+ EV_SET(&event[1], descriptor, EVFILT_WRITE, EV_DELETE, 0, 0, 0);
+ ::kevent(kqueue_fd_, event, 2, 0, 0, 0);
+
+ // Cancel any outstanding operations associated with the descriptor.
+ cancel_ops_unlocked(descriptor);
+ }
+
+ // Add a new timer queue to the reactor.
+ template <typename Time_Traits>
+ void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ timer_queues_.push_back(&timer_queue);
+ }
+
+ // Remove a timer queue from the reactor.
+ template <typename Time_Traits>
+ void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ {
+ if (timer_queues_[i] == &timer_queue)
+ {
+ timer_queues_.erase(timer_queues_.begin() + i);
+ return;
+ }
+ }
+ }
+
+ // Schedule a timer in the given timer queue to expire at the specified
+ // absolute time. The handler object will be invoked when the timer expires.
+ template <typename Time_Traits, typename Handler>
+ void schedule_timer(timer_queue<Time_Traits>& timer_queue,
+ const typename Time_Traits::time_type& time, Handler handler, void* token)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ if (!shutdown_)
+ if (timer_queue.enqueue_timer(time, handler, token))
+ interrupter_.interrupt();
+ }
+
+ // Cancel the timer associated with the given token. Returns the number of
+ // handlers that have been posted or dispatched.
+ template <typename Time_Traits>
+ std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ std::size_t n = timer_queue.cancel_timer(token);
+ if (n > 0)
+ interrupter_.interrupt();
+ return n;
+ }
+
+private:
+ friend class task_io_service<kqueue_reactor<Own_Thread> >;
+
+ // Run the kqueue loop.
+ void run(bool block)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ // Dispatch any operation cancellations that were made while the select
+ // loop was not running.
+ read_op_queue_.perform_cancellations();
+ write_op_queue_.perform_cancellations();
+ except_op_queue_.perform_cancellations();
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ timer_queues_[i]->dispatch_cancellations();
+
+ // Check if the thread is supposed to stop.
+ if (stop_thread_)
+ {
+ complete_operations_and_timers(lock);
+ return;
+ }
+
+ // We can return immediately if there's no work to do and the reactor is
+ // not supposed to block.
+ if (!block && read_op_queue_.empty() && write_op_queue_.empty()
+ && except_op_queue_.empty() && all_timer_queues_are_empty())
+ {
+ complete_operations_and_timers(lock);
+ return;
+ }
+
+ // Determine how long to block while waiting for events.
+ timespec timeout_buf = { 0, 0 };
+ timespec* timeout = block ? get_timeout(timeout_buf) : &timeout_buf;
+
+ wait_in_progress_ = true;
+ lock.unlock();
+
+ // Block on the kqueue descriptor.
+ struct kevent events[128];
+ int num_events = (block || need_kqueue_wait_)
+ ? kevent(kqueue_fd_, 0, 0, events, 128, timeout)
+ : 0;
+
+ lock.lock();
+ wait_in_progress_ = false;
+
+ // Block signals while performing operations.
+ boost::asio::detail::signal_blocker sb;
+
+ // Dispatch the waiting events.
+ for (int i = 0; i < num_events; ++i)
+ {
+ int descriptor = events[i].ident;
+ if (descriptor == interrupter_.read_descriptor())
+ {
+ interrupter_.reset();
+ }
+ else if (events[i].filter == EVFILT_READ)
+ {
+ // Dispatch operations associated with the descriptor.
+ bool more_reads = false;
+ bool more_except = false;
+ if (events[i].flags & EV_ERROR)
+ {
+ boost::system::error_code error(
+ events[i].data, boost::asio::error::get_system_category());
+ except_op_queue_.perform_all_operations(descriptor, error);
+ read_op_queue_.perform_all_operations(descriptor, error);
+ }
+ else if (events[i].flags & EV_OOBAND)
+ {
+ boost::system::error_code error;
+ more_except = except_op_queue_.perform_operation(descriptor, error);
+ if (events[i].data > 0)
+ more_reads = read_op_queue_.perform_operation(descriptor, error);
+ else
+ more_reads = read_op_queue_.has_operation(descriptor);
+ }
+ else
+ {
+ boost::system::error_code error;
+ more_reads = read_op_queue_.perform_operation(descriptor, error);
+ more_except = except_op_queue_.has_operation(descriptor);
+ }
+
+ // Update the descriptor in the kqueue.
+ struct kevent event;
+ if (more_reads)
+ EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, 0, 0, 0);
+ else if (more_except)
+ EV_SET(&event, descriptor, EVFILT_READ, EV_ADD, EV_OOBAND, 0, 0);
+ else
+ EV_SET(&event, descriptor, EVFILT_READ, EV_DELETE, 0, 0, 0);
+ if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
+ {
+ boost::system::error_code error(errno,
+ boost::asio::error::get_system_category());
+ except_op_queue_.perform_all_operations(descriptor, error);
+ read_op_queue_.perform_all_operations(descriptor, error);
+ }
+ }
+ else if (events[i].filter == EVFILT_WRITE)
+ {
+ // Dispatch operations associated with the descriptor.
+ bool more_writes = false;
+ if (events[i].flags & EV_ERROR)
+ {
+ boost::system::error_code error(
+ events[i].data, boost::asio::error::get_system_category());
+ write_op_queue_.perform_all_operations(descriptor, error);
+ }
+ else
+ {
+ boost::system::error_code error;
+ more_writes = write_op_queue_.perform_operation(descriptor, error);
+ }
+
+ // Update the descriptor in the kqueue.
+ struct kevent event;
+ if (more_writes)
+ EV_SET(&event, descriptor, EVFILT_WRITE, EV_ADD, 0, 0, 0);
+ else
+ EV_SET(&event, descriptor, EVFILT_WRITE, EV_DELETE, 0, 0, 0);
+ if (::kevent(kqueue_fd_, &event, 1, 0, 0, 0) == -1)
+ {
+ boost::system::error_code error(errno,
+ boost::asio::error::get_system_category());
+ write_op_queue_.perform_all_operations(descriptor, error);
+ }
+ }
+ }
+
+ read_op_queue_.perform_cancellations();
+ write_op_queue_.perform_cancellations();
+ except_op_queue_.perform_cancellations();
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ {
+ timer_queues_[i]->dispatch_timers();
+ timer_queues_[i]->dispatch_cancellations();
+ }
+
+ // Issue any pending cancellations.
+ for (std::size_t i = 0; i < pending_cancellations_.size(); ++i)
+ cancel_ops_unlocked(pending_cancellations_[i]);
+ pending_cancellations_.clear();
+
+ // Determine whether kqueue needs to be called next time the reactor is run.
+ need_kqueue_wait_ = !read_op_queue_.empty()
+ || !write_op_queue_.empty() || !except_op_queue_.empty();
+
+ complete_operations_and_timers(lock);
+ }
+
+ // Run the select loop in the thread.
+ void run_thread()
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ while (!stop_thread_)
+ {
+ lock.unlock();
+ run(true);
+ lock.lock();
+ }
+ }
+
+ // Entry point for the select loop thread.
+ static void call_run_thread(kqueue_reactor* reactor)
+ {
+ reactor->run_thread();
+ }
+
+ // Interrupt the select loop.
+ void interrupt()
+ {
+ interrupter_.interrupt();
+ }
+
+ // Create the kqueue file descriptor. Throws an exception if the descriptor
+ // cannot be created.
+ static int do_kqueue_create()
+ {
+ int fd = kqueue();
+ if (fd == -1)
+ {
+ boost::throw_exception(
+ boost::system::system_error(
+ boost::system::error_code(errno,
+ boost::asio::error::get_system_category()),
+ "kqueue"));
+ }
+ return fd;
+ }
+
+ // Check if all timer queues are empty.
+ bool all_timer_queues_are_empty() const
+ {
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ if (!timer_queues_[i]->empty())
+ return false;
+ return true;
+ }
+
+ // Get the timeout value for the kevent call.
+ timespec* get_timeout(timespec& ts)
+ {
+ if (all_timer_queues_are_empty())
+ return 0;
+
+ // 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.
+ boost::posix_time::time_duration minimum_wait_duration
+ = boost::posix_time::minutes(5);
+
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ {
+ boost::posix_time::time_duration wait_duration
+ = timer_queues_[i]->wait_duration();
+ if (wait_duration < minimum_wait_duration)
+ minimum_wait_duration = wait_duration;
+ }
+
+ if (minimum_wait_duration > boost::posix_time::time_duration())
+ {
+ ts.tv_sec = minimum_wait_duration.total_seconds();
+ ts.tv_nsec = minimum_wait_duration.total_nanoseconds() % 1000000000;
+ }
+ else
+ {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
+ }
+
+ return &ts;
+ }
+
+ // 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 kqueue_reactor's mutex.
+ void cancel_ops_unlocked(socket_type descriptor)
+ {
+ bool interrupt = read_op_queue_.cancel_operations(descriptor);
+ interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt;
+ interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt;
+ if (interrupt)
+ interrupter_.interrupt();
+ }
+
+ // Clean up operations and timers. We must not hold the lock since the
+ // destructors may make calls back into this reactor. We make a copy of the
+ // vector of timer queues since the original may be modified while the lock
+ // is not held.
+ void complete_operations_and_timers(
+ boost::asio::detail::mutex::scoped_lock& lock)
+ {
+ timer_queues_for_cleanup_ = timer_queues_;
+ lock.unlock();
+ read_op_queue_.complete_operations();
+ write_op_queue_.complete_operations();
+ except_op_queue_.complete_operations();
+ for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i)
+ timer_queues_for_cleanup_[i]->complete_timers();
+ }
+
+ // Mutex to protect access to internal data.
+ boost::asio::detail::mutex mutex_;
+
+ // The kqueue file descriptor.
+ int kqueue_fd_;
+
+ // Whether the kqueue wait call is currently in progress
+ bool wait_in_progress_;
+
+ // The interrupter is used to break a blocking kevent call.
+ select_interrupter interrupter_;
+
+ // The queue of read operations.
+ reactor_op_queue<socket_type> read_op_queue_;
+
+ // The queue of write operations.
+ reactor_op_queue<socket_type> write_op_queue_;
+
+ // The queue of except operations.
+ reactor_op_queue<socket_type> except_op_queue_;
+
+ // The timer queues.
+ std::vector<timer_queue_base*> timer_queues_;
+
+ // A copy of the timer queues, used when cleaning up timers. The copy is
+ // stored as a class data member to avoid unnecessary memory allocation.
+ std::vector<timer_queue_base*> timer_queues_for_cleanup_;
+
+ // The descriptors that are pending cancellation.
+ std::vector<socket_type> pending_cancellations_;
+
+ // Does the reactor loop thread need to stop.
+ bool stop_thread_;
+
+ // The thread that is running the reactor loop.
+ boost::asio::detail::thread* thread_;
+
+ // Whether the service has been shut down.
+ bool shutdown_;
+
+ // Whether we need to call kqueue the next time the reactor is run.
+ bool need_kqueue_wait_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_KQUEUE)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_KQUEUE_REACTOR_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/kqueue_reactor_fwd.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/kqueue_reactor_fwd.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,43 @@
+//
+// kqueue_reactor_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 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 BOOST_ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP
+#define BOOST_ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#if !defined(BOOST_ASIO_DISABLE_KQUEUE)
+#if defined(__MACH__) && defined(__APPLE__)
+
+// Define this to indicate that epoll is supported on the target platform.
+#define BOOST_ASIO_HAS_KQUEUE 1
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <bool Own_Thread>
+class kqueue_reactor;
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(__MACH__) && defined(__APPLE__)
+#endif // !defined(BOOST_ASIO_DISABLE_KQUEUE)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/local_free_on_block_exit.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/local_free_on_block_exit.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,61 @@
+//
+// local_free_on_block_exit.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP
+#define BOOST_ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class local_free_on_block_exit
+ : private noncopyable
+{
+public:
+ // Constructor blocks all signals for the calling thread.
+ explicit local_free_on_block_exit(void* p)
+ : p_(p)
+ {
+ }
+
+ // Destructor restores the previous signal mask.
+ ~local_free_on_block_exit()
+ {
+ ::LocalFree(p_);
+ }
+
+private:
+ void* p_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/mutex.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/mutex.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,52 @@
+//
+// mutex.hpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_MUTEX_HPP
+#define BOOST_ASIO_DETAIL_MUTEX_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if !defined(BOOST_HAS_THREADS)
+# include <boost/asio/detail/null_mutex.hpp>
+#elif defined(BOOST_WINDOWS)
+# include <boost/asio/detail/win_mutex.hpp>
+#elif defined(BOOST_HAS_PTHREADS)
+# include <boost/asio/detail/posix_mutex.hpp>
+#else
+# error Only Windows and POSIX are supported!
+#endif
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+#if !defined(BOOST_HAS_THREADS)
+typedef null_mutex mutex;
+#elif defined(BOOST_WINDOWS)
+typedef win_mutex mutex;
+#elif defined(BOOST_HAS_PTHREADS)
+typedef posix_mutex mutex;
+#endif
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_MUTEX_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/noncopyable.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/noncopyable.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,57 @@
+//
+// noncopyable.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_NONCOPYABLE_HPP
+#define BOOST_ASIO_DETAIL_NONCOPYABLE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+// Redefine the noncopyable class for Borland C++ since that compiler does not
+// apply the empty base optimisation unless the base class contains a dummy
+// char data member.
+class noncopyable
+{
+protected:
+ noncopyable() {}
+ ~noncopyable() {}
+private:
+ noncopyable(const noncopyable&);
+ const noncopyable& operator=(const noncopyable&);
+ char dummy_;
+};
+#else
+using boost::noncopyable;
+#endif
+
+} // namespace detail
+
+using boost::asio::detail::noncopyable;
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_NONCOPYABLE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/null_event.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/null_event.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,73 @@
+//
+// null_event.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_NULL_EVENT_HPP
+#define BOOST_ASIO_DETAIL_NULL_EVENT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if !defined(BOOST_HAS_THREADS)
+
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class null_event
+ : private noncopyable
+{
+public:
+ // Constructor.
+ null_event()
+ {
+ }
+
+ // Destructor.
+ ~null_event()
+ {
+ }
+
+ // Signal the event.
+ template <typename Lock>
+ void signal(Lock&)
+ {
+ }
+
+ // Reset the event.
+ template <typename Lock>
+ void clear(Lock&)
+ {
+ }
+
+ // Wait for the event to become signalled.
+ template <typename Lock>
+ void wait(Lock&)
+ {
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // !defined(BOOST_HAS_THREADS)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_NULL_EVENT_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/null_mutex.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/null_mutex.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,68 @@
+//
+// null_mutex.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_NULL_MUTEX_HPP
+#define BOOST_ASIO_DETAIL_NULL_MUTEX_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if !defined(BOOST_HAS_THREADS)
+
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/scoped_lock.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class null_mutex
+ : private noncopyable
+{
+public:
+ typedef boost::asio::detail::scoped_lock<null_mutex> scoped_lock;
+
+ // Constructor.
+ null_mutex()
+ {
+ }
+
+ // Destructor.
+ ~null_mutex()
+ {
+ }
+
+ // Lock the mutex.
+ void lock()
+ {
+ }
+
+ // Unlock the mutex.
+ void unlock()
+ {
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // !defined(BOOST_HAS_THREADS)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_NULL_MUTEX_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/null_signal_blocker.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/null_signal_blocker.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,65 @@
+//
+// null_signal_blocker.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_NULL_SIGNAL_BLOCKER_HPP
+#define BOOST_ASIO_DETAIL_NULL_SIGNAL_BLOCKER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if !defined(BOOST_HAS_THREADS)
+
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class null_signal_blocker
+ : private noncopyable
+{
+public:
+ // Constructor blocks all signals for the calling thread.
+ null_signal_blocker()
+ {
+ }
+
+ // Destructor restores the previous signal mask.
+ ~null_signal_blocker()
+ {
+ }
+
+ // Block all signals for the calling thread.
+ void block()
+ {
+ }
+
+ // Restore the previous signal mask.
+ void unblock()
+ {
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // !defined(BOOST_HAS_THREADS)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_NULL_SIGNAL_BLOCKER_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/null_thread.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/null_thread.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,73 @@
+//
+// null_thread.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_NULL_THREAD_HPP
+#define BOOST_ASIO_DETAIL_NULL_THREAD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if !defined(BOOST_HAS_THREADS)
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class null_thread
+ : private noncopyable
+{
+public:
+ // The purpose of the thread.
+ enum purpose { internal, external };
+
+ // Constructor.
+ template <typename Function>
+ null_thread(Function f, purpose = internal)
+ {
+ boost::system::system_error e(
+ boost::asio::error::operation_not_supported, "thread");
+ boost::throw_exception(e);
+ }
+
+ // Destructor.
+ ~null_thread()
+ {
+ }
+
+ // Wait for the thread to exit.
+ void join()
+ {
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // !defined(BOOST_HAS_THREADS)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_NULL_THREAD_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/null_tss_ptr.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/null_tss_ptr.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,72 @@
+//
+// null_tss_ptr.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_NULL_TSS_PTR_HPP
+#define BOOST_ASIO_DETAIL_NULL_TSS_PTR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if !defined(BOOST_HAS_THREADS)
+
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename T>
+class null_tss_ptr
+ : private noncopyable
+{
+public:
+ // Constructor.
+ null_tss_ptr()
+ : value_(0)
+ {
+ }
+
+ // Destructor.
+ ~null_tss_ptr()
+ {
+ }
+
+ // Get the value.
+ operator T*() const
+ {
+ return value_;
+ }
+
+ // Set the value.
+ void operator=(T* value)
+ {
+ value_ = value;
+ }
+
+private:
+ T* value_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // !defined(BOOST_HAS_THREADS)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_NULL_TSS_PTR_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/old_win_sdk_compat.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/old_win_sdk_compat.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,342 @@
+//
+// old_win_sdk_compat.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_OLD_WIN_SDK_COMPAT_HPP
+#define BOOST_ASIO_DETAIL_OLD_WIN_SDK_COMPAT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+// Guess whether we are building against on old Platform SDK.
+#if !defined(IN6ADDR_ANY_INIT)
+#define BOOST_ASIO_HAS_OLD_WIN_SDK 1
+#endif // !defined(IN6ADDR_ANY_INIT)
+
+#if defined(BOOST_ASIO_HAS_OLD_WIN_SDK)
+
+// Emulation of types that are missing from old Platform SDKs.
+//
+// N.B. this emulation is also used if building for a Windows 2000 target with
+// a recent (i.e. Vista or later) SDK, as the SDK does not provide IPv6 support
+// in that case.
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+enum
+{
+ sockaddr_storage_maxsize = 128, // Maximum size.
+ sockaddr_storage_alignsize = (sizeof(__int64)), // Desired alignment.
+ sockaddr_storage_pad1size = (sockaddr_storage_alignsize - sizeof(short)),
+ sockaddr_storage_pad2size = (sockaddr_storage_maxsize -
+ (sizeof(short) + sockaddr_storage_pad1size + sockaddr_storage_alignsize))
+};
+
+struct sockaddr_storage_emulation
+{
+ short ss_family;
+ char __ss_pad1[sockaddr_storage_pad1size];
+ __int64 __ss_align;
+ char __ss_pad2[sockaddr_storage_pad2size];
+};
+
+struct in6_addr_emulation
+{
+ union
+ {
+ u_char Byte[16];
+ u_short Word[8];
+ } u;
+};
+
+#if !defined(s6_addr)
+# define _S6_un u
+# define _S6_u8 Byte
+# define s6_addr _S6_un._S6_u8
+#endif // !defined(s6_addr)
+
+struct sockaddr_in6_emulation
+{
+ short sin6_family;
+ u_short sin6_port;
+ u_long sin6_flowinfo;
+ in6_addr_emulation sin6_addr;
+ u_long sin6_scope_id;
+};
+
+struct ipv6_mreq_emulation
+{
+ in6_addr_emulation ipv6mr_multiaddr;
+ unsigned int ipv6mr_interface;
+};
+
+#if !defined(IN6ADDR_ANY_INIT)
+# define IN6ADDR_ANY_INIT { 0 }
+#endif
+
+#if !defined(IN6ADDR_LOOPBACK_INIT)
+# define IN6ADDR_LOOPBACK_INIT { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }
+#endif
+
+struct addrinfo_emulation
+{
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+ size_t ai_addrlen;
+ char* ai_canonname;
+ sockaddr* ai_addr;
+ addrinfo_emulation* ai_next;
+};
+
+#if !defined(AI_PASSIVE)
+# define AI_PASSIVE 0x1
+#endif
+
+#if !defined(AI_CANONNAME)
+# define AI_CANONNAME 0x2
+#endif
+
+#if !defined(AI_NUMERICHOST)
+# define AI_NUMERICHOST 0x4
+#endif
+
+#if !defined(EAI_AGAIN)
+# define EAI_AGAIN WSATRY_AGAIN
+#endif
+
+#if !defined(EAI_BADFLAGS)
+# define EAI_BADFLAGS WSAEINVAL
+#endif
+
+#if !defined(EAI_FAIL)
+# define EAI_FAIL WSANO_RECOVERY
+#endif
+
+#if !defined(EAI_FAMILY)
+# define EAI_FAMILY WSAEAFNOSUPPORT
+#endif
+
+#if !defined(EAI_MEMORY)
+# define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY
+#endif
+
+#if !defined(EAI_NODATA)
+# define EAI_NODATA WSANO_DATA
+#endif
+
+#if !defined(EAI_NONAME)
+# define EAI_NONAME WSAHOST_NOT_FOUND
+#endif
+
+#if !defined(EAI_SERVICE)
+# define EAI_SERVICE WSATYPE_NOT_FOUND
+#endif
+
+#if !defined(EAI_SOCKTYPE)
+# define EAI_SOCKTYPE WSAESOCKTNOSUPPORT
+#endif
+
+#if !defined(NI_NOFQDN)
+# define NI_NOFQDN 0x01
+#endif
+
+#if !defined(NI_NUMERICHOST)
+# define NI_NUMERICHOST 0x02
+#endif
+
+#if !defined(NI_NAMEREQD)
+# define NI_NAMEREQD 0x04
+#endif
+
+#if !defined(NI_NUMERICSERV)
+# define NI_NUMERICSERV 0x08
+#endif
+
+#if !defined(NI_DGRAM)
+# define NI_DGRAM 0x10
+#endif
+
+#if !defined(IPPROTO_IPV6)
+# define IPPROTO_IPV6 41
+#endif
+
+#if !defined(IPV6_UNICAST_HOPS)
+# define IPV6_UNICAST_HOPS 4
+#endif
+
+#if !defined(IPV6_MULTICAST_IF)
+# define IPV6_MULTICAST_IF 9
+#endif
+
+#if !defined(IPV6_MULTICAST_HOPS)
+# define IPV6_MULTICAST_HOPS 10
+#endif
+
+#if !defined(IPV6_MULTICAST_LOOP)
+# define IPV6_MULTICAST_LOOP 11
+#endif
+
+#if !defined(IPV6_JOIN_GROUP)
+# define IPV6_JOIN_GROUP 12
+#endif
+
+#if !defined(IPV6_LEAVE_GROUP)
+# define IPV6_LEAVE_GROUP 13
+#endif
+
+inline int IN6_IS_ADDR_UNSPECIFIED(const in6_addr_emulation* a)
+{
+ return ((a->s6_addr[0] == 0)
+ && (a->s6_addr[1] == 0)
+ && (a->s6_addr[2] == 0)
+ && (a->s6_addr[3] == 0)
+ && (a->s6_addr[4] == 0)
+ && (a->s6_addr[5] == 0)
+ && (a->s6_addr[6] == 0)
+ && (a->s6_addr[7] == 0)
+ && (a->s6_addr[8] == 0)
+ && (a->s6_addr[9] == 0)
+ && (a->s6_addr[10] == 0)
+ && (a->s6_addr[11] == 0)
+ && (a->s6_addr[12] == 0)
+ && (a->s6_addr[13] == 0)
+ && (a->s6_addr[14] == 0)
+ && (a->s6_addr[15] == 0));
+}
+
+inline int IN6_IS_ADDR_LOOPBACK(const in6_addr_emulation* a)
+{
+ return ((a->s6_addr[0] == 0)
+ && (a->s6_addr[1] == 0)
+ && (a->s6_addr[2] == 0)
+ && (a->s6_addr[3] == 0)
+ && (a->s6_addr[4] == 0)
+ && (a->s6_addr[5] == 0)
+ && (a->s6_addr[6] == 0)
+ && (a->s6_addr[7] == 0)
+ && (a->s6_addr[8] == 0)
+ && (a->s6_addr[9] == 0)
+ && (a->s6_addr[10] == 0)
+ && (a->s6_addr[11] == 0)
+ && (a->s6_addr[12] == 0)
+ && (a->s6_addr[13] == 0)
+ && (a->s6_addr[14] == 0)
+ && (a->s6_addr[15] == 1));
+}
+
+inline int IN6_IS_ADDR_MULTICAST(const in6_addr_emulation* a)
+{
+ return (a->s6_addr[0] == 0xff);
+}
+
+inline int IN6_IS_ADDR_LINKLOCAL(const in6_addr_emulation* a)
+{
+ return ((a->s6_addr[0] == 0xfe) && ((a->s6_addr[1] & 0xc0) == 0x80));
+}
+
+inline int IN6_IS_ADDR_SITELOCAL(const in6_addr_emulation* a)
+{
+ return ((a->s6_addr[0] == 0xfe) && ((a->s6_addr[1] & 0xc0) == 0xc0));
+}
+
+inline int IN6_IS_ADDR_V4MAPPED(const in6_addr_emulation* a)
+{
+ return ((a->s6_addr[0] == 0)
+ && (a->s6_addr[1] == 0)
+ && (a->s6_addr[2] == 0)
+ && (a->s6_addr[3] == 0)
+ && (a->s6_addr[4] == 0)
+ && (a->s6_addr[5] == 0)
+ && (a->s6_addr[6] == 0)
+ && (a->s6_addr[7] == 0)
+ && (a->s6_addr[8] == 0)
+ && (a->s6_addr[9] == 0)
+ && (a->s6_addr[10] == 0xff)
+ && (a->s6_addr[11] == 0xff));
+}
+
+inline int IN6_IS_ADDR_V4COMPAT(const in6_addr_emulation* a)
+{
+ return ((a->s6_addr[0] == 0)
+ && (a->s6_addr[1] == 0)
+ && (a->s6_addr[2] == 0)
+ && (a->s6_addr[3] == 0)
+ && (a->s6_addr[4] == 0)
+ && (a->s6_addr[5] == 0)
+ && (a->s6_addr[6] == 0)
+ && (a->s6_addr[7] == 0)
+ && (a->s6_addr[8] == 0)
+ && (a->s6_addr[9] == 0)
+ && (a->s6_addr[10] == 0xff)
+ && (a->s6_addr[11] == 0xff)
+ && !((a->s6_addr[12] == 0)
+ && (a->s6_addr[13] == 0)
+ && (a->s6_addr[14] == 0)
+ && ((a->s6_addr[15] == 0) || (a->s6_addr[15] == 1))));
+}
+
+inline int IN6_IS_ADDR_MC_NODELOCAL(const in6_addr_emulation* a)
+{
+ return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 1);
+}
+
+inline int IN6_IS_ADDR_MC_LINKLOCAL(const in6_addr_emulation* a)
+{
+ return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 2);
+}
+
+inline int IN6_IS_ADDR_MC_SITELOCAL(const in6_addr_emulation* a)
+{
+ return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 5);
+}
+
+inline int IN6_IS_ADDR_MC_ORGLOCAL(const in6_addr_emulation* a)
+{
+ return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 8);
+}
+
+inline int IN6_IS_ADDR_MC_GLOBAL(const in6_addr_emulation* a)
+{
+ return IN6_IS_ADDR_MULTICAST(a) && ((a->s6_addr[1] & 0xf) == 0xe);
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_OLD_WIN_SDK)
+
+// Even newer Platform SDKs that support IPv6 may not define IPV6_V6ONLY.
+#if !defined(IPV6_V6ONLY)
+# define IPV6_V6ONLY 27
+#endif
+
+// Some SDKs (e.g. Windows CE) don't define IPPROTO_ICMPV6.
+#if !defined(IPPROTO_ICMPV6)
+# define IPPROTO_ICMPV6 58
+#endif
+
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_OLD_WIN_SDK_COMPAT_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/pipe_select_interrupter.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/pipe_select_interrupter.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,116 @@
+//
+// pipe_select_interrupter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP
+#define BOOST_ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include <boost/asio/detail/push_options.hpp>
+#include <fcntl.h>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class pipe_select_interrupter
+{
+public:
+ // Constructor.
+ pipe_select_interrupter()
+ {
+ int pipe_fds[2];
+ if (pipe(pipe_fds) == 0)
+ {
+ read_descriptor_ = pipe_fds[0];
+ ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
+ write_descriptor_ = pipe_fds[1];
+ ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
+ }
+ else
+ {
+ boost::system::error_code ec(errno,
+ boost::asio::error::get_system_category());
+ boost::system::system_error e(ec, "pipe_select_interrupter");
+ boost::throw_exception(e);
+ }
+ }
+
+ // Destructor.
+ ~pipe_select_interrupter()
+ {
+ if (read_descriptor_ != -1)
+ ::close(read_descriptor_);
+ if (write_descriptor_ != -1)
+ ::close(write_descriptor_);
+ }
+
+ // Interrupt the select call.
+ void interrupt()
+ {
+ char byte = 0;
+ ::write(write_descriptor_, &byte, 1);
+ }
+
+ // Reset the select interrupt. Returns true if the call was interrupted.
+ bool reset()
+ {
+ char data[1024];
+ int bytes_read = ::read(read_descriptor_, data, sizeof(data));
+ bool was_interrupted = (bytes_read > 0);
+ while (bytes_read == sizeof(data))
+ bytes_read = ::read(read_descriptor_, data, sizeof(data));
+ return was_interrupted;
+ }
+
+ // Get the read descriptor to be passed to select.
+ int read_descriptor() const
+ {
+ return read_descriptor_;
+ }
+
+private:
+ // The read end of a connection used to interrupt the select call. This file
+ // descriptor is passed to select such that when it is time to stop, a single
+ // byte will be written on the other end of the connection and this
+ // descriptor will become readable.
+ int read_descriptor_;
+
+ // The write end of a connection used to interrupt the select call. A single
+ // byte may be written to this to wake up the select which is waiting for the
+ // other end to become readable.
+ int write_descriptor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/pop_options.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/pop_options.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,88 @@
+//
+// pop_options.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// No header guard
+
+#if defined(__COMO__)
+
+// Comeau C++
+
+#elif defined(__DMC__)
+
+// Digital Mars C++
+
+#elif defined(__INTEL_COMPILER) || defined(__ICL) \
+ || defined(__ICC) || defined(__ECC)
+
+// Intel C++
+
+#elif defined(__GNUC__)
+
+// GNU C++
+
+# if defined(__MINGW32__) || defined(__CYGWIN__)
+# pragma pack (pop)
+# endif
+
+#elif defined(__KCC)
+
+// Kai C++
+
+#elif defined(__sgi)
+
+// SGI MIPSpro C++
+
+#elif defined(__DECCXX)
+
+// Compaq Tru64 Unix cxx
+
+#elif defined(__ghs)
+
+// Greenhills C++
+
+#elif defined(__BORLANDC__)
+
+// Borland C++
+
+# pragma option pop
+# pragma nopushoptwarn
+# pragma nopackwarning
+
+#elif defined(__MWERKS__)
+
+// Metrowerks CodeWarrior
+
+#elif defined(__SUNPRO_CC)
+
+// Sun Workshop Compiler C++
+
+#elif defined(__HP_aCC)
+
+// HP aCC
+
+#elif defined(__MRC__) || defined(__SC__)
+
+// MPW MrCpp or SCpp
+
+#elif defined(__IBMCPP__)
+
+// IBM Visual Age
+
+#elif defined(_MSC_VER)
+
+// Microsoft Visual C++
+//
+// Must remain the last #elif since some other vendors (Metrowerks, for example)
+// also #define _MSC_VER
+
+# pragma warning (pop)
+# pragma pack (pop)
+
+#endif
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/posix_event.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/posix_event.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,106 @@
+//
+// posix_event.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_POSIX_EVENT_HPP
+#define BOOST_ASIO_DETAIL_POSIX_EVENT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_HAS_PTHREADS)
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/assert.hpp>
+#include <boost/throw_exception.hpp>
+#include <pthread.h>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class posix_event
+ : private noncopyable
+{
+public:
+ // Constructor.
+ posix_event()
+ : signalled_(false)
+ {
+ int error = ::pthread_cond_init(&cond_, 0);
+ if (error != 0)
+ {
+ boost::system::system_error e(
+ boost::system::error_code(error,
+ boost::asio::error::get_system_category()),
+ "event");
+ boost::throw_exception(e);
+ }
+ }
+
+ // Destructor.
+ ~posix_event()
+ {
+ ::pthread_cond_destroy(&cond_);
+ }
+
+ // Signal the event.
+ template <typename Lock>
+ void signal(Lock& lock)
+ {
+ BOOST_ASSERT(lock.locked());
+ (void)lock;
+ signalled_ = true;
+ ::pthread_cond_signal(&cond_); // Ignore EINVAL.
+ }
+
+ // Reset the event.
+ template <typename Lock>
+ void clear(Lock& lock)
+ {
+ BOOST_ASSERT(lock.locked());
+ (void)lock;
+ signalled_ = false;
+ }
+
+ // Wait for the event to become signalled.
+ template <typename Lock>
+ void wait(Lock& lock)
+ {
+ BOOST_ASSERT(lock.locked());
+ while (!signalled_)
+ ::pthread_cond_wait(&cond_, &lock.mutex().mutex_); // Ignore EINVAL.
+ }
+
+private:
+ ::pthread_cond_t cond_;
+ bool signalled_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_HAS_PTHREADS)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_POSIX_EVENT_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/posix_fd_set_adapter.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/posix_fd_set_adapter.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,79 @@
+//
+// posix_fd_set_adapter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP
+#define BOOST_ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/socket_types.hpp>
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// Adapts the FD_SET type to meet the Descriptor_Set concept's requirements.
+class posix_fd_set_adapter
+{
+public:
+ posix_fd_set_adapter()
+ : max_descriptor_(invalid_socket)
+ {
+ using namespace std; // Needed for memset on Solaris.
+ FD_ZERO(&fd_set_);
+ }
+
+ bool set(socket_type descriptor)
+ {
+ if (descriptor < (socket_type)FD_SETSIZE)
+ {
+ if (max_descriptor_ == invalid_socket || descriptor > max_descriptor_)
+ max_descriptor_ = descriptor;
+ FD_SET(descriptor, &fd_set_);
+ return true;
+ }
+ return false;
+ }
+
+ bool is_set(socket_type descriptor) const
+ {
+ return FD_ISSET(descriptor, &fd_set_) != 0;
+ }
+
+ operator fd_set*()
+ {
+ return &fd_set_;
+ }
+
+ socket_type max_descriptor() const
+ {
+ return max_descriptor_;
+ }
+
+private:
+ mutable fd_set fd_set_;
+ socket_type max_descriptor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/posix_mutex.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/posix_mutex.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,109 @@
+//
+// posix_mutex.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_POSIX_MUTEX_HPP
+#define BOOST_ASIO_DETAIL_POSIX_MUTEX_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_HAS_PTHREADS)
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/throw_exception.hpp>
+#include <pthread.h>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/scoped_lock.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class posix_event;
+
+class posix_mutex
+ : private noncopyable
+{
+public:
+ typedef boost::asio::detail::scoped_lock<posix_mutex> scoped_lock;
+
+ // Constructor.
+ posix_mutex()
+ {
+ int error = ::pthread_mutex_init(&mutex_, 0);
+ if (error != 0)
+ {
+ boost::system::system_error e(
+ boost::system::error_code(error,
+ boost::asio::error::get_system_category()),
+ "mutex");
+ boost::throw_exception(e);
+ }
+ }
+
+ // Destructor.
+ ~posix_mutex()
+ {
+ ::pthread_mutex_destroy(&mutex_);
+ }
+
+ // Lock the mutex.
+ void lock()
+ {
+ int error = ::pthread_mutex_lock(&mutex_);
+ if (error != 0)
+ {
+ boost::system::system_error e(
+ boost::system::error_code(error,
+ boost::asio::error::get_system_category()),
+ "mutex");
+ boost::throw_exception(e);
+ }
+ }
+
+ // Unlock the mutex.
+ void unlock()
+ {
+ int error = ::pthread_mutex_unlock(&mutex_);
+ if (error != 0)
+ {
+ boost::system::system_error e(
+ boost::system::error_code(error,
+ boost::asio::error::get_system_category()),
+ "mutex");
+ boost::throw_exception(e);
+ }
+ }
+
+private:
+ friend class posix_event;
+ ::pthread_mutex_t mutex_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_HAS_PTHREADS)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_POSIX_MUTEX_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/posix_signal_blocker.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/posix_signal_blocker.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,92 @@
+//
+// posix_signal_blocker.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP
+#define BOOST_ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_HAS_PTHREADS)
+
+#include <boost/asio/detail/push_options.hpp>
+#include <csignal>
+#include <pthread.h>
+#include <signal.h>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class posix_signal_blocker
+ : private noncopyable
+{
+public:
+ // Constructor blocks all signals for the calling thread.
+ posix_signal_blocker()
+ : blocked_(false)
+ {
+ sigset_t new_mask;
+ sigfillset(&new_mask);
+ blocked_ = (pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask_) == 0);
+ }
+
+ // Destructor restores the previous signal mask.
+ ~posix_signal_blocker()
+ {
+ if (blocked_)
+ pthread_sigmask(SIG_SETMASK, &old_mask_, 0);
+ }
+
+ // Block all signals for the calling thread.
+ void block()
+ {
+ if (!blocked_)
+ {
+ sigset_t new_mask;
+ sigfillset(&new_mask);
+ blocked_ = (pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask_) == 0);
+ }
+ }
+
+ // Restore the previous signal mask.
+ void unblock()
+ {
+ if (blocked_)
+ blocked_ = (pthread_sigmask(SIG_SETMASK, &old_mask_, 0) != 0);
+ }
+
+private:
+ // Have signals been blocked.
+ bool blocked_;
+
+ // The previous signal mask.
+ sigset_t old_mask_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_HAS_PTHREADS)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/posix_thread.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/posix_thread.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,134 @@
+//
+// posix_thread.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_POSIX_THREAD_HPP
+#define BOOST_ASIO_DETAIL_POSIX_THREAD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_HAS_PTHREADS)
+
+#include <boost/asio/detail/push_options.hpp>
+#include <memory>
+#include <boost/throw_exception.hpp>
+#include <pthread.h>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+extern "C" void* asio_detail_posix_thread_function(void* arg);
+
+class posix_thread
+ : private noncopyable
+{
+public:
+ // The purpose of the thread.
+ enum purpose { internal, external };
+
+ // Constructor.
+ template <typename Function>
+ posix_thread(Function f, purpose = internal)
+ : joined_(false)
+ {
+ std::auto_ptr<func_base> arg(new func<Function>(f));
+ int error = ::pthread_create(&thread_, 0,
+ asio_detail_posix_thread_function, arg.get());
+ if (error != 0)
+ {
+ boost::system::system_error e(
+ boost::system::error_code(error,
+ boost::asio::error::get_system_category()),
+ "thread");
+ boost::throw_exception(e);
+ }
+ arg.release();
+ }
+
+ // Destructor.
+ ~posix_thread()
+ {
+ if (!joined_)
+ ::pthread_detach(thread_);
+ }
+
+ // Wait for the thread to exit.
+ void join()
+ {
+ if (!joined_)
+ {
+ ::pthread_join(thread_, 0);
+ joined_ = true;
+ }
+ }
+
+private:
+ friend void* asio_detail_posix_thread_function(void* arg);
+
+ class func_base
+ {
+ public:
+ virtual ~func_base() {}
+ virtual void run() = 0;
+ };
+
+ template <typename Function>
+ class func
+ : public func_base
+ {
+ public:
+ func(Function f)
+ : f_(f)
+ {
+ }
+
+ virtual void run()
+ {
+ f_();
+ }
+
+ private:
+ Function f_;
+ };
+
+ ::pthread_t thread_;
+ bool joined_;
+};
+
+inline void* asio_detail_posix_thread_function(void* arg)
+{
+ std::auto_ptr<posix_thread::func_base> f(
+ static_cast<posix_thread::func_base*>(arg));
+ f->run();
+ return 0;
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_HAS_PTHREADS)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_POSIX_THREAD_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/posix_tss_ptr.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/posix_tss_ptr.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,90 @@
+//
+// posix_tss_ptr.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_POSIX_TSS_PTR_HPP
+#define BOOST_ASIO_DETAIL_POSIX_TSS_PTR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_HAS_PTHREADS)
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/throw_exception.hpp>
+#include <pthread.h>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename T>
+class posix_tss_ptr
+ : private noncopyable
+{
+public:
+ // Constructor.
+ posix_tss_ptr()
+ {
+ int error = ::pthread_key_create(&tss_key_, 0);
+ if (error != 0)
+ {
+ boost::system::system_error e(
+ boost::system::error_code(error,
+ boost::asio::error::get_system_category()),
+ "tss");
+ boost::throw_exception(e);
+ }
+ }
+
+ // Destructor.
+ ~posix_tss_ptr()
+ {
+ ::pthread_key_delete(tss_key_);
+ }
+
+ // Get the value.
+ operator T*() const
+ {
+ return static_cast<T*>(::pthread_getspecific(tss_key_));
+ }
+
+ // Set the value.
+ void operator=(T* value)
+ {
+ ::pthread_setspecific(tss_key_, value);
+ }
+
+private:
+ // Thread-specific storage to allow unlocked access to determine whether a
+ // thread is a member of the pool.
+ pthread_key_t tss_key_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_HAS_PTHREADS)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_POSIX_TSS_PTR_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/push_options.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/push_options.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,114 @@
+//
+// push_options.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+// No header guard
+
+#if defined(__COMO__)
+
+// Comeau C++
+
+#elif defined(__DMC__)
+
+// Digital Mars C++
+
+#elif defined(__INTEL_COMPILER) || defined(__ICL) \
+ || defined(__ICC) || defined(__ECC)
+
+// Intel C++
+
+#elif defined(__GNUC__)
+
+// GNU C++
+
+# if defined(__MINGW32__) || defined(__CYGWIN__)
+# pragma pack (push, 8)
+# endif
+
+#elif defined(__KCC)
+
+// Kai C++
+
+#elif defined(__sgi)
+
+// SGI MIPSpro C++
+
+#elif defined(__DECCXX)
+
+// Compaq Tru64 Unix cxx
+
+#elif defined(__ghs)
+
+// Greenhills C++
+
+#elif defined(__BORLANDC__)
+
+// Borland C++
+
+# pragma option push -a8 -b -Ve- -Vx- -w-inl -vi-
+# pragma nopushoptwarn
+# pragma nopackwarning
+# if !defined(__MT__)
+# error Multithreaded RTL must be selected.
+# endif // !defined(__MT__)
+
+#elif defined(__MWERKS__)
+
+// Metrowerks CodeWarrior
+
+#elif defined(__SUNPRO_CC)
+
+// Sun Workshop Compiler C++
+
+#elif defined(__HP_aCC)
+
+// HP aCC
+
+#elif defined(__MRC__) || defined(__SC__)
+
+// MPW MrCpp or SCpp
+
+#elif defined(__IBMCPP__)
+
+// IBM Visual Age
+
+#elif defined(_MSC_VER)
+
+// Microsoft Visual C++
+//
+// Must remain the last #elif since some other vendors (Metrowerks, for example)
+// also #define _MSC_VER
+
+# pragma warning (disable:4103)
+# pragma warning (push)
+# pragma warning (disable:4127)
+# pragma warning (disable:4244)
+# pragma warning (disable:4355)
+# pragma warning (disable:4512)
+# pragma warning (disable:4675)
+# if defined(_M_IX86) && defined(_Wp64)
+// The /Wp64 option is broken. If you want to check 64 bit portability, use a
+// 64 bit compiler!
+# pragma warning (disable:4311)
+# pragma warning (disable:4312)
+# endif // defined(_M_IX86) && defined(_Wp64)
+# pragma pack (push, 8)
+// Note that if the /Og optimisation flag is enabled with MSVC6, the compiler
+// has a tendency to incorrectly optimise away some calls to member template
+// functions, even though those functions contain code that should not be
+// optimised away! Therefore we will always disable this optimisation option
+// for the MSVC6 compiler.
+# if (_MSC_VER < 1300)
+# pragma optimize ("g", off)
+# endif
+# if !defined(_MT)
+# error Multithreaded RTL must be selected.
+# endif // !defined(_MT)
+
+#endif
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/reactive_descriptor_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/reactive_descriptor_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,711 @@
+//
+// reactive_descriptor_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/handler_base_from_member.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/descriptor_ops.hpp>
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Reactor>
+class reactive_descriptor_service
+ : public boost::asio::detail::service_base<
+ reactive_descriptor_service<Reactor> >
+{
+public:
+ // The native type of a descriptor.
+ typedef int native_type;
+
+ // The implementation type of the descriptor.
+ class implementation_type
+ : private boost::asio::detail::noncopyable
+ {
+ public:
+ // Default constructor.
+ implementation_type()
+ : descriptor_(-1),
+ flags_(0)
+ {
+ }
+
+ private:
+ // Only this service will have access to the internal values.
+ friend class reactive_descriptor_service<Reactor>;
+
+ // The native descriptor representation.
+ int descriptor_;
+
+ enum
+ {
+ user_set_non_blocking = 1, // The user wants a non-blocking descriptor.
+ internal_non_blocking = 2 // The descriptor has been set non-blocking.
+ };
+
+ // Flags indicating the current state of the descriptor.
+ unsigned char flags_;
+
+ // Per-descriptor data used by the reactor.
+ typename Reactor::per_descriptor_data reactor_data_;
+ };
+
+ // The maximum number of buffers to support in a single operation.
+ enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
+
+ // Constructor.
+ reactive_descriptor_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ reactive_descriptor_service<Reactor> >(io_service),
+ reactor_(boost::asio::use_service<Reactor>(io_service))
+ {
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ // Construct a new descriptor implementation.
+ void construct(implementation_type& impl)
+ {
+ impl.descriptor_ = -1;
+ impl.flags_ = 0;
+ }
+
+ // Destroy a descriptor implementation.
+ void destroy(implementation_type& impl)
+ {
+ if (impl.descriptor_ != -1)
+ {
+ reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_);
+
+ if (impl.flags_ & implementation_type::internal_non_blocking)
+ {
+ ioctl_arg_type non_blocking = 0;
+ boost::system::error_code ignored_ec;
+ descriptor_ops::ioctl(impl.descriptor_,
+ FIONBIO, &non_blocking, ignored_ec);
+ impl.flags_ &= ~implementation_type::internal_non_blocking;
+ }
+
+ boost::system::error_code ignored_ec;
+ descriptor_ops::close(impl.descriptor_, ignored_ec);
+
+ impl.descriptor_ = -1;
+ }
+ }
+
+ // Assign a native descriptor to a descriptor implementation.
+ boost::system::error_code assign(implementation_type& impl,
+ const native_type& native_descriptor, boost::system::error_code& ec)
+ {
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ if (int err = reactor_.register_descriptor(
+ native_descriptor, impl.reactor_data_))
+ {
+ ec = boost::system::error_code(err,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ impl.descriptor_ = native_descriptor;
+ impl.flags_ = 0;
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Determine whether the descriptor is open.
+ bool is_open(const implementation_type& impl) const
+ {
+ return impl.descriptor_ != -1;
+ }
+
+ // Destroy a descriptor implementation.
+ boost::system::error_code close(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ if (is_open(impl))
+ {
+ reactor_.close_descriptor(impl.descriptor_, impl.reactor_data_);
+
+ if (impl.flags_ & implementation_type::internal_non_blocking)
+ {
+ ioctl_arg_type non_blocking = 0;
+ boost::system::error_code ignored_ec;
+ descriptor_ops::ioctl(impl.descriptor_,
+ FIONBIO, &non_blocking, ignored_ec);
+ impl.flags_ &= ~implementation_type::internal_non_blocking;
+ }
+
+ if (descriptor_ops::close(impl.descriptor_, ec) == -1)
+ return ec;
+
+ impl.descriptor_ = -1;
+ }
+
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Get the native descriptor representation.
+ native_type native(const implementation_type& impl) const
+ {
+ return impl.descriptor_;
+ }
+
+ // Cancel all operations associated with the descriptor.
+ boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ reactor_.cancel_ops(impl.descriptor_, impl.reactor_data_);
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Perform an IO control command on the descriptor.
+ template <typename IO_Control_Command>
+ boost::system::error_code io_control(implementation_type& impl,
+ IO_Control_Command& command, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ if (command.name() == static_cast<int>(FIONBIO))
+ {
+ if (command.get())
+ impl.flags_ |= implementation_type::user_set_non_blocking;
+ else
+ impl.flags_ &= ~implementation_type::user_set_non_blocking;
+ ec = boost::system::error_code();
+ }
+ else
+ {
+ descriptor_ops::ioctl(impl.descriptor_, command.name(),
+ static_cast<ioctl_arg_type*>(command.data()), ec);
+ }
+ return ec;
+ }
+
+ // Write some data to the descriptor.
+ template <typename ConstBufferSequence>
+ size_t write_some(implementation_type& impl,
+ const ConstBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Copy buffers into array.
+ descriptor_ops::buf bufs[max_buffers];
+ typename ConstBufferSequence::const_iterator iter = buffers.begin();
+ typename ConstBufferSequence::const_iterator end = buffers.end();
+ size_t i = 0;
+ size_t total_buffer_size = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::const_buffer buffer(*iter);
+ descriptor_ops::init_buf(bufs[i],
+ boost::asio::buffer_cast<const void*>(buffer),
+ boost::asio::buffer_size(buffer));
+ total_buffer_size += boost::asio::buffer_size(buffer);
+ }
+
+ // A request to read_some 0 bytes on a stream is a no-op.
+ if (total_buffer_size == 0)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ // Make descriptor non-blocking if user wants non-blocking.
+ if (impl.flags_ & implementation_type::user_set_non_blocking)
+ {
+ if (!(impl.flags_ & implementation_type::internal_non_blocking))
+ {
+ ioctl_arg_type non_blocking = 1;
+ if (descriptor_ops::ioctl(impl.descriptor_,
+ FIONBIO, &non_blocking, ec))
+ return 0;
+ impl.flags_ |= implementation_type::internal_non_blocking;
+ }
+ }
+
+ // Send the data.
+ for (;;)
+ {
+ // Try to complete the operation without blocking.
+ int bytes_sent = descriptor_ops::gather_write(
+ impl.descriptor_, bufs, i, ec);
+
+ // Check if operation succeeded.
+ if (bytes_sent >= 0)
+ return bytes_sent;
+
+ // Operation failed.
+ if ((impl.flags_ & implementation_type::user_set_non_blocking)
+ || (ec != boost::asio::error::would_block
+ && ec != boost::asio::error::try_again))
+ return 0;
+
+ // Wait for descriptor to become ready.
+ if (descriptor_ops::poll_write(impl.descriptor_, ec) < 0)
+ return 0;
+ }
+ }
+
+ // Wait until data can be written without blocking.
+ size_t write_some(implementation_type& impl,
+ const null_buffers&, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Wait for descriptor to become ready.
+ descriptor_ops::poll_write(impl.descriptor_, ec);
+
+ return 0;
+ }
+
+ template <typename ConstBufferSequence, typename Handler>
+ class write_operation :
+ public handler_base_from_member<Handler>
+ {
+ public:
+ write_operation(int descriptor, boost::asio::io_service& io_service,
+ const ConstBufferSequence& buffers, Handler handler)
+ : handler_base_from_member<Handler>(handler),
+ descriptor_(descriptor),
+ io_service_(io_service),
+ work_(io_service),
+ buffers_(buffers)
+ {
+ }
+
+ bool perform(boost::system::error_code& ec,
+ std::size_t& bytes_transferred)
+ {
+ // Check whether the operation was successful.
+ if (ec)
+ {
+ bytes_transferred = 0;
+ return true;
+ }
+
+ // Copy buffers into array.
+ descriptor_ops::buf bufs[max_buffers];
+ typename ConstBufferSequence::const_iterator iter = buffers_.begin();
+ typename ConstBufferSequence::const_iterator end = buffers_.end();
+ size_t i = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::const_buffer buffer(*iter);
+ descriptor_ops::init_buf(bufs[i],
+ boost::asio::buffer_cast<const void*>(buffer),
+ boost::asio::buffer_size(buffer));
+ }
+
+ // Write the data.
+ int bytes = descriptor_ops::gather_write(descriptor_, bufs, i, ec);
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
+
+ bytes_transferred = (bytes < 0 ? 0 : bytes);
+ return true;
+ }
+
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ io_service_.post(bind_handler(this->handler_, ec, bytes_transferred));
+ }
+
+ private:
+ int descriptor_;
+ boost::asio::io_service& io_service_;
+ boost::asio::io_service::work work_;
+ ConstBufferSequence buffers_;
+ };
+
+ // Start an asynchronous write. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_write_some(implementation_type& impl,
+ const ConstBufferSequence& buffers, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ }
+ else
+ {
+ // Determine total size of buffers.
+ typename ConstBufferSequence::const_iterator iter = buffers.begin();
+ typename ConstBufferSequence::const_iterator end = buffers.end();
+ size_t i = 0;
+ size_t total_buffer_size = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::const_buffer buffer(*iter);
+ total_buffer_size += boost::asio::buffer_size(buffer);
+ }
+
+ // A request to read_some 0 bytes on a stream is a no-op.
+ if (total_buffer_size == 0)
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::system::error_code(), 0));
+ return;
+ }
+
+ // Make descriptor non-blocking.
+ if (!(impl.flags_ & implementation_type::internal_non_blocking))
+ {
+ ioctl_arg_type non_blocking = 1;
+ boost::system::error_code ec;
+ if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec))
+ {
+ this->get_io_service().post(bind_handler(handler, ec, 0));
+ return;
+ }
+ impl.flags_ |= implementation_type::internal_non_blocking;
+ }
+
+ reactor_.start_write_op(impl.descriptor_, impl.reactor_data_,
+ write_operation<ConstBufferSequence, Handler>(
+ impl.descriptor_, this->get_io_service(), buffers, handler));
+ }
+ }
+
+ template <typename Handler>
+ class null_buffers_operation :
+ public handler_base_from_member<Handler>
+ {
+ public:
+ null_buffers_operation(boost::asio::io_service& io_service, Handler handler)
+ : handler_base_from_member<Handler>(handler),
+ work_(io_service)
+ {
+ }
+
+ bool perform(boost::system::error_code&,
+ std::size_t& bytes_transferred)
+ {
+ bytes_transferred = 0;
+ return true;
+ }
+
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ work_.get_io_service().post(bind_handler(
+ this->handler_, ec, bytes_transferred));
+ }
+
+ private:
+ boost::asio::io_service::work work_;
+ };
+
+ // Start an asynchronous wait until data can be written without blocking.
+ template <typename Handler>
+ void async_write_some(implementation_type& impl,
+ const null_buffers&, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ }
+ else
+ {
+ reactor_.start_write_op(impl.descriptor_, impl.reactor_data_,
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
+ false);
+ }
+ }
+
+ // Read some data from the stream. Returns the number of bytes read.
+ template <typename MutableBufferSequence>
+ size_t read_some(implementation_type& impl,
+ const MutableBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Copy buffers into array.
+ descriptor_ops::buf bufs[max_buffers];
+ typename MutableBufferSequence::const_iterator iter = buffers.begin();
+ typename MutableBufferSequence::const_iterator end = buffers.end();
+ size_t i = 0;
+ size_t total_buffer_size = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::mutable_buffer buffer(*iter);
+ descriptor_ops::init_buf(bufs[i],
+ boost::asio::buffer_cast<void*>(buffer),
+ boost::asio::buffer_size(buffer));
+ total_buffer_size += boost::asio::buffer_size(buffer);
+ }
+
+ // A request to read_some 0 bytes on a stream is a no-op.
+ if (total_buffer_size == 0)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ // Make descriptor non-blocking if user wants non-blocking.
+ if (impl.flags_ & implementation_type::user_set_non_blocking)
+ {
+ if (!(impl.flags_ & implementation_type::internal_non_blocking))
+ {
+ ioctl_arg_type non_blocking = 1;
+ if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec))
+ return 0;
+ impl.flags_ |= implementation_type::internal_non_blocking;
+ }
+ }
+
+ // Read some data.
+ for (;;)
+ {
+ // Try to complete the operation without blocking.
+ int bytes_read = descriptor_ops::scatter_read(
+ impl.descriptor_, bufs, i, ec);
+
+ // Check if operation succeeded.
+ if (bytes_read > 0)
+ return bytes_read;
+
+ // Check for EOF.
+ if (bytes_read == 0)
+ {
+ ec = boost::asio::error::eof;
+ return 0;
+ }
+
+ // Operation failed.
+ if ((impl.flags_ & implementation_type::user_set_non_blocking)
+ || (ec != boost::asio::error::would_block
+ && ec != boost::asio::error::try_again))
+ return 0;
+
+ // Wait for descriptor to become ready.
+ if (descriptor_ops::poll_read(impl.descriptor_, ec) < 0)
+ return 0;
+ }
+ }
+
+ // Wait until data can be read without blocking.
+ size_t read_some(implementation_type& impl,
+ const null_buffers&, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Wait for descriptor to become ready.
+ descriptor_ops::poll_read(impl.descriptor_, ec);
+
+ return 0;
+ }
+
+ template <typename MutableBufferSequence, typename Handler>
+ class read_operation :
+ public handler_base_from_member<Handler>
+ {
+ public:
+ read_operation(int descriptor, boost::asio::io_service& io_service,
+ const MutableBufferSequence& buffers, Handler handler)
+ : handler_base_from_member<Handler>(handler),
+ descriptor_(descriptor),
+ io_service_(io_service),
+ work_(io_service),
+ buffers_(buffers)
+ {
+ }
+
+ bool perform(boost::system::error_code& ec,
+ std::size_t& bytes_transferred)
+ {
+ // Check whether the operation was successful.
+ if (ec)
+ {
+ bytes_transferred = 0;
+ return true;
+ }
+
+ // Copy buffers into array.
+ descriptor_ops::buf bufs[max_buffers];
+ typename MutableBufferSequence::const_iterator iter = buffers_.begin();
+ typename MutableBufferSequence::const_iterator end = buffers_.end();
+ size_t i = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::mutable_buffer buffer(*iter);
+ descriptor_ops::init_buf(bufs[i],
+ boost::asio::buffer_cast<void*>(buffer),
+ boost::asio::buffer_size(buffer));
+ }
+
+ // Read some data.
+ int bytes = descriptor_ops::scatter_read(descriptor_, bufs, i, ec);
+ if (bytes == 0)
+ ec = boost::asio::error::eof;
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
+
+ bytes_transferred = (bytes < 0 ? 0 : bytes);
+ return true;
+ }
+
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ io_service_.post(bind_handler(this->handler_, ec, bytes_transferred));
+ }
+
+ private:
+ int descriptor_;
+ boost::asio::io_service& io_service_;
+ boost::asio::io_service::work work_;
+ MutableBufferSequence buffers_;
+ };
+
+ // Start an asynchronous read. The buffer for the data being read must be
+ // valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_read_some(implementation_type& impl,
+ const MutableBufferSequence& buffers, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ }
+ else
+ {
+ // Determine total size of buffers.
+ typename MutableBufferSequence::const_iterator iter = buffers.begin();
+ typename MutableBufferSequence::const_iterator end = buffers.end();
+ size_t i = 0;
+ size_t total_buffer_size = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::mutable_buffer buffer(*iter);
+ total_buffer_size += boost::asio::buffer_size(buffer);
+ }
+
+ // A request to read_some 0 bytes on a stream is a no-op.
+ if (total_buffer_size == 0)
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::system::error_code(), 0));
+ return;
+ }
+
+ // Make descriptor non-blocking.
+ if (!(impl.flags_ & implementation_type::internal_non_blocking))
+ {
+ ioctl_arg_type non_blocking = 1;
+ boost::system::error_code ec;
+ if (descriptor_ops::ioctl(impl.descriptor_, FIONBIO, &non_blocking, ec))
+ {
+ this->get_io_service().post(bind_handler(handler, ec, 0));
+ return;
+ }
+ impl.flags_ |= implementation_type::internal_non_blocking;
+ }
+
+ reactor_.start_read_op(impl.descriptor_, impl.reactor_data_,
+ read_operation<MutableBufferSequence, Handler>(
+ impl.descriptor_, this->get_io_service(), buffers, handler));
+ }
+ }
+
+ // Wait until data can be read without blocking.
+ template <typename Handler>
+ void async_read_some(implementation_type& impl,
+ const null_buffers&, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ }
+ else
+ {
+ reactor_.start_read_op(impl.descriptor_, impl.reactor_data_,
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
+ false);
+ }
+ }
+
+private:
+ // The selector that performs event demultiplexing for the service.
+ Reactor& reactor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/reactive_serial_port_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/reactive_serial_port_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,269 @@
+//
+// reactive_serial_port_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info_at_[hidden])
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstring>
+#include <string>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include <boost/asio/detail/push_options.hpp>
+#include <termios.h>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/descriptor_ops.hpp>
+#include <boost/asio/detail/reactive_descriptor_service.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// Extend reactive_descriptor_service to provide serial port support.
+template <typename Reactor>
+class reactive_serial_port_service
+ : public boost::asio::detail::service_base<
+ reactive_serial_port_service<Reactor> >
+{
+public:
+ // The native type of a stream handle.
+ typedef typename reactive_descriptor_service<Reactor>::native_type
+ native_type;
+
+ // The implementation type of the stream handle.
+ typedef typename reactive_descriptor_service<Reactor>::implementation_type
+ implementation_type;
+
+ reactive_serial_port_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ reactive_serial_port_service>(io_service),
+ descriptor_service_(boost::asio::use_service<
+ reactive_descriptor_service<Reactor> >(io_service))
+ {
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ // Construct a new handle implementation.
+ void construct(implementation_type& impl)
+ {
+ descriptor_service_.construct(impl);
+ }
+
+ // Destroy a handle implementation.
+ void destroy(implementation_type& impl)
+ {
+ descriptor_service_.destroy(impl);
+ }
+
+ // Open the serial port using the specified device name.
+ boost::system::error_code open(implementation_type& impl,
+ const std::string& device, boost::system::error_code& ec)
+ {
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ int fd = descriptor_ops::open(device.c_str(),
+ O_RDWR | O_NONBLOCK | O_NOCTTY, ec);
+ if (fd < 0)
+ return ec;
+
+ int s = descriptor_ops::fcntl(fd, F_GETFL, ec);
+ if (s >= 0)
+ s = descriptor_ops::fcntl(fd, F_SETFL, s | O_NONBLOCK, ec);
+ if (s < 0)
+ {
+ boost::system::error_code ignored_ec;
+ descriptor_ops::close(fd, ignored_ec);
+ return ec;
+ }
+
+ // Set up default serial port options.
+ termios ios;
+ descriptor_ops::clear_error(ec);
+ s = descriptor_ops::error_wrapper(::tcgetattr(fd, &ios), ec);
+ if (s >= 0)
+ {
+#if defined(_BSD_SOURCE)
+ ::cfmakeraw(&ios);
+#else
+ ios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK
+ | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
+ ios.c_oflag &= ~OPOST;
+ ios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+ ios.c_cflag &= ~(CSIZE | PARENB);
+ ios.c_cflag |= CS8;
+#endif
+ ios.c_iflag |= IGNPAR;
+ descriptor_ops::clear_error(ec);
+ s = descriptor_ops::error_wrapper(::tcsetattr(fd, TCSANOW, &ios), ec);
+ }
+ if (s < 0)
+ {
+ boost::system::error_code ignored_ec;
+ descriptor_ops::close(fd, ignored_ec);
+ return ec;
+ }
+
+ // We're done. Take ownership of the serial port descriptor.
+ if (descriptor_service_.assign(impl, fd, ec))
+ {
+ boost::system::error_code ignored_ec;
+ descriptor_ops::close(fd, ignored_ec);
+ }
+
+ return ec;
+ }
+
+ // Assign a native handle to a handle implementation.
+ boost::system::error_code assign(implementation_type& impl,
+ const native_type& native_descriptor, boost::system::error_code& ec)
+ {
+ return descriptor_service_.assign(impl, native_descriptor, ec);
+ }
+
+ // Determine whether the handle is open.
+ bool is_open(const implementation_type& impl) const
+ {
+ return descriptor_service_.is_open(impl);
+ }
+
+ // Destroy a handle implementation.
+ boost::system::error_code close(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return descriptor_service_.close(impl, ec);
+ }
+
+ // Get the native handle representation.
+ native_type native(implementation_type& impl)
+ {
+ return descriptor_service_.native(impl);
+ }
+
+ // Cancel all operations associated with the handle.
+ boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return descriptor_service_.cancel(impl, ec);
+ }
+
+ // Set an option on the serial port.
+ template <typename SettableSerialPortOption>
+ boost::system::error_code set_option(implementation_type& impl,
+ const SettableSerialPortOption& option, boost::system::error_code& ec)
+ {
+ termios ios;
+ descriptor_ops::clear_error(ec);
+ descriptor_ops::error_wrapper(::tcgetattr(
+ descriptor_service_.native(impl), &ios), ec);
+ if (ec)
+ return ec;
+
+ if (option.store(ios, ec))
+ return ec;
+
+ descriptor_ops::clear_error(ec);
+ descriptor_ops::error_wrapper(::tcsetattr(
+ descriptor_service_.native(impl), TCSANOW, &ios), ec);
+ return ec;
+ }
+
+ // Get an option from the serial port.
+ template <typename GettableSerialPortOption>
+ boost::system::error_code get_option(const implementation_type& impl,
+ GettableSerialPortOption& option, boost::system::error_code& ec) const
+ {
+ termios ios;
+ descriptor_ops::clear_error(ec);
+ descriptor_ops::error_wrapper(::tcgetattr(
+ descriptor_service_.native(impl), &ios), ec);
+ if (ec)
+ return ec;
+
+ return option.load(ios, ec);
+ }
+
+ // Send a break sequence to the serial port.
+ boost::system::error_code send_break(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ descriptor_ops::clear_error(ec);
+ descriptor_ops::error_wrapper(::tcsendbreak(
+ descriptor_service_.native(impl), 0), ec);
+ return ec;
+ }
+
+ // Write the given data. Returns the number of bytes sent.
+ template <typename ConstBufferSequence>
+ size_t write_some(implementation_type& impl,
+ const ConstBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return descriptor_service_.write_some(impl, buffers, ec);
+ }
+
+ // Start an asynchronous write. The data being written must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_write_some(implementation_type& impl,
+ const ConstBufferSequence& buffers, Handler handler)
+ {
+ descriptor_service_.async_write_some(impl, buffers, handler);
+ }
+
+ // Read some data. Returns the number of bytes received.
+ template <typename MutableBufferSequence>
+ size_t read_some(implementation_type& impl,
+ const MutableBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return descriptor_service_.read_some(impl, buffers, ec);
+ }
+
+ // Start an asynchronous read. The buffer for the data being received must be
+ // valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_read_some(implementation_type& impl,
+ const MutableBufferSequence& buffers, Handler handler)
+ {
+ descriptor_service_.async_read_some(impl, buffers, handler);
+ }
+
+private:
+ // The handle service used for initiating asynchronous operations.
+ reactive_descriptor_service<Reactor>& descriptor_service_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/reactive_socket_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/reactive_socket_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,1782 @@
+//
+// reactive_socket_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/handler_base_from_member.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/socket_holder.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Protocol, typename Reactor>
+class reactive_socket_service
+ : public boost::asio::detail::service_base<
+ reactive_socket_service<Protocol, Reactor> >
+{
+public:
+ // The protocol type.
+ typedef Protocol protocol_type;
+
+ // The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ // The native type of a socket.
+ typedef socket_type native_type;
+
+ // The implementation type of the socket.
+ class implementation_type
+ : private boost::asio::detail::noncopyable
+ {
+ public:
+ // Default constructor.
+ implementation_type()
+ : socket_(invalid_socket),
+ flags_(0),
+ protocol_(endpoint_type().protocol())
+ {
+ }
+
+ private:
+ // Only this service will have access to the internal values.
+ friend class reactive_socket_service<Protocol, Reactor>;
+
+ // The native socket representation.
+ socket_type socket_;
+
+ enum
+ {
+ user_set_non_blocking = 1, // The user wants a non-blocking socket.
+ internal_non_blocking = 2, // The socket has been set non-blocking.
+ enable_connection_aborted = 4, // User wants connection_aborted errors.
+ user_set_linger = 8 // The user set the linger option.
+ };
+
+ // Flags indicating the current state of the socket.
+ unsigned char flags_;
+
+ // The protocol associated with the socket.
+ protocol_type protocol_;
+
+ // Per-descriptor data used by the reactor.
+ typename Reactor::per_descriptor_data reactor_data_;
+ };
+
+ // The maximum number of buffers to support in a single operation.
+ enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
+
+ // Constructor.
+ reactive_socket_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ reactive_socket_service<Protocol, Reactor> >(io_service),
+ reactor_(boost::asio::use_service<Reactor>(io_service))
+ {
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ // Construct a new socket implementation.
+ void construct(implementation_type& impl)
+ {
+ impl.socket_ = invalid_socket;
+ impl.flags_ = 0;
+ }
+
+ // Destroy a socket implementation.
+ void destroy(implementation_type& impl)
+ {
+ if (impl.socket_ != invalid_socket)
+ {
+ reactor_.close_descriptor(impl.socket_, impl.reactor_data_);
+
+ if (impl.flags_ & implementation_type::internal_non_blocking)
+ {
+ ioctl_arg_type non_blocking = 0;
+ boost::system::error_code ignored_ec;
+ socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec);
+ impl.flags_ &= ~implementation_type::internal_non_blocking;
+ }
+
+ if (impl.flags_ & implementation_type::user_set_linger)
+ {
+ ::linger opt;
+ opt.l_onoff = 0;
+ opt.l_linger = 0;
+ boost::system::error_code ignored_ec;
+ socket_ops::setsockopt(impl.socket_,
+ SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec);
+ }
+
+ boost::system::error_code ignored_ec;
+ socket_ops::close(impl.socket_, ignored_ec);
+
+ impl.socket_ = invalid_socket;
+ }
+ }
+
+ // Open a new socket implementation.
+ boost::system::error_code open(implementation_type& impl,
+ const protocol_type& protocol, boost::system::error_code& ec)
+ {
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ socket_holder sock(socket_ops::socket(protocol.family(),
+ protocol.type(), protocol.protocol(), ec));
+ if (sock.get() == invalid_socket)
+ return ec;
+
+ if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_))
+ {
+ ec = boost::system::error_code(err,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ impl.socket_ = sock.release();
+ impl.flags_ = 0;
+ impl.protocol_ = protocol;
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Assign a native socket to a socket implementation.
+ boost::system::error_code assign(implementation_type& impl,
+ const protocol_type& protocol, const native_type& native_socket,
+ boost::system::error_code& ec)
+ {
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ if (int err = reactor_.register_descriptor(
+ native_socket, impl.reactor_data_))
+ {
+ ec = boost::system::error_code(err,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ impl.socket_ = native_socket;
+ impl.flags_ = 0;
+ impl.protocol_ = protocol;
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Determine whether the socket is open.
+ bool is_open(const implementation_type& impl) const
+ {
+ return impl.socket_ != invalid_socket;
+ }
+
+ // Destroy a socket implementation.
+ boost::system::error_code close(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ if (is_open(impl))
+ {
+ reactor_.close_descriptor(impl.socket_, impl.reactor_data_);
+
+ if (impl.flags_ & implementation_type::internal_non_blocking)
+ {
+ ioctl_arg_type non_blocking = 0;
+ boost::system::error_code ignored_ec;
+ socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec);
+ impl.flags_ &= ~implementation_type::internal_non_blocking;
+ }
+
+ if (socket_ops::close(impl.socket_, ec) == socket_error_retval)
+ return ec;
+
+ impl.socket_ = invalid_socket;
+ }
+
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Get the native socket representation.
+ native_type native(implementation_type& impl)
+ {
+ return impl.socket_;
+ }
+
+ // Cancel all operations associated with the socket.
+ boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ reactor_.cancel_ops(impl.socket_, impl.reactor_data_);
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Determine whether the socket is at the out-of-band data mark.
+ bool at_mark(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return false;
+ }
+
+ boost::asio::detail::ioctl_arg_type value = 0;
+ socket_ops::ioctl(impl.socket_, SIOCATMARK, &value, ec);
+#if defined(ENOTTY)
+ if (ec.value() == ENOTTY)
+ ec = boost::asio::error::not_socket;
+#endif // defined(ENOTTY)
+ return ec ? false : value != 0;
+ }
+
+ // Determine the number of bytes available for reading.
+ std::size_t available(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ boost::asio::detail::ioctl_arg_type value = 0;
+ socket_ops::ioctl(impl.socket_, FIONREAD, &value, ec);
+#if defined(ENOTTY)
+ if (ec.value() == ENOTTY)
+ ec = boost::asio::error::not_socket;
+#endif // defined(ENOTTY)
+ return ec ? static_cast<std::size_t>(0) : static_cast<std::size_t>(value);
+ }
+
+ // Bind the socket to the specified local endpoint.
+ boost::system::error_code bind(implementation_type& impl,
+ const endpoint_type& endpoint, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
+ return ec;
+ }
+
+ // Place the socket into the state where it will listen for new connections.
+ boost::system::error_code listen(implementation_type& impl, int backlog,
+ boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ socket_ops::listen(impl.socket_, backlog, ec);
+ return ec;
+ }
+
+ // Set a socket option.
+ template <typename Option>
+ boost::system::error_code set_option(implementation_type& impl,
+ const Option& option, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ if (option.level(impl.protocol_) == custom_socket_option_level
+ && option.name(impl.protocol_) == enable_connection_aborted_option)
+ {
+ if (option.size(impl.protocol_) != sizeof(int))
+ {
+ ec = boost::asio::error::invalid_argument;
+ }
+ else
+ {
+ if (*reinterpret_cast<const int*>(option.data(impl.protocol_)))
+ impl.flags_ |= implementation_type::enable_connection_aborted;
+ else
+ impl.flags_ &= ~implementation_type::enable_connection_aborted;
+ ec = boost::system::error_code();
+ }
+ return ec;
+ }
+ else
+ {
+ if (option.level(impl.protocol_) == SOL_SOCKET
+ && option.name(impl.protocol_) == SO_LINGER)
+ {
+ impl.flags_ |= implementation_type::user_set_linger;
+ }
+
+ socket_ops::setsockopt(impl.socket_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), option.size(impl.protocol_), ec);
+
+#if defined(__MACH__) && defined(__APPLE__) \
+|| defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+ // To implement portable behaviour for SO_REUSEADDR with UDP sockets we
+ // need to also set SO_REUSEPORT on BSD-based platforms.
+ if (!ec && impl.protocol_.type() == SOCK_DGRAM
+ && option.level(impl.protocol_) == SOL_SOCKET
+ && option.name(impl.protocol_) == SO_REUSEADDR)
+ {
+ boost::system::error_code ignored_ec;
+ socket_ops::setsockopt(impl.socket_, SOL_SOCKET, SO_REUSEPORT,
+ option.data(impl.protocol_), option.size(impl.protocol_),
+ ignored_ec);
+ }
+#endif
+
+ return ec;
+ }
+ }
+
+ // Set a socket option.
+ template <typename Option>
+ boost::system::error_code get_option(const implementation_type& impl,
+ Option& option, boost::system::error_code& ec) const
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ if (option.level(impl.protocol_) == custom_socket_option_level
+ && option.name(impl.protocol_) == enable_connection_aborted_option)
+ {
+ if (option.size(impl.protocol_) != sizeof(int))
+ {
+ ec = boost::asio::error::invalid_argument;
+ }
+ else
+ {
+ int* target = reinterpret_cast<int*>(option.data(impl.protocol_));
+ if (impl.flags_ & implementation_type::enable_connection_aborted)
+ *target = 1;
+ else
+ *target = 0;
+ option.resize(impl.protocol_, sizeof(int));
+ ec = boost::system::error_code();
+ }
+ return ec;
+ }
+ else
+ {
+ size_t size = option.size(impl.protocol_);
+ socket_ops::getsockopt(impl.socket_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), &size, ec);
+ if (!ec)
+ option.resize(impl.protocol_, size);
+ return ec;
+ }
+ }
+
+ // Perform an IO control command on the socket.
+ template <typename IO_Control_Command>
+ boost::system::error_code io_control(implementation_type& impl,
+ IO_Control_Command& command, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ if (command.name() == static_cast<int>(FIONBIO))
+ {
+ if (command.get())
+ impl.flags_ |= implementation_type::user_set_non_blocking;
+ else
+ impl.flags_ &= ~implementation_type::user_set_non_blocking;
+ ec = boost::system::error_code();
+ }
+ else
+ {
+ socket_ops::ioctl(impl.socket_, command.name(),
+ static_cast<ioctl_arg_type*>(command.data()), ec);
+ }
+ return ec;
+ }
+
+ // Get the local endpoint.
+ endpoint_type local_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return endpoint_type();
+ }
+
+ endpoint_type endpoint;
+ std::size_t addr_len = endpoint.capacity();
+ if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
+ return endpoint_type();
+ endpoint.resize(addr_len);
+ return endpoint;
+ }
+
+ // Get the remote endpoint.
+ endpoint_type remote_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return endpoint_type();
+ }
+
+ endpoint_type endpoint;
+ std::size_t addr_len = endpoint.capacity();
+ if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec))
+ return endpoint_type();
+ endpoint.resize(addr_len);
+ return endpoint;
+ }
+
+ /// Disable sends or receives on the socket.
+ boost::system::error_code shutdown(implementation_type& impl,
+ socket_base::shutdown_type what, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ socket_ops::shutdown(impl.socket_, what, ec);
+ return ec;
+ }
+
+ // Send the given data to the peer.
+ template <typename ConstBufferSequence>
+ size_t send(implementation_type& impl, const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Copy buffers into array.
+ socket_ops::buf bufs[max_buffers];
+ typename ConstBufferSequence::const_iterator iter = buffers.begin();
+ typename ConstBufferSequence::const_iterator end = buffers.end();
+ size_t i = 0;
+ size_t total_buffer_size = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::const_buffer buffer(*iter);
+ socket_ops::init_buf(bufs[i],
+ boost::asio::buffer_cast<const void*>(buffer),
+ boost::asio::buffer_size(buffer));
+ total_buffer_size += boost::asio::buffer_size(buffer);
+ }
+
+ // A request to receive 0 bytes on a stream socket is a no-op.
+ if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ // Make socket non-blocking if user wants non-blocking.
+ if (impl.flags_ & implementation_type::user_set_non_blocking)
+ {
+ if (!(impl.flags_ & implementation_type::internal_non_blocking))
+ {
+ ioctl_arg_type non_blocking = 1;
+ if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
+ return 0;
+ impl.flags_ |= implementation_type::internal_non_blocking;
+ }
+ }
+
+ // Send the data.
+ for (;;)
+ {
+ // Try to complete the operation without blocking.
+ int bytes_sent = socket_ops::send(impl.socket_, bufs, i, flags, ec);
+
+ // Check if operation succeeded.
+ if (bytes_sent >= 0)
+ return bytes_sent;
+
+ // Operation failed.
+ if ((impl.flags_ & implementation_type::user_set_non_blocking)
+ || (ec != boost::asio::error::would_block
+ && ec != boost::asio::error::try_again))
+ return 0;
+
+ // Wait for socket to become ready.
+ if (socket_ops::poll_write(impl.socket_, ec) < 0)
+ return 0;
+ }
+ }
+
+ // Wait until data can be sent without blocking.
+ size_t send(implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Wait for socket to become ready.
+ socket_ops::poll_write(impl.socket_, ec);
+
+ return 0;
+ }
+
+ template <typename ConstBufferSequence, typename Handler>
+ class send_operation :
+ public handler_base_from_member<Handler>
+ {
+ public:
+ send_operation(socket_type socket, boost::asio::io_service& io_service,
+ const ConstBufferSequence& buffers, socket_base::message_flags flags,
+ Handler handler)
+ : handler_base_from_member<Handler>(handler),
+ socket_(socket),
+ io_service_(io_service),
+ work_(io_service),
+ buffers_(buffers),
+ flags_(flags)
+ {
+ }
+
+ bool perform(boost::system::error_code& ec,
+ std::size_t& bytes_transferred)
+ {
+ // Check whether the operation was successful.
+ if (ec)
+ {
+ bytes_transferred = 0;
+ return true;
+ }
+
+ // Copy buffers into array.
+ socket_ops::buf bufs[max_buffers];
+ typename ConstBufferSequence::const_iterator iter = buffers_.begin();
+ typename ConstBufferSequence::const_iterator end = buffers_.end();
+ size_t i = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::const_buffer buffer(*iter);
+ socket_ops::init_buf(bufs[i],
+ boost::asio::buffer_cast<const void*>(buffer),
+ boost::asio::buffer_size(buffer));
+ }
+
+ // Send the data.
+ int bytes = socket_ops::send(socket_, bufs, i, flags_, ec);
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
+
+ bytes_transferred = (bytes < 0 ? 0 : bytes);
+ return true;
+ }
+
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ io_service_.post(bind_handler(this->handler_, ec, bytes_transferred));
+ }
+
+ private:
+ socket_type socket_;
+ boost::asio::io_service& io_service_;
+ boost::asio::io_service::work work_;
+ ConstBufferSequence buffers_;
+ socket_base::message_flags flags_;
+ };
+
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_send(implementation_type& impl, const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ }
+ else
+ {
+ if (impl.protocol_.type() == SOCK_STREAM)
+ {
+ // Determine total size of buffers.
+ typename ConstBufferSequence::const_iterator iter = buffers.begin();
+ typename ConstBufferSequence::const_iterator end = buffers.end();
+ size_t i = 0;
+ size_t total_buffer_size = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::const_buffer buffer(*iter);
+ total_buffer_size += boost::asio::buffer_size(buffer);
+ }
+
+ // A request to receive 0 bytes on a stream socket is a no-op.
+ if (total_buffer_size == 0)
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::system::error_code(), 0));
+ return;
+ }
+ }
+
+ // Make socket non-blocking.
+ if (!(impl.flags_ & implementation_type::internal_non_blocking))
+ {
+ ioctl_arg_type non_blocking = 1;
+ boost::system::error_code ec;
+ if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
+ {
+ this->get_io_service().post(bind_handler(handler, ec, 0));
+ return;
+ }
+ impl.flags_ |= implementation_type::internal_non_blocking;
+ }
+
+ reactor_.start_write_op(impl.socket_, impl.reactor_data_,
+ send_operation<ConstBufferSequence, Handler>(
+ impl.socket_, this->get_io_service(), buffers, flags, handler));
+ }
+ }
+
+ template <typename Handler>
+ class null_buffers_operation :
+ public handler_base_from_member<Handler>
+ {
+ public:
+ null_buffers_operation(boost::asio::io_service& io_service, Handler handler)
+ : handler_base_from_member<Handler>(handler),
+ work_(io_service)
+ {
+ }
+
+ bool perform(boost::system::error_code&,
+ std::size_t& bytes_transferred)
+ {
+ bytes_transferred = 0;
+ return true;
+ }
+
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ work_.get_io_service().post(bind_handler(
+ this->handler_, ec, bytes_transferred));
+ }
+
+ private:
+ boost::asio::io_service::work work_;
+ };
+
+ // Start an asynchronous wait until data can be sent without blocking.
+ template <typename Handler>
+ void async_send(implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ }
+ else
+ {
+ reactor_.start_write_op(impl.socket_, impl.reactor_data_,
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
+ false);
+ }
+ }
+
+ // Send a datagram to the specified endpoint. Returns the number of bytes
+ // sent.
+ template <typename ConstBufferSequence>
+ size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Copy buffers into array.
+ socket_ops::buf bufs[max_buffers];
+ typename ConstBufferSequence::const_iterator iter = buffers.begin();
+ typename ConstBufferSequence::const_iterator end = buffers.end();
+ size_t i = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::const_buffer buffer(*iter);
+ socket_ops::init_buf(bufs[i],
+ boost::asio::buffer_cast<const void*>(buffer),
+ boost::asio::buffer_size(buffer));
+ }
+
+ // Make socket non-blocking if user wants non-blocking.
+ if (impl.flags_ & implementation_type::user_set_non_blocking)
+ {
+ if (!(impl.flags_ & implementation_type::internal_non_blocking))
+ {
+ ioctl_arg_type non_blocking = 1;
+ if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
+ return 0;
+ impl.flags_ |= implementation_type::internal_non_blocking;
+ }
+ }
+
+ // Send the data.
+ for (;;)
+ {
+ // Try to complete the operation without blocking.
+ int bytes_sent = socket_ops::sendto(impl.socket_, bufs, i, flags,
+ destination.data(), destination.size(), ec);
+
+ // Check if operation succeeded.
+ if (bytes_sent >= 0)
+ return bytes_sent;
+
+ // Operation failed.
+ if ((impl.flags_ & implementation_type::user_set_non_blocking)
+ || (ec != boost::asio::error::would_block
+ && ec != boost::asio::error::try_again))
+ return 0;
+
+ // Wait for socket to become ready.
+ if (socket_ops::poll_write(impl.socket_, ec) < 0)
+ return 0;
+ }
+ }
+
+ // Wait until data can be sent without blocking.
+ size_t send_to(implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, const endpoint_type&,
+ boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Wait for socket to become ready.
+ socket_ops::poll_write(impl.socket_, ec);
+
+ return 0;
+ }
+
+ template <typename ConstBufferSequence, typename Handler>
+ class send_to_operation :
+ public handler_base_from_member<Handler>
+ {
+ public:
+ send_to_operation(socket_type socket, boost::asio::io_service& io_service,
+ const ConstBufferSequence& buffers, const endpoint_type& endpoint,
+ socket_base::message_flags flags, Handler handler)
+ : handler_base_from_member<Handler>(handler),
+ socket_(socket),
+ io_service_(io_service),
+ work_(io_service),
+ buffers_(buffers),
+ destination_(endpoint),
+ flags_(flags)
+ {
+ }
+
+ bool perform(boost::system::error_code& ec,
+ std::size_t& bytes_transferred)
+ {
+ // Check whether the operation was successful.
+ if (ec)
+ {
+ bytes_transferred = 0;
+ return true;
+ }
+
+ // Copy buffers into array.
+ socket_ops::buf bufs[max_buffers];
+ typename ConstBufferSequence::const_iterator iter = buffers_.begin();
+ typename ConstBufferSequence::const_iterator end = buffers_.end();
+ size_t i = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::const_buffer buffer(*iter);
+ socket_ops::init_buf(bufs[i],
+ boost::asio::buffer_cast<const void*>(buffer),
+ boost::asio::buffer_size(buffer));
+ }
+
+ // Send the data.
+ int bytes = socket_ops::sendto(socket_, bufs, i, flags_,
+ destination_.data(), destination_.size(), ec);
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
+
+ bytes_transferred = (bytes < 0 ? 0 : bytes);
+ return true;
+ }
+
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ io_service_.post(bind_handler(this->handler_, ec, bytes_transferred));
+ }
+
+ private:
+ socket_type socket_;
+ boost::asio::io_service& io_service_;
+ boost::asio::io_service::work work_;
+ ConstBufferSequence buffers_;
+ endpoint_type destination_;
+ socket_base::message_flags flags_;
+ };
+
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_send_to(implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ }
+ else
+ {
+ // Make socket non-blocking.
+ if (!(impl.flags_ & implementation_type::internal_non_blocking))
+ {
+ ioctl_arg_type non_blocking = 1;
+ boost::system::error_code ec;
+ if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
+ {
+ this->get_io_service().post(bind_handler(handler, ec, 0));
+ return;
+ }
+ impl.flags_ |= implementation_type::internal_non_blocking;
+ }
+
+ reactor_.start_write_op(impl.socket_, impl.reactor_data_,
+ send_to_operation<ConstBufferSequence, Handler>(
+ impl.socket_, this->get_io_service(), buffers,
+ destination, flags, handler));
+ }
+ }
+
+ // Start an asynchronous wait until data can be sent without blocking.
+ template <typename Handler>
+ void async_send_to(implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, const endpoint_type&, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ }
+ else
+ {
+ reactor_.start_write_op(impl.socket_, impl.reactor_data_,
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
+ false);
+ }
+ }
+
+ // Receive some data from the peer. Returns the number of bytes received.
+ template <typename MutableBufferSequence>
+ size_t receive(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Copy buffers into array.
+ socket_ops::buf bufs[max_buffers];
+ typename MutableBufferSequence::const_iterator iter = buffers.begin();
+ typename MutableBufferSequence::const_iterator end = buffers.end();
+ size_t i = 0;
+ size_t total_buffer_size = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::mutable_buffer buffer(*iter);
+ socket_ops::init_buf(bufs[i],
+ boost::asio::buffer_cast<void*>(buffer),
+ boost::asio::buffer_size(buffer));
+ total_buffer_size += boost::asio::buffer_size(buffer);
+ }
+
+ // A request to receive 0 bytes on a stream socket is a no-op.
+ if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ // Make socket non-blocking if user wants non-blocking.
+ if (impl.flags_ & implementation_type::user_set_non_blocking)
+ {
+ if (!(impl.flags_ & implementation_type::internal_non_blocking))
+ {
+ ioctl_arg_type non_blocking = 1;
+ if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
+ return 0;
+ impl.flags_ |= implementation_type::internal_non_blocking;
+ }
+ }
+
+ // Receive some data.
+ for (;;)
+ {
+ // Try to complete the operation without blocking.
+ int bytes_recvd = socket_ops::recv(impl.socket_, bufs, i, flags, ec);
+
+ // Check if operation succeeded.
+ if (bytes_recvd > 0)
+ return bytes_recvd;
+
+ // Check for EOF.
+ if (bytes_recvd == 0 && impl.protocol_.type() == SOCK_STREAM)
+ {
+ ec = boost::asio::error::eof;
+ return 0;
+ }
+
+ // Operation failed.
+ if ((impl.flags_ & implementation_type::user_set_non_blocking)
+ || (ec != boost::asio::error::would_block
+ && ec != boost::asio::error::try_again))
+ return 0;
+
+ // Wait for socket to become ready.
+ if (socket_ops::poll_read(impl.socket_, ec) < 0)
+ return 0;
+ }
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive(implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, ec);
+
+ return 0;
+ }
+
+ template <typename MutableBufferSequence, typename Handler>
+ class receive_operation :
+ public handler_base_from_member<Handler>
+ {
+ public:
+ receive_operation(socket_type socket, int protocol_type,
+ boost::asio::io_service& io_service,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, Handler handler)
+ : handler_base_from_member<Handler>(handler),
+ socket_(socket),
+ protocol_type_(protocol_type),
+ io_service_(io_service),
+ work_(io_service),
+ buffers_(buffers),
+ flags_(flags)
+ {
+ }
+
+ bool perform(boost::system::error_code& ec,
+ std::size_t& bytes_transferred)
+ {
+ // Check whether the operation was successful.
+ if (ec)
+ {
+ bytes_transferred = 0;
+ return true;
+ }
+
+ // Copy buffers into array.
+ socket_ops::buf bufs[max_buffers];
+ typename MutableBufferSequence::const_iterator iter = buffers_.begin();
+ typename MutableBufferSequence::const_iterator end = buffers_.end();
+ size_t i = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::mutable_buffer buffer(*iter);
+ socket_ops::init_buf(bufs[i],
+ boost::asio::buffer_cast<void*>(buffer),
+ boost::asio::buffer_size(buffer));
+ }
+
+ // Receive some data.
+ int bytes = socket_ops::recv(socket_, bufs, i, flags_, ec);
+ if (bytes == 0 && protocol_type_ == SOCK_STREAM)
+ ec = boost::asio::error::eof;
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
+
+ bytes_transferred = (bytes < 0 ? 0 : bytes);
+ return true;
+ }
+
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ io_service_.post(bind_handler(this->handler_, ec, bytes_transferred));
+ }
+
+ private:
+ socket_type socket_;
+ int protocol_type_;
+ boost::asio::io_service& io_service_;
+ boost::asio::io_service::work work_;
+ MutableBufferSequence buffers_;
+ socket_base::message_flags flags_;
+ };
+
+ // Start an asynchronous receive. The buffer for the data being received
+ // must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ }
+ else
+ {
+ if (impl.protocol_.type() == SOCK_STREAM)
+ {
+ // Determine total size of buffers.
+ typename MutableBufferSequence::const_iterator iter = buffers.begin();
+ typename MutableBufferSequence::const_iterator end = buffers.end();
+ size_t i = 0;
+ size_t total_buffer_size = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::mutable_buffer buffer(*iter);
+ total_buffer_size += boost::asio::buffer_size(buffer);
+ }
+
+ // A request to receive 0 bytes on a stream socket is a no-op.
+ if (total_buffer_size == 0)
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::system::error_code(), 0));
+ return;
+ }
+ }
+
+ // Make socket non-blocking.
+ if (!(impl.flags_ & implementation_type::internal_non_blocking))
+ {
+ ioctl_arg_type non_blocking = 1;
+ boost::system::error_code ec;
+ if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
+ {
+ this->get_io_service().post(bind_handler(handler, ec, 0));
+ return;
+ }
+ impl.flags_ |= implementation_type::internal_non_blocking;
+ }
+
+ if (flags & socket_base::message_out_of_band)
+ {
+ reactor_.start_except_op(impl.socket_, impl.reactor_data_,
+ receive_operation<MutableBufferSequence, Handler>(
+ impl.socket_, impl.protocol_.type(),
+ this->get_io_service(), buffers, flags, handler));
+ }
+ else
+ {
+ reactor_.start_read_op(impl.socket_, impl.reactor_data_,
+ receive_operation<MutableBufferSequence, Handler>(
+ impl.socket_, impl.protocol_.type(),
+ this->get_io_service(), buffers, flags, handler));
+ }
+ }
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler>
+ void async_receive(implementation_type& impl, const null_buffers&,
+ socket_base::message_flags flags, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ }
+ else if (flags & socket_base::message_out_of_band)
+ {
+ reactor_.start_except_op(impl.socket_, impl.reactor_data_,
+ null_buffers_operation<Handler>(this->get_io_service(), handler));
+ }
+ else
+ {
+ reactor_.start_read_op(impl.socket_, impl.reactor_data_,
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
+ false);
+ }
+ }
+
+ // Receive a datagram with the endpoint of the sender. Returns the number of
+ // bytes received.
+ template <typename MutableBufferSequence>
+ size_t receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Copy buffers into array.
+ socket_ops::buf bufs[max_buffers];
+ typename MutableBufferSequence::const_iterator iter = buffers.begin();
+ typename MutableBufferSequence::const_iterator end = buffers.end();
+ size_t i = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::mutable_buffer buffer(*iter);
+ socket_ops::init_buf(bufs[i],
+ boost::asio::buffer_cast<void*>(buffer),
+ boost::asio::buffer_size(buffer));
+ }
+
+ // Make socket non-blocking if user wants non-blocking.
+ if (impl.flags_ & implementation_type::user_set_non_blocking)
+ {
+ if (!(impl.flags_ & implementation_type::internal_non_blocking))
+ {
+ ioctl_arg_type non_blocking = 1;
+ if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
+ return 0;
+ impl.flags_ |= implementation_type::internal_non_blocking;
+ }
+ }
+
+ // Receive some data.
+ for (;;)
+ {
+ // Try to complete the operation without blocking.
+ std::size_t addr_len = sender_endpoint.capacity();
+ int bytes_recvd = socket_ops::recvfrom(impl.socket_, bufs, i, flags,
+ sender_endpoint.data(), &addr_len, ec);
+
+ // Check if operation succeeded.
+ if (bytes_recvd > 0)
+ {
+ sender_endpoint.resize(addr_len);
+ return bytes_recvd;
+ }
+
+ // Check for EOF.
+ if (bytes_recvd == 0 && impl.protocol_.type() == SOCK_STREAM)
+ {
+ ec = boost::asio::error::eof;
+ return 0;
+ }
+
+ // Operation failed.
+ if ((impl.flags_ & implementation_type::user_set_non_blocking)
+ || (ec != boost::asio::error::would_block
+ && ec != boost::asio::error::try_again))
+ return 0;
+
+ // Wait for socket to become ready.
+ if (socket_ops::poll_read(impl.socket_, ec) < 0)
+ return 0;
+ }
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive_from(implementation_type& impl, const null_buffers&,
+ endpoint_type& sender_endpoint, socket_base::message_flags,
+ boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, ec);
+
+ // Reset endpoint since it can be given no sensible value at this time.
+ sender_endpoint = endpoint_type();
+
+ return 0;
+ }
+
+ template <typename MutableBufferSequence, typename Handler>
+ class receive_from_operation :
+ public handler_base_from_member<Handler>
+ {
+ public:
+ receive_from_operation(socket_type socket, int protocol_type,
+ boost::asio::io_service& io_service,
+ const MutableBufferSequence& buffers, endpoint_type& endpoint,
+ socket_base::message_flags flags, Handler handler)
+ : handler_base_from_member<Handler>(handler),
+ socket_(socket),
+ protocol_type_(protocol_type),
+ io_service_(io_service),
+ work_(io_service),
+ buffers_(buffers),
+ sender_endpoint_(endpoint),
+ flags_(flags)
+ {
+ }
+
+ bool perform(boost::system::error_code& ec,
+ std::size_t& bytes_transferred)
+ {
+ // Check whether the operation was successful.
+ if (ec)
+ {
+ bytes_transferred = 0;
+ return true;
+ }
+
+ // Copy buffers into array.
+ socket_ops::buf bufs[max_buffers];
+ typename MutableBufferSequence::const_iterator iter = buffers_.begin();
+ typename MutableBufferSequence::const_iterator end = buffers_.end();
+ size_t i = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::mutable_buffer buffer(*iter);
+ socket_ops::init_buf(bufs[i],
+ boost::asio::buffer_cast<void*>(buffer),
+ boost::asio::buffer_size(buffer));
+ }
+
+ // Receive some data.
+ std::size_t addr_len = sender_endpoint_.capacity();
+ int bytes = socket_ops::recvfrom(socket_, bufs, i, flags_,
+ sender_endpoint_.data(), &addr_len, ec);
+ if (bytes == 0 && protocol_type_ == SOCK_STREAM)
+ ec = boost::asio::error::eof;
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
+
+ sender_endpoint_.resize(addr_len);
+ bytes_transferred = (bytes < 0 ? 0 : bytes);
+ return true;
+ }
+
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ io_service_.post(bind_handler(this->handler_, ec, bytes_transferred));
+ }
+
+ private:
+ socket_type socket_;
+ int protocol_type_;
+ boost::asio::io_service& io_service_;
+ boost::asio::io_service::work work_;
+ MutableBufferSequence buffers_;
+ endpoint_type& sender_endpoint_;
+ socket_base::message_flags flags_;
+ };
+
+ // Start an asynchronous receive. The buffer for the data being received and
+ // the sender_endpoint object must both be valid for the lifetime of the
+ // asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ }
+ else
+ {
+ // Make socket non-blocking.
+ if (!(impl.flags_ & implementation_type::internal_non_blocking))
+ {
+ ioctl_arg_type non_blocking = 1;
+ boost::system::error_code ec;
+ if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
+ {
+ this->get_io_service().post(bind_handler(handler, ec, 0));
+ return;
+ }
+ impl.flags_ |= implementation_type::internal_non_blocking;
+ }
+
+ reactor_.start_read_op(impl.socket_, impl.reactor_data_,
+ receive_from_operation<MutableBufferSequence, Handler>(
+ impl.socket_, impl.protocol_.type(), this->get_io_service(),
+ buffers, sender_endpoint, flags, handler));
+ }
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler>
+ void async_receive_from(implementation_type& impl,
+ const null_buffers&, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ }
+ else
+ {
+ // Reset endpoint since it can be given no sensible value at this time.
+ sender_endpoint = endpoint_type();
+
+ if (flags & socket_base::message_out_of_band)
+ {
+ reactor_.start_except_op(impl.socket_, impl.reactor_data_,
+ null_buffers_operation<Handler>(this->get_io_service(), handler));
+ }
+ else
+ {
+ reactor_.start_read_op(impl.socket_, impl.reactor_data_,
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
+ false);
+ }
+ }
+ }
+
+ // Accept a new connection.
+ template <typename Socket>
+ boost::system::error_code accept(implementation_type& impl,
+ Socket& peer, endpoint_type* peer_endpoint, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ // We cannot accept a socket that is already open.
+ if (peer.is_open())
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ // Make socket non-blocking if user wants non-blocking.
+ if (impl.flags_ & implementation_type::user_set_non_blocking)
+ {
+ if (!(impl.flags_ & implementation_type::internal_non_blocking))
+ {
+ ioctl_arg_type non_blocking = 1;
+ if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
+ return ec;
+ impl.flags_ |= implementation_type::internal_non_blocking;
+ }
+ }
+
+ // Accept a socket.
+ for (;;)
+ {
+ // Try to complete the operation without blocking.
+ boost::system::error_code ec;
+ socket_holder new_socket;
+ std::size_t addr_len = 0;
+ if (peer_endpoint)
+ {
+ addr_len = peer_endpoint->capacity();
+ new_socket.reset(socket_ops::accept(impl.socket_,
+ peer_endpoint->data(), &addr_len, ec));
+ }
+ else
+ {
+ new_socket.reset(socket_ops::accept(impl.socket_, 0, 0, ec));
+ }
+
+ // Check if operation succeeded.
+ if (new_socket.get() >= 0)
+ {
+ if (peer_endpoint)
+ peer_endpoint->resize(addr_len);
+ peer.assign(impl.protocol_, new_socket.get(), ec);
+ if (!ec)
+ new_socket.release();
+ return ec;
+ }
+
+ // Operation failed.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ {
+ if (impl.flags_ & implementation_type::user_set_non_blocking)
+ return ec;
+ // Fall through to retry operation.
+ }
+ else if (ec == boost::asio::error::connection_aborted)
+ {
+ if (impl.flags_ & implementation_type::enable_connection_aborted)
+ return ec;
+ // Fall through to retry operation.
+ }
+#if defined(EPROTO)
+ else if (ec.value() == EPROTO)
+ {
+ if (impl.flags_ & implementation_type::enable_connection_aborted)
+ return ec;
+ // Fall through to retry operation.
+ }
+#endif // defined(EPROTO)
+ else
+ return ec;
+
+ // Wait for socket to become ready.
+ if (socket_ops::poll_read(impl.socket_, ec) < 0)
+ return ec;
+ }
+ }
+
+ template <typename Socket, typename Handler>
+ class accept_operation :
+ public handler_base_from_member<Handler>
+ {
+ public:
+ accept_operation(socket_type socket, boost::asio::io_service& io_service,
+ Socket& peer, const protocol_type& protocol,
+ endpoint_type* peer_endpoint, bool enable_connection_aborted,
+ Handler handler)
+ : handler_base_from_member<Handler>(handler),
+ socket_(socket),
+ io_service_(io_service),
+ work_(io_service),
+ peer_(peer),
+ protocol_(protocol),
+ peer_endpoint_(peer_endpoint),
+ enable_connection_aborted_(enable_connection_aborted)
+ {
+ }
+
+ bool perform(boost::system::error_code& ec, std::size_t&)
+ {
+ // Check whether the operation was successful.
+ if (ec)
+ return true;
+
+ // Accept the waiting connection.
+ socket_holder new_socket;
+ std::size_t addr_len = 0;
+ if (peer_endpoint_)
+ {
+ addr_len = peer_endpoint_->capacity();
+ new_socket.reset(socket_ops::accept(socket_,
+ peer_endpoint_->data(), &addr_len, ec));
+ }
+ else
+ {
+ new_socket.reset(socket_ops::accept(socket_, 0, 0, ec));
+ }
+
+ // Check if we need to run the operation again.
+ if (ec == boost::asio::error::would_block
+ || ec == boost::asio::error::try_again)
+ return false;
+ if (ec == boost::asio::error::connection_aborted
+ && !enable_connection_aborted_)
+ return false;
+#if defined(EPROTO)
+ if (ec.value() == EPROTO && !enable_connection_aborted_)
+ return false;
+#endif // defined(EPROTO)
+
+ // Transfer ownership of the new socket to the peer object.
+ if (!ec)
+ {
+ if (peer_endpoint_)
+ peer_endpoint_->resize(addr_len);
+ peer_.assign(protocol_, new_socket.get(), ec);
+ if (!ec)
+ new_socket.release();
+ }
+
+ return true;
+ }
+
+ void complete(const boost::system::error_code& ec, std::size_t)
+ {
+ io_service_.post(bind_handler(this->handler_, ec));
+ }
+
+ private:
+ socket_type socket_;
+ boost::asio::io_service& io_service_;
+ boost::asio::io_service::work work_;
+ Socket& peer_;
+ protocol_type protocol_;
+ endpoint_type* peer_endpoint_;
+ bool enable_connection_aborted_;
+ };
+
+ // Start an asynchronous accept. The peer and peer_endpoint objects
+ // must be valid until the accept's handler is invoked.
+ template <typename Socket, typename Handler>
+ void async_accept(implementation_type& impl, Socket& peer,
+ endpoint_type* peer_endpoint, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor));
+ }
+ else if (peer.is_open())
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::already_open));
+ }
+ else
+ {
+ // Make socket non-blocking.
+ if (!(impl.flags_ & implementation_type::internal_non_blocking))
+ {
+ ioctl_arg_type non_blocking = 1;
+ boost::system::error_code ec;
+ if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
+ {
+ this->get_io_service().post(bind_handler(handler, ec));
+ return;
+ }
+ impl.flags_ |= implementation_type::internal_non_blocking;
+ }
+
+ reactor_.start_read_op(impl.socket_, impl.reactor_data_,
+ accept_operation<Socket, Handler>(
+ impl.socket_, this->get_io_service(),
+ peer, impl.protocol_, peer_endpoint,
+ (impl.flags_ & implementation_type::enable_connection_aborted) != 0,
+ handler));
+ }
+ }
+
+ // Connect the socket to the specified endpoint.
+ boost::system::error_code connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ if (impl.flags_ & implementation_type::internal_non_blocking)
+ {
+ // Mark the socket as blocking while we perform the connect.
+ ioctl_arg_type non_blocking = 0;
+ if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
+ return ec;
+ impl.flags_ &= ~implementation_type::internal_non_blocking;
+ }
+
+ // Perform the connect operation.
+ socket_ops::connect(impl.socket_,
+ peer_endpoint.data(), peer_endpoint.size(), ec);
+ return ec;
+ }
+
+ template <typename Handler>
+ class connect_operation :
+ public handler_base_from_member<Handler>
+ {
+ public:
+ connect_operation(socket_type socket,
+ boost::asio::io_service& io_service, Handler handler)
+ : handler_base_from_member<Handler>(handler),
+ socket_(socket),
+ io_service_(io_service),
+ work_(io_service)
+ {
+ }
+
+ bool perform(boost::system::error_code& ec, std::size_t&)
+ {
+ // Check whether the operation was successful.
+ if (ec)
+ return true;
+
+ // Get the error code from the connect operation.
+ int connect_error = 0;
+ size_t connect_error_len = sizeof(connect_error);
+ if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR,
+ &connect_error, &connect_error_len, ec) == socket_error_retval)
+ return true;
+
+ // The connection failed so the handler will be posted with an error code.
+ if (connect_error)
+ {
+ ec = boost::system::error_code(connect_error,
+ boost::asio::error::get_system_category());
+ return true;
+ }
+
+ return true;
+ }
+
+ void complete(const boost::system::error_code& ec, std::size_t)
+ {
+ io_service_.post(bind_handler(this->handler_, ec));
+ }
+
+ private:
+ socket_type socket_;
+ boost::asio::io_service& io_service_;
+ boost::asio::io_service::work work_;
+ };
+
+ // Start an asynchronous connect.
+ template <typename Handler>
+ void async_connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor));
+ return;
+ }
+
+ // Make socket non-blocking.
+ if (!(impl.flags_ & implementation_type::internal_non_blocking))
+ {
+ ioctl_arg_type non_blocking = 1;
+ boost::system::error_code ec;
+ if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
+ {
+ this->get_io_service().post(bind_handler(handler, ec));
+ return;
+ }
+ impl.flags_ |= implementation_type::internal_non_blocking;
+ }
+
+ // Start the connect operation. The socket is already marked as non-blocking
+ // so the connection will take place asynchronously.
+ boost::system::error_code ec;
+ if (socket_ops::connect(impl.socket_, peer_endpoint.data(),
+ peer_endpoint.size(), ec) == 0)
+ {
+ // The connect operation has finished successfully so we need to post the
+ // handler immediately.
+ this->get_io_service().post(bind_handler(handler,
+ boost::system::error_code()));
+ }
+ else if (ec == boost::asio::error::in_progress
+ || ec == boost::asio::error::would_block)
+ {
+ // The connection is happening in the background, and we need to wait
+ // until the socket becomes writeable.
+ reactor_.start_connect_op(impl.socket_, impl.reactor_data_,
+ connect_operation<Handler>(impl.socket_,
+ this->get_io_service(), handler));
+ }
+ else
+ {
+ // The connect operation has failed, so post the handler immediately.
+ this->get_io_service().post(bind_handler(handler, ec));
+ }
+ }
+
+private:
+ // The selector that performs event demultiplexing for the service.
+ Reactor& reactor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/reactor_op_queue.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/reactor_op_queue.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,456 @@
+//
+// reactor_op_queue.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_REACTOR_OP_QUEUE_HPP
+#define BOOST_ASIO_DETAIL_REACTOR_OP_QUEUE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <memory>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/hash_map.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Descriptor>
+class reactor_op_queue
+ : private noncopyable
+{
+public:
+ // Constructor.
+ reactor_op_queue()
+ : operations_(),
+ cancelled_operations_(0),
+ complete_operations_(0)
+ {
+ }
+
+ // Add a new operation to the queue. Returns true if this is the only
+ // operation for the given descriptor, in which case the reactor's event
+ // demultiplexing function call may need to be interrupted and restarted.
+ template <typename Operation>
+ bool enqueue_operation(Descriptor descriptor, Operation operation)
+ {
+ // Allocate and construct an object to wrap the handler.
+ typedef handler_alloc_traits<Operation, op<Operation> > alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(operation);
+ handler_ptr<alloc_traits> ptr(raw_ptr, descriptor, operation);
+
+ typedef typename operation_map::iterator iterator;
+ typedef typename operation_map::value_type value_type;
+ std::pair<iterator, bool> entry =
+ operations_.insert(value_type(descriptor, ptr.get()));
+ if (entry.second)
+ {
+ ptr.release();
+ return true;
+ }
+
+ op_base* current_op = entry.first->second;
+ while (current_op->next_)
+ current_op = current_op->next_;
+ current_op->next_ = ptr.release();
+
+ return false;
+ }
+
+ // Cancel all operations associated with the descriptor. Any operations
+ // pending for the descriptor will be notified that they have been cancelled
+ // next time perform_cancellations is called. Returns true if any operations
+ // were cancelled, in which case the reactor's event demultiplexing function
+ // may need to be interrupted and restarted.
+ bool cancel_operations(Descriptor descriptor)
+ {
+ typename operation_map::iterator i = operations_.find(descriptor);
+ if (i != operations_.end())
+ {
+ op_base* last_op = i->second;
+ while (last_op->next_)
+ last_op = last_op->next_;
+ last_op->next_ = cancelled_operations_;
+ cancelled_operations_ = i->second;
+ operations_.erase(i);
+ return true;
+ }
+
+ return false;
+ }
+
+ // Whether there are no operations in the queue.
+ bool empty() const
+ {
+ return operations_.empty();
+ }
+
+ // Determine whether there are any operations associated with the descriptor.
+ bool has_operation(Descriptor descriptor) const
+ {
+ return operations_.find(descriptor) != operations_.end();
+ }
+
+ // Perform the first operation corresponding to the descriptor. Returns true
+ // if there are more operations queued for the descriptor.
+ bool perform_operation(Descriptor descriptor,
+ const boost::system::error_code& result)
+ {
+ typename operation_map::iterator i = operations_.find(descriptor);
+ if (i != operations_.end())
+ {
+ op_base* this_op = i->second;
+ i->second = this_op->next_;
+ this_op->next_ = complete_operations_;
+ complete_operations_ = this_op;
+ bool done = this_op->perform(result);
+ if (done)
+ {
+ // Operation has finished.
+ if (i->second)
+ {
+ return true;
+ }
+ else
+ {
+ operations_.erase(i);
+ return false;
+ }
+ }
+ else
+ {
+ // Operation wants to be called again. Leave it at the front of the
+ // queue for this descriptor, and remove from the completed list.
+ complete_operations_ = this_op->next_;
+ this_op->next_ = i->second;
+ i->second = this_op;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Perform all operations corresponding to the descriptor.
+ void perform_all_operations(Descriptor descriptor,
+ const boost::system::error_code& result)
+ {
+ typename operation_map::iterator i = operations_.find(descriptor);
+ if (i != operations_.end())
+ {
+ while (i->second)
+ {
+ op_base* this_op = i->second;
+ i->second = this_op->next_;
+ this_op->next_ = complete_operations_;
+ complete_operations_ = this_op;
+ bool done = this_op->perform(result);
+ if (!done)
+ {
+ // Operation has not finished yet, so leave at front of queue, and
+ // remove from the completed list.
+ complete_operations_ = this_op->next_;
+ this_op->next_ = i->second;
+ i->second = this_op;
+ return;
+ }
+ }
+ operations_.erase(i);
+ }
+ }
+
+ // Fill a descriptor set with the descriptors corresponding to each active
+ // operation.
+ template <typename Descriptor_Set>
+ void get_descriptors(Descriptor_Set& descriptors)
+ {
+ typename operation_map::iterator i = operations_.begin();
+ while (i != operations_.end())
+ {
+ Descriptor descriptor = i->first;
+ ++i;
+ if (!descriptors.set(descriptor))
+ {
+ boost::system::error_code ec(error::fd_set_failure);
+ perform_all_operations(descriptor, ec);
+ }
+ }
+ }
+
+ // Perform the operations corresponding to the ready file descriptors
+ // contained in the given descriptor set.
+ template <typename Descriptor_Set>
+ void perform_operations_for_descriptors(const Descriptor_Set& descriptors,
+ const boost::system::error_code& result)
+ {
+ typename operation_map::iterator i = operations_.begin();
+ while (i != operations_.end())
+ {
+ typename operation_map::iterator op_iter = i++;
+ if (descriptors.is_set(op_iter->first))
+ {
+ op_base* this_op = op_iter->second;
+ op_iter->second = this_op->next_;
+ this_op->next_ = complete_operations_;
+ complete_operations_ = this_op;
+ bool done = this_op->perform(result);
+ if (done)
+ {
+ if (!op_iter->second)
+ operations_.erase(op_iter);
+ }
+ else
+ {
+ // Operation has not finished yet, so leave at front of queue, and
+ // remove from the completed list.
+ complete_operations_ = this_op->next_;
+ this_op->next_ = op_iter->second;
+ op_iter->second = this_op;
+ }
+ }
+ }
+ }
+
+ // Perform any pending cancels for operations.
+ void perform_cancellations()
+ {
+ while (cancelled_operations_)
+ {
+ op_base* this_op = cancelled_operations_;
+ cancelled_operations_ = this_op->next_;
+ this_op->next_ = complete_operations_;
+ complete_operations_ = this_op;
+ this_op->perform(boost::asio::error::operation_aborted);
+ }
+ }
+
+ // Complete all operations that are waiting to be completed.
+ void complete_operations()
+ {
+ while (complete_operations_)
+ {
+ op_base* next_op = complete_operations_->next_;
+ complete_operations_->next_ = 0;
+ complete_operations_->complete();
+ complete_operations_ = next_op;
+ }
+ }
+
+ // Destroy all operations owned by the queue.
+ void destroy_operations()
+ {
+ while (cancelled_operations_)
+ {
+ op_base* next_op = cancelled_operations_->next_;
+ cancelled_operations_->next_ = 0;
+ cancelled_operations_->destroy();
+ cancelled_operations_ = next_op;
+ }
+
+ while (complete_operations_)
+ {
+ op_base* next_op = complete_operations_->next_;
+ complete_operations_->next_ = 0;
+ complete_operations_->destroy();
+ complete_operations_ = next_op;
+ }
+
+ typename operation_map::iterator i = operations_.begin();
+ while (i != operations_.end())
+ {
+ typename operation_map::iterator op_iter = i++;
+ op_base* curr_op = op_iter->second;
+ operations_.erase(op_iter);
+ while (curr_op)
+ {
+ op_base* next_op = curr_op->next_;
+ curr_op->next_ = 0;
+ curr_op->destroy();
+ curr_op = next_op;
+ }
+ }
+ }
+
+private:
+ // Base class for reactor operations. A function pointer is used instead of
+ // virtual functions to avoid the associated overhead.
+ class op_base
+ {
+ public:
+ // Get the descriptor associated with the operation.
+ Descriptor descriptor() const
+ {
+ return descriptor_;
+ }
+
+ // Perform the operation.
+ bool perform(const boost::system::error_code& result)
+ {
+ result_ = result;
+ return perform_func_(this, result_, bytes_transferred_);
+ }
+
+ // Destroy the operation and post the handler.
+ void complete()
+ {
+ complete_func_(this, result_, bytes_transferred_);
+ }
+
+ // Destroy the operation.
+ void destroy()
+ {
+ destroy_func_(this);
+ }
+
+ protected:
+ typedef bool (*perform_func_type)(op_base*,
+ boost::system::error_code&, std::size_t&);
+ typedef void (*complete_func_type)(op_base*,
+ const boost::system::error_code&, std::size_t);
+ typedef void (*destroy_func_type)(op_base*);
+
+ // Construct an operation for the given descriptor.
+ op_base(perform_func_type perform_func, complete_func_type complete_func,
+ destroy_func_type destroy_func, Descriptor descriptor)
+ : perform_func_(perform_func),
+ complete_func_(complete_func),
+ destroy_func_(destroy_func),
+ descriptor_(descriptor),
+ result_(),
+ bytes_transferred_(0),
+ next_(0)
+ {
+ }
+
+ // Prevent deletion through this type.
+ ~op_base()
+ {
+ }
+
+ private:
+ friend class reactor_op_queue<Descriptor>;
+
+ // The function to be called to perform the operation.
+ perform_func_type perform_func_;
+
+ // The function to be called to delete the operation and post the handler.
+ complete_func_type complete_func_;
+
+ // The function to be called to delete the operation.
+ destroy_func_type destroy_func_;
+
+ // The descriptor associated with the operation.
+ Descriptor descriptor_;
+
+ // The result of the operation.
+ boost::system::error_code result_;
+
+ // The number of bytes transferred in the operation.
+ std::size_t bytes_transferred_;
+
+ // The next operation for the same file descriptor.
+ op_base* next_;
+ };
+
+ // Adaptor class template for operations.
+ template <typename Operation>
+ class op
+ : public op_base
+ {
+ public:
+ // Constructor.
+ op(Descriptor descriptor, Operation operation)
+ : op_base(&op<Operation>::do_perform, &op<Operation>::do_complete,
+ &op<Operation>::do_destroy, descriptor),
+ operation_(operation)
+ {
+ }
+
+ // Perform the operation.
+ static bool do_perform(op_base* base,
+ boost::system::error_code& result, std::size_t& bytes_transferred)
+ {
+ return static_cast<op<Operation>*>(base)->operation_.perform(
+ result, bytes_transferred);
+ }
+
+ // Destroy the operation and post the handler.
+ static void do_complete(op_base* base,
+ const boost::system::error_code& result, std::size_t bytes_transferred)
+ {
+ // Take ownership of the operation object.
+ typedef op<Operation> this_type;
+ this_type* this_op(static_cast<this_type*>(base));
+ typedef handler_alloc_traits<Operation, this_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(this_op->operation_, this_op);
+
+ // Make a copy of the error_code and the operation so that the memory can
+ // be deallocated before the upcall is made.
+ boost::system::error_code ec(result);
+ Operation operation(this_op->operation_);
+
+ // Free the memory associated with the operation.
+ ptr.reset();
+
+ // Make the upcall.
+ operation.complete(ec, bytes_transferred);
+ }
+
+ // Destroy the operation.
+ static void do_destroy(op_base* base)
+ {
+ // Take ownership of the operation object.
+ typedef op<Operation> this_type;
+ this_type* this_op(static_cast<this_type*>(base));
+ typedef handler_alloc_traits<Operation, this_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(this_op->operation_, this_op);
+
+ // A sub-object of the operation may be the true owner of the memory
+ // associated with the operation. Consequently, a local copy of the
+ // operation is required to ensure that any owning sub-object remains
+ // valid until after we have deallocated the memory here.
+ Operation operation(this_op->operation_);
+ (void)operation;
+
+ // Free the memory associated with the operation.
+ ptr.reset();
+ }
+
+ private:
+ Operation operation_;
+ };
+
+ // The type for a map of operations.
+ typedef hash_map<Descriptor, op_base*> operation_map;
+
+ // The operations that are currently executing asynchronously.
+ operation_map operations_;
+
+ // The list of operations that have been cancelled.
+ op_base* cancelled_operations_;
+
+ // The list of operations waiting to be completed.
+ op_base* complete_operations_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTOR_OP_QUEUE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/resolver_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/resolver_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,359 @@
+//
+// resolver_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_RESOLVER_SERVICE_HPP
+#define BOOST_ASIO_DETAIL_RESOLVER_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstring>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/thread.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Protocol>
+class resolver_service
+ : public boost::asio::detail::service_base<resolver_service<Protocol> >
+{
+private:
+ // Helper class to perform exception-safe cleanup of addrinfo objects.
+ class auto_addrinfo
+ : private boost::asio::detail::noncopyable
+ {
+ public:
+ explicit auto_addrinfo(boost::asio::detail::addrinfo_type* ai)
+ : ai_(ai)
+ {
+ }
+
+ ~auto_addrinfo()
+ {
+ if (ai_)
+ socket_ops::freeaddrinfo(ai_);
+ }
+
+ operator boost::asio::detail::addrinfo_type*()
+ {
+ return ai_;
+ }
+
+ private:
+ boost::asio::detail::addrinfo_type* ai_;
+ };
+
+public:
+ // The implementation type of the resolver. The shared pointer is used as a
+ // cancellation token to indicate to the background thread that the operation
+ // has been cancelled.
+ typedef boost::shared_ptr<void> implementation_type;
+ struct noop_deleter { void operator()(void*) {} };
+
+ // The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ // The query type.
+ typedef typename Protocol::resolver_query query_type;
+
+ // The iterator type.
+ typedef typename Protocol::resolver_iterator iterator_type;
+
+ // Constructor.
+ resolver_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ resolver_service<Protocol> >(io_service),
+ mutex_(),
+ work_io_service_(new boost::asio::io_service),
+ work_(new boost::asio::io_service::work(*work_io_service_)),
+ work_thread_(0)
+ {
+ }
+
+ // Destructor.
+ ~resolver_service()
+ {
+ shutdown_service();
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ work_.reset();
+ if (work_io_service_)
+ {
+ work_io_service_->stop();
+ if (work_thread_)
+ {
+ work_thread_->join();
+ work_thread_.reset();
+ }
+ work_io_service_.reset();
+ }
+ }
+
+ // Construct a new resolver implementation.
+ void construct(implementation_type& impl)
+ {
+ impl.reset(static_cast<void*>(0), noop_deleter());
+ }
+
+ // Destroy a resolver implementation.
+ void destroy(implementation_type&)
+ {
+ }
+
+ // Cancel pending asynchronous operations.
+ void cancel(implementation_type& impl)
+ {
+ impl.reset(static_cast<void*>(0), noop_deleter());
+ }
+
+ // Resolve a query to a list of entries.
+ iterator_type resolve(implementation_type&, const query_type& query,
+ boost::system::error_code& ec)
+ {
+ boost::asio::detail::addrinfo_type* address_info = 0;
+ std::string host_name = query.host_name();
+ std::string service_name = query.service_name();
+ boost::asio::detail::addrinfo_type hints = query.hints();
+
+ socket_ops::getaddrinfo(host_name.length() ? host_name.c_str() : 0,
+ service_name.c_str(), &hints, &address_info, ec);
+ auto_addrinfo auto_address_info(address_info);
+
+ if (ec)
+ return iterator_type();
+
+ return iterator_type::create(address_info, host_name, service_name);
+ }
+
+ template <typename Handler>
+ class resolve_query_handler
+ {
+ public:
+ resolve_query_handler(implementation_type impl, const query_type& query,
+ boost::asio::io_service& io_service, Handler handler)
+ : impl_(impl),
+ query_(query),
+ io_service_(io_service),
+ work_(io_service),
+ handler_(handler)
+ {
+ }
+
+ void operator()()
+ {
+ // Check if the operation has been cancelled.
+ if (impl_.expired())
+ {
+ iterator_type iterator;
+ io_service_.post(boost::asio::detail::bind_handler(handler_,
+ boost::asio::error::operation_aborted, iterator));
+ return;
+ }
+
+ // Perform the blocking host resolution operation.
+ boost::asio::detail::addrinfo_type* address_info = 0;
+ std::string host_name = query_.host_name();
+ std::string service_name = query_.service_name();
+ boost::asio::detail::addrinfo_type hints = query_.hints();
+ boost::system::error_code ec;
+ socket_ops::getaddrinfo(host_name.length() ? host_name.c_str() : 0,
+ service_name.c_str(), &hints, &address_info, ec);
+ auto_addrinfo auto_address_info(address_info);
+
+ // Invoke the handler and pass the result.
+ iterator_type iterator;
+ if (!ec)
+ iterator = iterator_type::create(address_info, host_name, service_name);
+ io_service_.post(boost::asio::detail::bind_handler(
+ handler_, ec, iterator));
+ }
+
+ private:
+ boost::weak_ptr<void> impl_;
+ query_type query_;
+ boost::asio::io_service& io_service_;
+ boost::asio::io_service::work work_;
+ Handler handler_;
+ };
+
+ // Asynchronously resolve a query to a list of entries.
+ template <typename Handler>
+ void async_resolve(implementation_type& impl, const query_type& query,
+ Handler handler)
+ {
+ if (work_io_service_)
+ {
+ start_work_thread();
+ work_io_service_->post(
+ resolve_query_handler<Handler>(
+ impl, query, this->get_io_service(), handler));
+ }
+ }
+
+ // Resolve an endpoint to a list of entries.
+ iterator_type resolve(implementation_type&,
+ const endpoint_type& endpoint, boost::system::error_code& ec)
+ {
+ // First try resolving with the service name. If that fails try resolving
+ // but allow the service to be returned as a number.
+ char host_name[NI_MAXHOST];
+ char service_name[NI_MAXSERV];
+ int flags = endpoint.protocol().type() == SOCK_DGRAM ? NI_DGRAM : 0;
+ socket_ops::getnameinfo(endpoint.data(), endpoint.size(),
+ host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec);
+ if (ec)
+ {
+ flags |= NI_NUMERICSERV;
+ socket_ops::getnameinfo(endpoint.data(), endpoint.size(),
+ host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec);
+ }
+
+ if (ec)
+ return iterator_type();
+
+ return iterator_type::create(endpoint, host_name, service_name);
+ }
+
+ template <typename Handler>
+ class resolve_endpoint_handler
+ {
+ public:
+ resolve_endpoint_handler(implementation_type impl,
+ const endpoint_type& endpoint, boost::asio::io_service& io_service,
+ Handler handler)
+ : impl_(impl),
+ endpoint_(endpoint),
+ io_service_(io_service),
+ work_(io_service),
+ handler_(handler)
+ {
+ }
+
+ void operator()()
+ {
+ // Check if the operation has been cancelled.
+ if (impl_.expired())
+ {
+ iterator_type iterator;
+ io_service_.post(boost::asio::detail::bind_handler(handler_,
+ boost::asio::error::operation_aborted, iterator));
+ return;
+ }
+
+
+ // First try resolving with the service name. If that fails try resolving
+ // but allow the service to be returned as a number.
+ char host_name[NI_MAXHOST];
+ char service_name[NI_MAXSERV];
+ int flags = endpoint_.protocol().type() == SOCK_DGRAM ? NI_DGRAM : 0;
+ boost::system::error_code ec;
+ socket_ops::getnameinfo(endpoint_.data(), endpoint_.size(),
+ host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec);
+ if (ec)
+ {
+ flags |= NI_NUMERICSERV;
+ socket_ops::getnameinfo(endpoint_.data(), endpoint_.size(),
+ host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags, ec);
+ }
+
+ // Invoke the handler and pass the result.
+ iterator_type iterator;
+ if (!ec)
+ iterator = iterator_type::create(endpoint_, host_name, service_name);
+ io_service_.post(boost::asio::detail::bind_handler(
+ handler_, ec, iterator));
+ }
+
+ private:
+ boost::weak_ptr<void> impl_;
+ endpoint_type endpoint_;
+ boost::asio::io_service& io_service_;
+ boost::asio::io_service::work work_;
+ Handler handler_;
+ };
+
+ // Asynchronously resolve an endpoint to a list of entries.
+ template <typename Handler>
+ void async_resolve(implementation_type& impl, const endpoint_type& endpoint,
+ Handler handler)
+ {
+ if (work_io_service_)
+ {
+ start_work_thread();
+ work_io_service_->post(
+ resolve_endpoint_handler<Handler>(
+ impl, endpoint, this->get_io_service(), handler));
+ }
+ }
+
+private:
+ // Helper class to run the work io_service in a thread.
+ class work_io_service_runner
+ {
+ public:
+ work_io_service_runner(boost::asio::io_service& io_service)
+ : io_service_(io_service) {}
+ void operator()() { io_service_.run(); }
+ private:
+ boost::asio::io_service& io_service_;
+ };
+
+ // Start the work thread if it's not already running.
+ void start_work_thread()
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ if (work_thread_ == 0)
+ {
+ work_thread_.reset(new boost::asio::detail::thread(
+ work_io_service_runner(*work_io_service_)));
+ }
+ }
+
+ // Mutex to protect access to internal data.
+ boost::asio::detail::mutex mutex_;
+
+ // Private io_service used for performing asynchronous host resolution.
+ boost::scoped_ptr<boost::asio::io_service> work_io_service_;
+
+ // Work for the private io_service to perform.
+ boost::scoped_ptr<boost::asio::io_service::work> work_;
+
+ // Thread used for running the work io_service's run loop.
+ boost::scoped_ptr<boost::asio::detail::thread> work_thread_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_RESOLVER_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/scoped_lock.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/scoped_lock.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,93 @@
+//
+// scoped_lock.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_SCOPED_LOCK_HPP
+#define BOOST_ASIO_DETAIL_SCOPED_LOCK_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// Helper class to lock and unlock a mutex automatically.
+template <typename Mutex>
+class scoped_lock
+ : private noncopyable
+{
+public:
+ // Constructor acquires the lock.
+ scoped_lock(Mutex& m)
+ : mutex_(m)
+ {
+ mutex_.lock();
+ locked_ = true;
+ }
+
+ // Destructor releases the lock.
+ ~scoped_lock()
+ {
+ if (locked_)
+ mutex_.unlock();
+ }
+
+ // Explicitly acquire the lock.
+ void lock()
+ {
+ if (!locked_)
+ {
+ mutex_.lock();
+ locked_ = true;
+ }
+ }
+
+ // Explicitly release the lock.
+ void unlock()
+ {
+ if (locked_)
+ {
+ mutex_.unlock();
+ locked_ = false;
+ }
+ }
+
+ // Test whether the lock is held.
+ bool locked() const
+ {
+ return locked_;
+ }
+
+ // Get the underlying mutex.
+ Mutex& mutex()
+ {
+ return mutex_;
+ }
+
+private:
+ // The underlying mutex.
+ Mutex& mutex_;
+
+ // Whether the mutex is currently locked or unlocked.
+ bool locked_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SCOPED_LOCK_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/select_interrupter.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/select_interrupter.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,43 @@
+//
+// select_interrupter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_SELECT_INTERRUPTER_HPP
+#define BOOST_ASIO_DETAIL_SELECT_INTERRUPTER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/pipe_select_interrupter.hpp>
+#include <boost/asio/detail/socket_select_interrupter.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+typedef socket_select_interrupter select_interrupter;
+#else
+typedef pipe_select_interrupter select_interrupter;
+#endif
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SELECT_INTERRUPTER_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/select_reactor.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/select_reactor.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,536 @@
+//
+// select_reactor.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_SELECT_REACTOR_HPP
+#define BOOST_ASIO_DETAIL_SELECT_REACTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/socket_types.hpp> // Must come before posix_time.
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/shared_ptr.hpp>
+#include <vector>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/fd_set_adapter.hpp>
+#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/reactor_op_queue.hpp>
+#include <boost/asio/detail/select_interrupter.hpp>
+#include <boost/asio/detail/select_reactor_fwd.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/signal_blocker.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/task_io_service.hpp>
+#include <boost/asio/detail/thread.hpp>
+#include <boost/asio/detail/timer_queue.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <bool Own_Thread>
+class select_reactor
+ : public boost::asio::detail::service_base<select_reactor<Own_Thread> >
+{
+public:
+ // Per-descriptor data.
+ struct per_descriptor_data
+ {
+ };
+
+ // Constructor.
+ select_reactor(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ select_reactor<Own_Thread> >(io_service),
+ mutex_(),
+ select_in_progress_(false),
+ interrupter_(),
+ read_op_queue_(),
+ write_op_queue_(),
+ except_op_queue_(),
+ pending_cancellations_(),
+ stop_thread_(false),
+ thread_(0),
+ shutdown_(false)
+ {
+ if (Own_Thread)
+ {
+ boost::asio::detail::signal_blocker sb;
+ thread_ = new boost::asio::detail::thread(
+ bind_handler(&select_reactor::call_run_thread, this));
+ }
+ }
+
+ // Destructor.
+ ~select_reactor()
+ {
+ shutdown_service();
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ shutdown_ = true;
+ stop_thread_ = true;
+ lock.unlock();
+
+ if (thread_)
+ {
+ interrupter_.interrupt();
+ thread_->join();
+ delete thread_;
+ thread_ = 0;
+ }
+
+ read_op_queue_.destroy_operations();
+ write_op_queue_.destroy_operations();
+ except_op_queue_.destroy_operations();
+
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ timer_queues_[i]->destroy_timers();
+ timer_queues_.clear();
+ }
+
+ // Register a socket with the reactor. Returns 0 on success, system error
+ // code on failure.
+ int register_descriptor(socket_type, per_descriptor_data&)
+ {
+ return 0;
+ }
+
+ // Start a new read operation. The handler object will be invoked when the
+ // given descriptor is ready to be read, or an error has occurred.
+ template <typename Handler>
+ void start_read_op(socket_type descriptor, per_descriptor_data&,
+ Handler handler, bool /*allow_speculative_read*/ = true)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ if (!shutdown_)
+ if (read_op_queue_.enqueue_operation(descriptor, handler))
+ interrupter_.interrupt();
+ }
+
+ // Start a new write operation. The handler object will be invoked when the
+ // given descriptor is ready to be written, or an error has occurred.
+ template <typename Handler>
+ void start_write_op(socket_type descriptor, per_descriptor_data&,
+ Handler handler, bool /*allow_speculative_write*/ = true)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ if (!shutdown_)
+ if (write_op_queue_.enqueue_operation(descriptor, handler))
+ interrupter_.interrupt();
+ }
+
+ // Start a new exception operation. The handler object will be invoked when
+ // the given descriptor has exception information, or an error has occurred.
+ template <typename Handler>
+ void start_except_op(socket_type descriptor,
+ per_descriptor_data&, Handler handler)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ if (!shutdown_)
+ if (except_op_queue_.enqueue_operation(descriptor, handler))
+ interrupter_.interrupt();
+ }
+
+ // Wrapper for connect handlers to enable the handler object to be placed
+ // in both the write and the except operation queues, but ensure that only
+ // one of the handlers is called.
+ template <typename Handler>
+ class connect_handler_wrapper
+ {
+ public:
+ connect_handler_wrapper(socket_type descriptor,
+ boost::shared_ptr<bool> completed,
+ select_reactor<Own_Thread>& reactor, Handler handler)
+ : descriptor_(descriptor),
+ completed_(completed),
+ reactor_(reactor),
+ handler_(handler)
+ {
+ }
+
+ bool perform(boost::system::error_code& ec,
+ std::size_t& bytes_transferred)
+ {
+ // Check whether one of the handlers has already been called. If it has,
+ // then we don't want to do anything in this handler.
+ if (*completed_)
+ {
+ completed_.reset(); // Indicate that this handler should not complete.
+ return true;
+ }
+
+ // Cancel the other reactor operation for the connection.
+ *completed_ = true;
+ reactor_.enqueue_cancel_ops_unlocked(descriptor_);
+
+ // Call the contained handler.
+ return handler_.perform(ec, bytes_transferred);
+ }
+
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ if (completed_.get())
+ handler_.complete(ec, bytes_transferred);
+ }
+
+ private:
+ socket_type descriptor_;
+ boost::shared_ptr<bool> completed_;
+ select_reactor<Own_Thread>& reactor_;
+ Handler handler_;
+ };
+
+ // Start new write and exception operations. The handler object will be
+ // invoked when the given descriptor is ready for writing or has exception
+ // information available, or an error has occurred. The handler will be called
+ // only once.
+ template <typename Handler>
+ void start_connect_op(socket_type descriptor,
+ per_descriptor_data&, Handler handler)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ if (!shutdown_)
+ {
+ boost::shared_ptr<bool> completed(new bool(false));
+ connect_handler_wrapper<Handler> wrapped_handler(
+ descriptor, completed, *this, handler);
+ bool interrupt = write_op_queue_.enqueue_operation(
+ descriptor, wrapped_handler);
+ interrupt = except_op_queue_.enqueue_operation(
+ descriptor, wrapped_handler) || interrupt;
+ if (interrupt)
+ interrupter_.interrupt();
+ }
+ }
+
+ // 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&)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ cancel_ops_unlocked(descriptor);
+ }
+
+ // Enqueue cancellation of all operations associated with the given
+ // descriptor. The handlers associated with the descriptor will be invoked
+ // with the operation_aborted error. This function does not acquire the
+ // select_reactor's mutex, and so should only be used when the reactor lock is
+ // already held.
+ void enqueue_cancel_ops_unlocked(socket_type descriptor)
+ {
+ pending_cancellations_.push_back(descriptor);
+ }
+
+ // 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&)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ cancel_ops_unlocked(descriptor);
+ }
+
+ // Add a new timer queue to the reactor.
+ template <typename Time_Traits>
+ void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ timer_queues_.push_back(&timer_queue);
+ }
+
+ // Remove a timer queue from the reactor.
+ template <typename Time_Traits>
+ void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ {
+ if (timer_queues_[i] == &timer_queue)
+ {
+ timer_queues_.erase(timer_queues_.begin() + i);
+ return;
+ }
+ }
+ }
+
+ // Schedule a timer in the given timer queue to expire at the specified
+ // absolute time. The handler object will be invoked when the timer expires.
+ template <typename Time_Traits, typename Handler>
+ void schedule_timer(timer_queue<Time_Traits>& timer_queue,
+ const typename Time_Traits::time_type& time, Handler handler, void* token)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ if (!shutdown_)
+ if (timer_queue.enqueue_timer(time, handler, token))
+ interrupter_.interrupt();
+ }
+
+ // Cancel the timer associated with the given token. Returns the number of
+ // handlers that have been posted or dispatched.
+ template <typename Time_Traits>
+ std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ std::size_t n = timer_queue.cancel_timer(token);
+ if (n > 0)
+ interrupter_.interrupt();
+ return n;
+ }
+
+private:
+ friend class task_io_service<select_reactor<Own_Thread> >;
+
+ // Run select once until interrupted or events are ready to be dispatched.
+ void run(bool block)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ // Dispatch any operation cancellations that were made while the select
+ // loop was not running.
+ read_op_queue_.perform_cancellations();
+ write_op_queue_.perform_cancellations();
+ except_op_queue_.perform_cancellations();
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ timer_queues_[i]->dispatch_cancellations();
+
+ // Check if the thread is supposed to stop.
+ if (stop_thread_)
+ {
+ complete_operations_and_timers(lock);
+ return;
+ }
+
+ // We can return immediately if there's no work to do and the reactor is
+ // not supposed to block.
+ if (!block && read_op_queue_.empty() && write_op_queue_.empty()
+ && except_op_queue_.empty() && all_timer_queues_are_empty())
+ {
+ complete_operations_and_timers(lock);
+ return;
+ }
+
+ // Set up the descriptor sets.
+ fd_set_adapter read_fds;
+ read_fds.set(interrupter_.read_descriptor());
+ read_op_queue_.get_descriptors(read_fds);
+ fd_set_adapter write_fds;
+ write_op_queue_.get_descriptors(write_fds);
+ fd_set_adapter except_fds;
+ except_op_queue_.get_descriptors(except_fds);
+ socket_type max_fd = read_fds.max_descriptor();
+ if (write_fds.max_descriptor() > max_fd)
+ max_fd = write_fds.max_descriptor();
+ if (except_fds.max_descriptor() > max_fd)
+ max_fd = except_fds.max_descriptor();
+
+ // Block on the select call without holding the lock so that new
+ // operations can be started while the call is executing.
+ timeval tv_buf = { 0, 0 };
+ timeval* tv = block ? get_timeout(tv_buf) : &tv_buf;
+ select_in_progress_ = true;
+ lock.unlock();
+ boost::system::error_code ec;
+ int retval = socket_ops::select(static_cast<int>(max_fd + 1),
+ read_fds, write_fds, except_fds, tv, ec);
+ lock.lock();
+ select_in_progress_ = false;
+
+ // Block signals while dispatching operations.
+ boost::asio::detail::signal_blocker sb;
+
+ // Reset the interrupter.
+ if (retval > 0 && read_fds.is_set(interrupter_.read_descriptor()))
+ interrupter_.reset();
+
+ // Dispatch all ready operations.
+ if (retval > 0)
+ {
+ // Exception operations must be processed first to ensure that any
+ // out-of-band data is read before normal data.
+ except_op_queue_.perform_operations_for_descriptors(
+ except_fds, boost::system::error_code());
+ read_op_queue_.perform_operations_for_descriptors(
+ read_fds, boost::system::error_code());
+ write_op_queue_.perform_operations_for_descriptors(
+ write_fds, boost::system::error_code());
+ except_op_queue_.perform_cancellations();
+ read_op_queue_.perform_cancellations();
+ write_op_queue_.perform_cancellations();
+ }
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ {
+ timer_queues_[i]->dispatch_timers();
+ timer_queues_[i]->dispatch_cancellations();
+ }
+
+ // Issue any pending cancellations.
+ for (size_t i = 0; i < pending_cancellations_.size(); ++i)
+ cancel_ops_unlocked(pending_cancellations_[i]);
+ pending_cancellations_.clear();
+
+ complete_operations_and_timers(lock);
+ }
+
+ // Run the select loop in the thread.
+ void run_thread()
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ while (!stop_thread_)
+ {
+ lock.unlock();
+ run(true);
+ lock.lock();
+ }
+ }
+
+ // Entry point for the select loop thread.
+ static void call_run_thread(select_reactor* reactor)
+ {
+ reactor->run_thread();
+ }
+
+ // Interrupt the select loop.
+ void interrupt()
+ {
+ interrupter_.interrupt();
+ }
+
+ // Check if all timer queues are empty.
+ bool all_timer_queues_are_empty() const
+ {
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ if (!timer_queues_[i]->empty())
+ return false;
+ return true;
+ }
+
+ // Get the timeout value for the select call.
+ timeval* get_timeout(timeval& tv)
+ {
+ if (all_timer_queues_are_empty())
+ return 0;
+
+ // 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.
+ boost::posix_time::time_duration minimum_wait_duration
+ = boost::posix_time::minutes(5);
+
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ {
+ boost::posix_time::time_duration wait_duration
+ = timer_queues_[i]->wait_duration();
+ if (wait_duration < minimum_wait_duration)
+ minimum_wait_duration = wait_duration;
+ }
+
+ if (minimum_wait_duration > boost::posix_time::time_duration())
+ {
+ tv.tv_sec = minimum_wait_duration.total_seconds();
+ tv.tv_usec = minimum_wait_duration.total_microseconds() % 1000000;
+ }
+ else
+ {
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ }
+
+ return &tv;
+ }
+
+ // 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 select_reactor's mutex.
+ void cancel_ops_unlocked(socket_type descriptor)
+ {
+ bool interrupt = read_op_queue_.cancel_operations(descriptor);
+ interrupt = write_op_queue_.cancel_operations(descriptor) || interrupt;
+ interrupt = except_op_queue_.cancel_operations(descriptor) || interrupt;
+ if (interrupt)
+ interrupter_.interrupt();
+ }
+
+ // Clean up operations and timers. We must not hold the lock since the
+ // destructors may make calls back into this reactor. We make a copy of the
+ // vector of timer queues since the original may be modified while the lock
+ // is not held.
+ void complete_operations_and_timers(
+ boost::asio::detail::mutex::scoped_lock& lock)
+ {
+ timer_queues_for_cleanup_ = timer_queues_;
+ lock.unlock();
+ read_op_queue_.complete_operations();
+ write_op_queue_.complete_operations();
+ except_op_queue_.complete_operations();
+ for (std::size_t i = 0; i < timer_queues_for_cleanup_.size(); ++i)
+ timer_queues_for_cleanup_[i]->complete_timers();
+ }
+
+ // Mutex to protect access to internal data.
+ boost::asio::detail::mutex mutex_;
+
+ // Whether the select loop is currently running or not.
+ bool select_in_progress_;
+
+ // The interrupter is used to break a blocking select call.
+ select_interrupter interrupter_;
+
+ // The queue of read operations.
+ reactor_op_queue<socket_type> read_op_queue_;
+
+ // The queue of write operations.
+ reactor_op_queue<socket_type> write_op_queue_;
+
+ // The queue of exception operations.
+ reactor_op_queue<socket_type> except_op_queue_;
+
+ // The timer queues.
+ std::vector<timer_queue_base*> timer_queues_;
+
+ // A copy of the timer queues, used when cleaning up timers. The copy is
+ // stored as a class data member to avoid unnecessary memory allocation.
+ std::vector<timer_queue_base*> timer_queues_for_cleanup_;
+
+ // The descriptors that are pending cancellation.
+ std::vector<socket_type> pending_cancellations_;
+
+ // Does the reactor loop thread need to stop.
+ bool stop_thread_;
+
+ // The thread that is running the reactor loop.
+ boost::asio::detail::thread* thread_;
+
+ // Whether the service has been shut down.
+ bool shutdown_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SELECT_REACTOR_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/select_reactor_fwd.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/select_reactor_fwd.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,33 @@
+//
+// select_reactor_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_SELECT_REACTOR_FWD_HPP
+#define BOOST_ASIO_DETAIL_SELECT_REACTOR_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <bool Own_Thread>
+class select_reactor;
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SELECT_REACTOR_FWD_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/service_base.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/service_base.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,51 @@
+//
+// service_base.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_SERVICE_BASE_HPP
+#define BOOST_ASIO_DETAIL_SERVICE_BASE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/service_id.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// Special service base class to keep classes header-file only.
+template <typename Type>
+class service_base
+ : public boost::asio::io_service::service
+{
+public:
+ static boost::asio::detail::service_id<Type> id;
+
+ // Constructor.
+ service_base(boost::asio::io_service& io_service)
+ : boost::asio::io_service::service(io_service)
+ {
+ }
+};
+
+template <typename Type>
+boost::asio::detail::service_id<Type> service_base<Type>::id;
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SERVICE_BASE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/service_id.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/service_id.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,39 @@
+//
+// service_id.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_SERVICE_ID_HPP
+#define BOOST_ASIO_DETAIL_SERVICE_ID_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/io_service.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// Special derived service id type to keep classes header-file only.
+template <typename Type>
+class service_id
+ : public boost::asio::io_service::id
+{
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SERVICE_ID_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/service_registry.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/service_registry.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,212 @@
+//
+// service_registry.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_SERVICE_REGISTRY_HPP
+#define BOOST_ASIO_DETAIL_SERVICE_REGISTRY_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <memory>
+#include <typeinfo>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/service_id.hpp>
+
+#if defined(BOOST_NO_TYPEID)
+# if !defined(BOOST_ASIO_NO_TYPEID)
+# define BOOST_ASIO_NO_TYPEID
+# endif // !defined(BOOST_ASIO_NO_TYPEID)
+#endif // defined(BOOST_NO_TYPEID)
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class service_registry
+ : private noncopyable
+{
+public:
+ // Constructor.
+ service_registry(boost::asio::io_service& o)
+ : owner_(o),
+ first_service_(0)
+ {
+ }
+
+ // Destructor.
+ ~service_registry()
+ {
+ // Shutdown all services. This must be done in a separate loop before the
+ // services are destroyed since the destructors of user-defined handler
+ // objects may try to access other service objects.
+ boost::asio::io_service::service* service = first_service_;
+ while (service)
+ {
+ service->shutdown_service();
+ service = service->next_;
+ }
+
+ // Destroy all services.
+ while (first_service_)
+ {
+ boost::asio::io_service::service* next_service = first_service_->next_;
+ delete first_service_;
+ first_service_ = next_service;
+ }
+ }
+
+ // Get the service object corresponding to the specified service type. Will
+ // create a new service object automatically if no such object already
+ // exists. Ownership of the service object is not transferred to the caller.
+ template <typename Service>
+ Service& use_service()
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ // First see if there is an existing service object for the given type.
+ boost::asio::io_service::service* service = first_service_;
+ while (service)
+ {
+ if (service_id_matches(*service, Service::id))
+ return *static_cast<Service*>(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();
+ std::auto_ptr<Service> new_service(new Service(owner_));
+ init_service_id(*new_service, Service::id);
+ Service& new_service_ref = *new_service;
+ 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 (service_id_matches(*service, Service::id))
+ return *static_cast<Service*>(service);
+ service = service->next_;
+ }
+
+ // Service was successfully initialised, pass ownership to registry.
+ new_service->next_ = first_service_;
+ first_service_ = new_service.release();
+
+ return new_service_ref;
+ }
+
+ // Add a service object. Returns false on error, in which case ownership of
+ // the object is retained by the caller.
+ template <typename Service>
+ bool add_service(Service* new_service)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ // Check if there is an existing service object for the given type.
+ boost::asio::io_service::service* service = first_service_;
+ while (service)
+ {
+ if (service_id_matches(*service, Service::id))
+ return false;
+ service = service->next_;
+ }
+
+ // Take ownership of the service object.
+ init_service_id(*new_service, Service::id);
+ new_service->next_ = first_service_;
+ first_service_ = new_service;
+
+ return true;
+ }
+
+ // Check whether a service object of the specified type already exists.
+ template <typename Service>
+ bool has_service() const
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ boost::asio::io_service::service* service = first_service_;
+ while (service)
+ {
+ if (service_id_matches(*service, Service::id))
+ return true;
+ service = service->next_;
+ }
+
+ return false;
+ }
+
+private:
+ // Set a service's id.
+ void init_service_id(boost::asio::io_service::service& service,
+ const boost::asio::io_service::id& id)
+ {
+ service.type_info_ = 0;
+ service.id_ = &id;
+ }
+
+#if !defined(BOOST_ASIO_NO_TYPEID)
+ // Set a service's id.
+ template <typename Service>
+ void init_service_id(boost::asio::io_service::service& service,
+ const boost::asio::detail::service_id<Service>& /*id*/)
+ {
+ service.type_info_ = &typeid(Service);
+ service.id_ = 0;
+ }
+#endif // !defined(BOOST_ASIO_NO_TYPEID)
+
+ // Check if a service matches the given id.
+ static bool service_id_matches(
+ const boost::asio::io_service::service& service,
+ const boost::asio::io_service::id& id)
+ {
+ return service.id_ == &id;
+ }
+
+#if !defined(BOOST_ASIO_NO_TYPEID)
+ // Check if a service matches the given id.
+ template <typename Service>
+ static bool service_id_matches(
+ const boost::asio::io_service::service& service,
+ const boost::asio::detail::service_id<Service>& /*id*/)
+ {
+ return service.type_info_ != 0 && *service.type_info_ == typeid(Service);
+ }
+#endif // !defined(BOOST_ASIO_NO_TYPEID)
+
+ // Mutex to protect access to internal data.
+ mutable boost::asio::detail::mutex mutex_;
+
+ // The owner of this service registry and the services it contains.
+ boost::asio::io_service& owner_;
+
+ // The first service in the list of contained services.
+ boost::asio::io_service::service* first_service_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SERVICE_REGISTRY_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/service_registry_fwd.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/service_registry_fwd.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,32 @@
+//
+// service_registry_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_SERVICE_REGISTRY_FWD_HPP
+#define BOOST_ASIO_DETAIL_SERVICE_REGISTRY_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class service_registry;
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SERVICE_REGISTRY_FWD_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/signal_blocker.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/signal_blocker.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,52 @@
+//
+// signal_blocker.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_SIGNAL_BLOCKER_HPP
+#define BOOST_ASIO_DETAIL_SIGNAL_BLOCKER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if !defined(BOOST_HAS_THREADS)
+# include <boost/asio/detail/null_signal_blocker.hpp>
+#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# include <boost/asio/detail/win_signal_blocker.hpp>
+#elif defined(BOOST_HAS_PTHREADS)
+# include <boost/asio/detail/posix_signal_blocker.hpp>
+#else
+# error Only Windows and POSIX are supported!
+#endif
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+#if !defined(BOOST_HAS_THREADS)
+typedef null_signal_blocker signal_blocker;
+#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+typedef win_signal_blocker signal_blocker;
+#elif defined(BOOST_HAS_PTHREADS)
+typedef posix_signal_blocker signal_blocker;
+#endif
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SIGNAL_BLOCKER_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/signal_init.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/signal_init.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,53 @@
+//
+// signal_init.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_SIGNAL_INIT_HPP
+#define BOOST_ASIO_DETAIL_SIGNAL_INIT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include <boost/asio/detail/push_options.hpp>
+#include <csignal>
+#include <boost/asio/detail/pop_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <int Signal = SIGPIPE>
+class signal_init
+{
+public:
+ // Constructor.
+ signal_init()
+ {
+ std::signal(Signal, SIG_IGN);
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SIGNAL_INIT_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/socket_holder.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/socket_holder.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,97 @@
+//
+// socket_holder.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_SOCKET_HOLDER_HPP
+#define BOOST_ASIO_DETAIL_SOCKET_HOLDER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// Implement the resource acquisition is initialisation idiom for sockets.
+class socket_holder
+ : private noncopyable
+{
+public:
+ // Construct as an uninitialised socket.
+ socket_holder()
+ : socket_(invalid_socket)
+ {
+ }
+
+ // Construct to take ownership of the specified socket.
+ explicit socket_holder(socket_type s)
+ : socket_(s)
+ {
+ }
+
+ // Destructor.
+ ~socket_holder()
+ {
+ if (socket_ != invalid_socket)
+ {
+ boost::system::error_code ec;
+ socket_ops::close(socket_, ec);
+ }
+ }
+
+ // Get the underlying socket.
+ socket_type get() const
+ {
+ return socket_;
+ }
+
+ // Reset to an uninitialised socket.
+ void reset()
+ {
+ if (socket_ != invalid_socket)
+ {
+ boost::system::error_code ec;
+ socket_ops::close(socket_, ec);
+ socket_ = invalid_socket;
+ }
+ }
+
+ // Reset to take ownership of the specified socket.
+ void reset(socket_type s)
+ {
+ reset();
+ socket_ = s;
+ }
+
+ // Release ownership of the socket.
+ socket_type release()
+ {
+ socket_type tmp = socket_;
+ socket_ = invalid_socket;
+ return tmp;
+ }
+
+private:
+ // The underlying socket.
+ socket_type socket_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SOCKET_HOLDER_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/socket_ops.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/socket_ops.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,1895 @@
+//
+// socket_ops.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_SOCKET_OPS_HPP
+#define BOOST_ASIO_DETAIL_SOCKET_OPS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/assert.hpp>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+#include <boost/detail/workaround.hpp>
+#include <new>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+namespace socket_ops {
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+struct msghdr { int msg_namelen; };
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#if defined(__hpux)
+// HP-UX doesn't declare these functions extern "C", so they are declared again
+// here to avoid linker errors about undefined symbols.
+extern "C" char* if_indextoname(unsigned int, char*);
+extern "C" unsigned int if_nametoindex(const char*);
+#endif // defined(__hpux)
+
+inline void clear_error(boost::system::error_code& ec)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ WSASetLastError(0);
+#else
+ errno = 0;
+#endif
+ ec = boost::system::error_code();
+}
+
+template <typename ReturnType>
+inline ReturnType error_wrapper(ReturnType return_value,
+ boost::system::error_code& ec)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ ec = boost::system::error_code(WSAGetLastError(),
+ boost::asio::error::get_system_category());
+#else
+ ec = boost::system::error_code(errno,
+ boost::asio::error::get_system_category());
+#endif
+ return return_value;
+}
+
+template <typename SockLenType>
+inline socket_type call_accept(SockLenType msghdr::*,
+ socket_type s, socket_addr_type* addr, std::size_t* addrlen)
+{
+ SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0;
+ socket_type result = ::accept(s, addr, addrlen ? &tmp_addrlen : 0);
+ if (addrlen)
+ *addrlen = (std::size_t)tmp_addrlen;
+ return result;
+}
+
+inline socket_type accept(socket_type s, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec)
+{
+ clear_error(ec);
+
+ socket_type new_s = error_wrapper(call_accept(
+ &msghdr::msg_namelen, s, addr, addrlen), ec);
+ if (new_s == invalid_socket)
+ return new_s;
+
+#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
+ int optval = 1;
+ int result = error_wrapper(::setsockopt(new_s,
+ SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec);
+ if (result != 0)
+ {
+ ::close(new_s);
+ return invalid_socket;
+ }
+#endif
+
+#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
+ clear_error(ec);
+#endif
+
+ return new_s;
+}
+
+template <typename SockLenType>
+inline int call_bind(SockLenType msghdr::*,
+ socket_type s, const socket_addr_type* addr, std::size_t addrlen)
+{
+ return ::bind(s, addr, (SockLenType)addrlen);
+}
+
+inline int bind(socket_type s, const socket_addr_type* addr,
+ std::size_t addrlen, boost::system::error_code& ec)
+{
+ clear_error(ec);
+ int result = error_wrapper(call_bind(
+ &msghdr::msg_namelen, s, addr, addrlen), ec);
+#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
+ if (result == 0)
+ clear_error(ec);
+#endif
+ return result;
+}
+
+inline int close(socket_type s, boost::system::error_code& ec)
+{
+ clear_error(ec);
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ int result = error_wrapper(::closesocket(s), ec);
+# if defined(UNDER_CE)
+ if (result == 0)
+ clear_error(ec);
+# endif
+ return result;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ return error_wrapper(::close(s), ec);
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+inline int shutdown(socket_type s, int what, boost::system::error_code& ec)
+{
+ clear_error(ec);
+ int result = error_wrapper(::shutdown(s, what), ec);
+#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
+ if (result == 0)
+ clear_error(ec);
+#endif
+ return result;
+}
+
+template <typename SockLenType>
+inline int call_connect(SockLenType msghdr::*,
+ socket_type s, const socket_addr_type* addr, std::size_t addrlen)
+{
+ return ::connect(s, addr, (SockLenType)addrlen);
+}
+
+inline int connect(socket_type s, const socket_addr_type* addr,
+ std::size_t addrlen, boost::system::error_code& ec)
+{
+ clear_error(ec);
+ int result = error_wrapper(call_connect(
+ &msghdr::msg_namelen, s, addr, addrlen), ec);
+#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
+ if (result == 0)
+ clear_error(ec);
+#endif
+ return result;
+}
+
+inline int socketpair(int af, int type, int protocol,
+ socket_type sv[2], boost::system::error_code& ec)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ (void)(af);
+ (void)(type);
+ (void)(protocol);
+ (void)(sv);
+ ec = boost::asio::error::operation_not_supported;
+ return -1;
+#else
+ clear_error(ec);
+ return error_wrapper(::socketpair(af, type, protocol, sv), ec);
+#endif
+}
+
+inline int listen(socket_type s, int backlog, boost::system::error_code& ec)
+{
+ clear_error(ec);
+ int result = error_wrapper(::listen(s, backlog), ec);
+#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
+ if (result == 0)
+ clear_error(ec);
+#endif
+ return result;
+}
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+typedef WSABUF buf;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+typedef iovec buf;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+inline void init_buf(buf& b, void* data, size_t size)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ b.buf = static_cast<char*>(data);
+ b.len = static_cast<u_long>(size);
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ b.iov_base = data;
+ b.iov_len = size;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+inline void init_buf(buf& b, const void* data, size_t size)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ b.buf = static_cast<char*>(const_cast<void*>(data));
+ b.len = static_cast<u_long>(size);
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ b.iov_base = const_cast<void*>(data);
+ b.iov_len = size;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+inline void init_msghdr_msg_name(void*& name, socket_addr_type* addr)
+{
+ name = addr;
+}
+
+inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr)
+{
+ name = const_cast<socket_addr_type*>(addr);
+}
+
+template <typename T>
+inline void init_msghdr_msg_name(T& name, socket_addr_type* addr)
+{
+ name = reinterpret_cast<T>(addr);
+}
+
+template <typename T>
+inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr)
+{
+ name = reinterpret_cast<T>(const_cast<socket_addr_type*>(addr));
+}
+
+inline int recv(socket_type s, buf* bufs, size_t count, int flags,
+ boost::system::error_code& ec)
+{
+ clear_error(ec);
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ // Receive some data.
+ DWORD recv_buf_count = static_cast<DWORD>(count);
+ DWORD bytes_transferred = 0;
+ DWORD recv_flags = flags;
+ int result = error_wrapper(::WSARecv(s, bufs,
+ recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec);
+ if (result != 0)
+ return -1;
+# if defined(UNDER_CE)
+ clear_error(ec);
+# endif
+ return bytes_transferred;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ msghdr msg = msghdr();
+ msg.msg_iov = bufs;
+ msg.msg_iovlen = count;
+ return error_wrapper(::recvmsg(s, &msg, flags), ec);
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+inline int recvfrom(socket_type s, buf* bufs, size_t count, int flags,
+ socket_addr_type* addr, std::size_t* addrlen,
+ boost::system::error_code& ec)
+{
+ clear_error(ec);
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ // Receive some data.
+ DWORD recv_buf_count = static_cast<DWORD>(count);
+ DWORD bytes_transferred = 0;
+ DWORD recv_flags = flags;
+ int tmp_addrlen = (int)*addrlen;
+ int result = error_wrapper(::WSARecvFrom(s, bufs, recv_buf_count,
+ &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0), ec);
+ *addrlen = (std::size_t)tmp_addrlen;
+ if (result != 0)
+ return -1;
+# if defined(UNDER_CE)
+ clear_error(ec);
+# endif
+ return bytes_transferred;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ msghdr msg = msghdr();
+ init_msghdr_msg_name(msg.msg_name, addr);
+ msg.msg_namelen = *addrlen;
+ msg.msg_iov = bufs;
+ msg.msg_iovlen = count;
+ int result = error_wrapper(::recvmsg(s, &msg, flags), ec);
+ *addrlen = msg.msg_namelen;
+ return result;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+inline int send(socket_type s, const buf* bufs, size_t count, int flags,
+ boost::system::error_code& ec)
+{
+ clear_error(ec);
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ // Send the data.
+ DWORD send_buf_count = static_cast<DWORD>(count);
+ DWORD bytes_transferred = 0;
+ DWORD send_flags = flags;
+ int result = error_wrapper(::WSASend(s, const_cast<buf*>(bufs),
+ send_buf_count, &bytes_transferred, send_flags, 0, 0), ec);
+ if (result != 0)
+ return -1;
+# if defined(UNDER_CE)
+ clear_error(ec);
+# endif
+ return bytes_transferred;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ msghdr msg = msghdr();
+ msg.msg_iov = const_cast<buf*>(bufs);
+ msg.msg_iovlen = count;
+#if defined(__linux__)
+ flags |= MSG_NOSIGNAL;
+#endif // defined(__linux__)
+ return error_wrapper(::sendmsg(s, &msg, flags), ec);
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+inline int sendto(socket_type s, const buf* bufs, size_t count, int flags,
+ const socket_addr_type* addr, std::size_t addrlen,
+ boost::system::error_code& ec)
+{
+ clear_error(ec);
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ // Send the data.
+ DWORD send_buf_count = static_cast<DWORD>(count);
+ DWORD bytes_transferred = 0;
+ int result = error_wrapper(::WSASendTo(s, const_cast<buf*>(bufs),
+ send_buf_count, &bytes_transferred, flags, addr,
+ static_cast<int>(addrlen), 0, 0), ec);
+ if (result != 0)
+ return -1;
+# if defined(UNDER_CE)
+ clear_error(ec);
+# endif
+ return bytes_transferred;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ msghdr msg = msghdr();
+ init_msghdr_msg_name(msg.msg_name, addr);
+ msg.msg_namelen = addrlen;
+ msg.msg_iov = const_cast<buf*>(bufs);
+ msg.msg_iovlen = count;
+#if defined(__linux__)
+ flags |= MSG_NOSIGNAL;
+#endif // defined(__linux__)
+ return error_wrapper(::sendmsg(s, &msg, flags), ec);
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+inline socket_type socket(int af, int type, int protocol,
+ boost::system::error_code& ec)
+{
+ clear_error(ec);
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ socket_type s = error_wrapper(::WSASocket(af, type, protocol, 0, 0,
+ WSA_FLAG_OVERLAPPED), ec);
+ if (s == invalid_socket)
+ return s;
+
+ if (af == AF_INET6)
+ {
+ // Try to enable the POSIX default behaviour of having IPV6_V6ONLY set to
+ // false. This will only succeed on Windows Vista and later versions of
+ // Windows, where a dual-stack IPv4/v6 implementation is available.
+ DWORD optval = 0;
+ ::setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
+ reinterpret_cast<const char*>(&optval), sizeof(optval));
+ }
+
+# if defined(UNDER_CE)
+ clear_error(ec);
+# endif
+
+ return s;
+#elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
+ socket_type s = error_wrapper(::socket(af, type, protocol), ec);
+ if (s == invalid_socket)
+ return s;
+
+ int optval = 1;
+ int result = error_wrapper(::setsockopt(s,
+ SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)), ec);
+ if (result != 0)
+ {
+ ::close(s);
+ return invalid_socket;
+ }
+
+ return s;
+#else
+ return error_wrapper(::socket(af, type, protocol), ec);
+#endif
+}
+
+template <typename SockLenType>
+inline int call_setsockopt(SockLenType msghdr::*,
+ socket_type s, int level, int optname,
+ const void* optval, std::size_t optlen)
+{
+ return ::setsockopt(s, level, optname,
+ (const char*)optval, (SockLenType)optlen);
+}
+
+inline int setsockopt(socket_type s, int level, int optname,
+ const void* optval, std::size_t optlen, boost::system::error_code& ec)
+{
+ if (level == custom_socket_option_level && optname == always_fail_option)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return -1;
+ }
+
+#if defined(__BORLANDC__)
+ // Mysteriously, using the getsockopt and setsockopt functions directly with
+ // Borland C++ results in incorrect values being set and read. The bug can be
+ // worked around by using function addresses resolved with GetProcAddress.
+ if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
+ {
+ typedef int (WSAAPI *sso_t)(SOCKET, int, int, const char*, int);
+ if (sso_t sso = (sso_t)::GetProcAddress(winsock_module, "setsockopt"))
+ {
+ clear_error(ec);
+ return error_wrapper(sso(s, level, optname,
+ reinterpret_cast<const char*>(optval),
+ static_cast<int>(optlen)), ec);
+ }
+ }
+ ec = boost::asio::error::fault;
+ return -1;
+#else // defined(__BORLANDC__)
+ clear_error(ec);
+ int result = error_wrapper(call_setsockopt(&msghdr::msg_namelen,
+ s, level, optname, optval, optlen), ec);
+# if defined(BOOST_WINDOWS) && defined(UNDER_CE)
+ if (result == 0)
+ clear_error(ec);
+# endif
+ return result;
+#endif // defined(__BORLANDC__)
+}
+
+template <typename SockLenType>
+inline int call_getsockopt(SockLenType msghdr::*,
+ socket_type s, int level, int optname,
+ void* optval, std::size_t* optlen)
+{
+ SockLenType tmp_optlen = (SockLenType)*optlen;
+ int result = ::getsockopt(s, level, optname, (char*)optval, &tmp_optlen);
+ *optlen = (std::size_t)tmp_optlen;
+ return result;
+}
+
+inline int getsockopt(socket_type s, int level, int optname, void* optval,
+ size_t* optlen, boost::system::error_code& ec)
+{
+ if (level == custom_socket_option_level && optname == always_fail_option)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return -1;
+ }
+
+#if defined(__BORLANDC__)
+ // Mysteriously, using the getsockopt and setsockopt functions directly with
+ // Borland C++ results in incorrect values being set and read. The bug can be
+ // worked around by using function addresses resolved with GetProcAddress.
+ if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
+ {
+ typedef int (WSAAPI *gso_t)(SOCKET, int, int, char*, int*);
+ if (gso_t gso = (gso_t)::GetProcAddress(winsock_module, "getsockopt"))
+ {
+ clear_error(ec);
+ int tmp_optlen = static_cast<int>(*optlen);
+ int result = error_wrapper(gso(s, level, optname,
+ reinterpret_cast<char*>(optval), &tmp_optlen), ec);
+ *optlen = static_cast<size_t>(tmp_optlen);
+ if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
+ && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
+ {
+ // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are
+ // only supported on Windows Vista and later. To simplify program logic
+ // we will fake success of getting this option and specify that the
+ // value is non-zero (i.e. true). This corresponds to the behavior of
+ // IPv6 sockets on Windows platforms pre-Vista.
+ *static_cast<DWORD*>(optval) = 1;
+ clear_error(ec);
+ }
+ return result;
+ }
+ }
+ ec = boost::asio::error::fault;
+ return -1;
+#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ clear_error(ec);
+ int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
+ s, level, optname, optval, optlen), ec);
+ if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY
+ && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))
+ {
+ // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are only
+ // supported on Windows Vista and later. To simplify program logic we will
+ // fake success of getting this option and specify that the value is
+ // non-zero (i.e. true). This corresponds to the behavior of IPv6 sockets
+ // on Windows platforms pre-Vista.
+ *static_cast<DWORD*>(optval) = 1;
+ clear_error(ec);
+ }
+# if defined(UNDER_CE)
+ if (result == 0)
+ clear_error(ec);
+# endif
+ return result;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ clear_error(ec);
+ int result = error_wrapper(call_getsockopt(&msghdr::msg_namelen,
+ s, level, optname, optval, optlen), ec);
+#if defined(__linux__)
+ if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int)
+ && (optname == SO_SNDBUF || optname == SO_RCVBUF))
+ {
+ // On Linux, setting SO_SNDBUF or SO_RCVBUF to N actually causes the kernel
+ // to set the buffer size to N*2. Linux puts additional stuff into the
+ // buffers so that only about half is actually available to the application.
+ // The retrieved value is divided by 2 here to make it appear as though the
+ // correct value has been set.
+ *static_cast<int*>(optval) /= 2;
+ }
+#endif // defined(__linux__)
+ return result;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+template <typename SockLenType>
+inline int call_getpeername(SockLenType msghdr::*,
+ socket_type s, socket_addr_type* addr, std::size_t* addrlen)
+{
+ SockLenType tmp_addrlen = (SockLenType)*addrlen;
+ int result = ::getpeername(s, addr, &tmp_addrlen);
+ *addrlen = (std::size_t)tmp_addrlen;
+ return result;
+}
+
+inline int getpeername(socket_type s, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec)
+{
+ clear_error(ec);
+ int result = error_wrapper(call_getpeername(
+ &msghdr::msg_namelen, s, addr, addrlen), ec);
+#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
+ if (result == 0)
+ clear_error(ec);
+#endif
+ return result;
+}
+
+template <typename SockLenType>
+inline int call_getsockname(SockLenType msghdr::*,
+ socket_type s, socket_addr_type* addr, std::size_t* addrlen)
+{
+ SockLenType tmp_addrlen = (SockLenType)*addrlen;
+ int result = ::getsockname(s, addr, &tmp_addrlen);
+ *addrlen = (std::size_t)tmp_addrlen;
+ return result;
+}
+
+inline int getsockname(socket_type s, socket_addr_type* addr,
+ std::size_t* addrlen, boost::system::error_code& ec)
+{
+ clear_error(ec);
+ int result = error_wrapper(call_getsockname(
+ &msghdr::msg_namelen, s, addr, addrlen), ec);
+#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
+ if (result == 0)
+ clear_error(ec);
+#endif
+ return result;
+}
+
+inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg,
+ boost::system::error_code& ec)
+{
+ clear_error(ec);
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ int result = error_wrapper(::ioctlsocket(s, cmd, arg), ec);
+# if defined(UNDER_CE)
+ if (result == 0)
+ clear_error(ec);
+# endif
+ return result;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ return error_wrapper(::ioctl(s, cmd, arg), ec);
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+inline int select(int nfds, fd_set* readfds, fd_set* writefds,
+ fd_set* exceptfds, timeval* timeout, boost::system::error_code& ec)
+{
+ clear_error(ec);
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ if (!readfds && !writefds && !exceptfds && timeout)
+ {
+ DWORD milliseconds = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
+ if (milliseconds == 0)
+ milliseconds = 1; // Force context switch.
+ ::Sleep(milliseconds);
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ // The select() call allows timeout values measured in microseconds, but the
+ // system clock (as wrapped by boost::posix_time::microsec_clock) typically
+ // has a resolution of 10 milliseconds. This can lead to a spinning select
+ // reactor, meaning increased CPU usage, when waiting for the earliest
+ // scheduled timeout if it's less than 10 milliseconds away. To avoid a tight
+ // spin we'll use a minimum timeout of 1 millisecond.
+ if (timeout && timeout->tv_sec == 0
+ && timeout->tv_usec > 0 && timeout->tv_usec < 1000)
+ timeout->tv_usec = 1000;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#if defined(__hpux) && defined(__HP_aCC)
+ timespec ts;
+ ts.tv_sec = timeout ? timeout->tv_sec : 0;
+ ts.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0;
+ return error_wrapper(::pselect(nfds, readfds,
+ writefds, exceptfds, timeout ? &ts : 0, 0), ec);
+#else
+ int result = error_wrapper(::select(nfds, readfds,
+ writefds, exceptfds, timeout), ec);
+# if defined(BOOST_WINDOWS) && defined(UNDER_CE)
+ if (result >= 0)
+ clear_error(ec);
+# endif
+ return result;
+#endif
+}
+
+inline int poll_read(socket_type s, boost::system::error_code& ec)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ FD_SET fds;
+ FD_ZERO(&fds);
+ FD_SET(s, &fds);
+ clear_error(ec);
+ int result = error_wrapper(::select(s, &fds, 0, 0, 0), ec);
+# if defined(UNDER_CE)
+ if (result >= 0)
+ clear_error(ec);
+# endif
+ return result;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ pollfd fds;
+ fds.fd = s;
+ fds.events = POLLIN;
+ fds.revents = 0;
+ clear_error(ec);
+ return error_wrapper(::poll(&fds, 1, -1), ec);
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+inline int poll_write(socket_type s, boost::system::error_code& ec)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ FD_SET fds;
+ FD_ZERO(&fds);
+ FD_SET(s, &fds);
+ clear_error(ec);
+ int result = error_wrapper(::select(s, 0, &fds, 0, 0), ec);
+# if defined(UNDER_CE)
+ if (result >= 0)
+ clear_error(ec);
+# endif
+ return result;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ pollfd fds;
+ fds.fd = s;
+ fds.events = POLLOUT;
+ fds.revents = 0;
+ clear_error(ec);
+ return error_wrapper(::poll(&fds, 1, -1), ec);
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+inline const char* inet_ntop(int af, const void* src, char* dest, size_t length,
+ unsigned long scope_id, boost::system::error_code& ec)
+{
+ clear_error(ec);
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ using namespace std; // For memcpy.
+
+ if (af != AF_INET && af != AF_INET6)
+ {
+ ec = boost::asio::error::address_family_not_supported;
+ return 0;
+ }
+
+ union
+ {
+ socket_addr_type base;
+ sockaddr_storage_type storage;
+ sockaddr_in4_type v4;
+ sockaddr_in6_type v6;
+ } address;
+ DWORD address_length;
+ if (af == AF_INET)
+ {
+ address_length = sizeof(sockaddr_in4_type);
+ address.v4.sin_family = AF_INET;
+ address.v4.sin_port = 0;
+ memcpy(&address.v4.sin_addr, src, sizeof(in4_addr_type));
+ }
+ else // AF_INET6
+ {
+ address_length = sizeof(sockaddr_in6_type);
+ address.v6.sin6_family = AF_INET6;
+ address.v6.sin6_port = 0;
+ address.v6.sin6_flowinfo = 0;
+ address.v6.sin6_scope_id = scope_id;
+ memcpy(&address.v6.sin6_addr, src, sizeof(in6_addr_type));
+ }
+
+ DWORD string_length = static_cast<DWORD>(length);
+#if defined(BOOST_NO_ANSI_APIS)
+ LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR));
+ int result = error_wrapper(::WSAAddressToStringW(&address.base,
+ address_length, 0, string_buffer, &string_length), ec);
+ ::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1, dest, length, 0, 0);
+#else
+ int result = error_wrapper(::WSAAddressToStringA(
+ &address.base, address_length, 0, dest, &string_length), ec);
+#endif
+
+ // Windows may set error code on success.
+ if (result != socket_error_retval)
+ clear_error(ec);
+
+ // Windows may not set an error code on failure.
+ else if (result == socket_error_retval && !ec)
+ ec = boost::asio::error::invalid_argument;
+
+ return result == socket_error_retval ? 0 : dest;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ const char* result = error_wrapper(::inet_ntop(af, src, dest, length), ec);
+ if (result == 0 && !ec)
+ ec = boost::asio::error::invalid_argument;
+ if (result != 0 && af == AF_INET6 && scope_id != 0)
+ {
+ using namespace std; // For strcat and sprintf.
+ char if_name[IF_NAMESIZE + 1] = "%";
+ const in6_addr_type* ipv6_address = static_cast<const in6_addr_type*>(src);
+ bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address);
+ if (!is_link_local || if_indextoname(scope_id, if_name + 1) == 0)
+ sprintf(if_name + 1, "%lu", scope_id);
+ strcat(dest, if_name);
+ }
+ return result;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+inline int inet_pton(int af, const char* src, void* dest,
+ unsigned long* scope_id, boost::system::error_code& ec)
+{
+ clear_error(ec);
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ using namespace std; // For memcpy and strcmp.
+
+ if (af != AF_INET && af != AF_INET6)
+ {
+ ec = boost::asio::error::address_family_not_supported;
+ return -1;
+ }
+
+ union
+ {
+ socket_addr_type base;
+ sockaddr_storage_type storage;
+ sockaddr_in4_type v4;
+ sockaddr_in6_type v6;
+ } address;
+ int address_length = sizeof(sockaddr_storage_type);
+#if defined(BOOST_NO_ANSI_APIS)
+ int num_wide_chars = strlen(src) + 1;
+ LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR));
+ ::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars);
+ int result = error_wrapper(::WSAStringToAddressW(
+ wide_buffer, af, 0, &address.base, &address_length), ec);
+#else
+ int result = error_wrapper(::WSAStringToAddressA(
+ const_cast<char*>(src), af, 0, &address.base, &address_length), ec);
+#endif
+
+ if (af == AF_INET)
+ {
+ if (result != socket_error_retval)
+ {
+ memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type));
+ clear_error(ec);
+ }
+ else if (strcmp(src, "255.255.255.255") == 0)
+ {
+ static_cast<in4_addr_type*>(dest)->s_addr = INADDR_NONE;
+ clear_error(ec);
+ }
+ }
+ else // AF_INET6
+ {
+ if (result != socket_error_retval)
+ {
+ memcpy(dest, &address.v6.sin6_addr, sizeof(in6_addr_type));
+ if (scope_id)
+ *scope_id = address.v6.sin6_scope_id;
+ clear_error(ec);
+ }
+ }
+
+ // Windows may not set an error code on failure.
+ if (result == socket_error_retval && !ec)
+ ec = boost::asio::error::invalid_argument;
+
+#if defined(UNDER_CE)
+ if (result != socket_error_retval)
+ clear_error(ec);
+#endif
+
+ return result == socket_error_retval ? -1 : 1;
+#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ int result = error_wrapper(::inet_pton(af, src, dest), ec);
+ if (result <= 0 && !ec)
+ ec = boost::asio::error::invalid_argument;
+ if (result > 0 && af == AF_INET6 && scope_id)
+ {
+ using namespace std; // For strchr and atoi.
+ *scope_id = 0;
+ if (const char* if_name = strchr(src, '%'))
+ {
+ in6_addr_type* ipv6_address = static_cast<in6_addr_type*>(dest);
+ bool is_link_local = IN6_IS_ADDR_LINKLOCAL(ipv6_address);
+ if (is_link_local)
+ *scope_id = if_nametoindex(if_name + 1);
+ if (*scope_id == 0)
+ *scope_id = atoi(if_name + 1);
+ }
+ }
+ return result;
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+}
+
+inline int gethostname(char* name, int namelen, boost::system::error_code& ec)
+{
+ clear_error(ec);
+ int result = error_wrapper(::gethostname(name, namelen), ec);
+#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
+ if (result == 0)
+ clear_error(ec);
+#endif
+ return result;
+}
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) \
+ || defined(__MACH__) && defined(__APPLE__)
+
+// The following functions are only needed for emulation of getaddrinfo and
+// getnameinfo.
+
+inline boost::system::error_code translate_netdb_error(int error)
+{
+ switch (error)
+ {
+ case 0:
+ return boost::system::error_code();
+ case HOST_NOT_FOUND:
+ return boost::asio::error::host_not_found;
+ case TRY_AGAIN:
+ return boost::asio::error::host_not_found_try_again;
+ case NO_RECOVERY:
+ return boost::asio::error::no_recovery;
+ case NO_DATA:
+ return boost::asio::error::no_data;
+ default:
+ BOOST_ASSERT(false);
+ return boost::asio::error::invalid_argument;
+ }
+}
+
+inline hostent* gethostbyaddr(const char* addr, int length, int af,
+ hostent* result, char* buffer, int buflength, boost::system::error_code& ec)
+{
+ clear_error(ec);
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ (void)(buffer);
+ (void)(buflength);
+ hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec);
+ if (!retval)
+ return 0;
+# if defined(UNDER_CE)
+ clear_error(ec);
+# endif
+ *result = *retval;
+ return retval;
+#elif defined(__sun) || defined(__QNX__)
+ int error = 0;
+ hostent* retval = error_wrapper(::gethostbyaddr_r(addr, length, af, result,
+ buffer, buflength, &error), ec);
+ if (error)
+ ec = translate_netdb_error(error);
+ return retval;
+#elif defined(__MACH__) && defined(__APPLE__)
+ (void)(buffer);
+ (void)(buflength);
+ int error = 0;
+ hostent* retval = error_wrapper(::getipnodebyaddr(
+ addr, length, af, &error), ec);
+ if (error)
+ ec = translate_netdb_error(error);
+ if (!retval)
+ return 0;
+ *result = *retval;
+ return retval;
+#else
+ hostent* retval = 0;
+ int error = 0;
+ error_wrapper(::gethostbyaddr_r(addr, length, af, result, buffer,
+ buflength, &retval, &error), ec);
+ if (error)
+ ec = translate_netdb_error(error);
+ return retval;
+#endif
+}
+
+inline hostent* gethostbyname(const char* name, int af, struct hostent* result,
+ char* buffer, int buflength, int ai_flags, boost::system::error_code& ec)
+{
+ clear_error(ec);
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ (void)(buffer);
+ (void)(buflength);
+ (void)(ai_flags);
+ if (af != AF_INET)
+ {
+ ec = boost::asio::error::address_family_not_supported;
+ return 0;
+ }
+ hostent* retval = error_wrapper(::gethostbyname(name), ec);
+ if (!retval)
+ return 0;
+# if defined(UNDER_CE)
+ clear_error(ec);
+# endif
+ *result = *retval;
+ return result;
+#elif defined(__sun) || defined(__QNX__)
+ (void)(ai_flags);
+ if (af != AF_INET)
+ {
+ ec = boost::asio::error::address_family_not_supported;
+ return 0;
+ }
+ int error = 0;
+ hostent* retval = error_wrapper(::gethostbyname_r(name, result, buffer,
+ buflength, &error), ec);
+ if (error)
+ ec = translate_netdb_error(error);
+ return retval;
+#elif defined(__MACH__) && defined(__APPLE__)
+ (void)(buffer);
+ (void)(buflength);
+ int error = 0;
+ hostent* retval = error_wrapper(::getipnodebyname(
+ name, af, ai_flags, &error), ec);
+ if (error)
+ ec = translate_netdb_error(error);
+ if (!retval)
+ return 0;
+ *result = *retval;
+ return retval;
+#else
+ (void)(ai_flags);
+ if (af != AF_INET)
+ {
+ ec = boost::asio::error::address_family_not_supported;
+ return 0;
+ }
+ hostent* retval = 0;
+ int error = 0;
+ error_wrapper(::gethostbyname_r(name, result,
+ buffer, buflength, &retval, &error), ec);
+ if (error)
+ ec = translate_netdb_error(error);
+ return retval;
+#endif
+}
+
+inline void freehostent(hostent* h)
+{
+#if defined(__MACH__) && defined(__APPLE__)
+ if (h)
+ ::freehostent(h);
+#else
+ (void)(h);
+#endif
+}
+
+// Emulation of getaddrinfo based on implementation in:
+// Stevens, W. R., UNIX Network Programming Vol. 1, 2nd Ed., Prentice-Hall 1998.
+
+struct gai_search
+{
+ const char* host;
+ int family;
+};
+
+inline int gai_nsearch(const char* host,
+ const addrinfo_type* hints, gai_search (&search)[2])
+{
+ int search_count = 0;
+ if (host == 0 || host[0] == '\0')
+ {
+ if (hints->ai_flags & AI_PASSIVE)
+ {
+ // No host and AI_PASSIVE implies wildcard bind.
+ switch (hints->ai_family)
+ {
+ case AF_INET:
+ search[search_count].host = "0.0.0.0";
+ search[search_count].family = AF_INET;
+ ++search_count;
+ break;
+ case AF_INET6:
+ search[search_count].host = "0::0";
+ search[search_count].family = AF_INET6;
+ ++search_count;
+ break;
+ case AF_UNSPEC:
+ search[search_count].host = "0::0";
+ search[search_count].family = AF_INET6;
+ ++search_count;
+ search[search_count].host = "0.0.0.0";
+ search[search_count].family = AF_INET;
+ ++search_count;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // No host and not AI_PASSIVE means connect to local host.
+ switch (hints->ai_family)
+ {
+ case AF_INET:
+ search[search_count].host = "localhost";
+ search[search_count].family = AF_INET;
+ ++search_count;
+ break;
+ case AF_INET6:
+ search[search_count].host = "localhost";
+ search[search_count].family = AF_INET6;
+ ++search_count;
+ break;
+ case AF_UNSPEC:
+ search[search_count].host = "localhost";
+ search[search_count].family = AF_INET6;
+ ++search_count;
+ search[search_count].host = "localhost";
+ search[search_count].family = AF_INET;
+ ++search_count;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else
+ {
+ // Host is specified.
+ switch (hints->ai_family)
+ {
+ case AF_INET:
+ search[search_count].host = host;
+ search[search_count].family = AF_INET;
+ ++search_count;
+ break;
+ case AF_INET6:
+ search[search_count].host = host;
+ search[search_count].family = AF_INET6;
+ ++search_count;
+ break;
+ case AF_UNSPEC:
+ search[search_count].host = host;
+ search[search_count].family = AF_INET6;
+ ++search_count;
+ search[search_count].host = host;
+ search[search_count].family = AF_INET;
+ ++search_count;
+ break;
+ default:
+ break;
+ }
+ }
+ return search_count;
+}
+
+template <typename T>
+inline T* gai_alloc(std::size_t size = sizeof(T))
+{
+ using namespace std;
+ T* p = static_cast<T*>(::operator new(size, std::nothrow));
+ if (p)
+ memset(p, 0, size);
+ return p;
+}
+
+inline void gai_free(void* p)
+{
+ ::operator delete(p);
+}
+
+inline void gai_strcpy(char* target, const char* source, std::size_t max_size)
+{
+ using namespace std;
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
+ strcpy_s(target, max_size, source);
+#else
+ *target = 0;
+ strncat(target, source, max_size);
+#endif
+}
+
+enum { gai_clone_flag = 1 << 30 };
+
+inline int gai_aistruct(addrinfo_type*** next, const addrinfo_type* hints,
+ const void* addr, int family)
+{
+ using namespace std;
+
+ addrinfo_type* ai = gai_alloc<addrinfo_type>();
+ if (ai == 0)
+ return EAI_MEMORY;
+
+ ai->ai_next = 0;
+ **next = ai;
+ *next = &ai->ai_next;
+
+ ai->ai_canonname = 0;
+ ai->ai_socktype = hints->ai_socktype;
+ if (ai->ai_socktype == 0)
+ ai->ai_flags |= gai_clone_flag;
+ ai->ai_protocol = hints->ai_protocol;
+ ai->ai_family = family;
+
+ switch (ai->ai_family)
+ {
+ case AF_INET:
+ {
+ sockaddr_in4_type* sinptr = gai_alloc<sockaddr_in4_type>();
+ if (sinptr == 0)
+ return EAI_MEMORY;
+ sinptr->sin_family = AF_INET;
+ memcpy(&sinptr->sin_addr, addr, sizeof(in4_addr_type));
+ ai->ai_addr = reinterpret_cast<sockaddr*>(sinptr);
+ ai->ai_addrlen = sizeof(sockaddr_in4_type);
+ break;
+ }
+ case AF_INET6:
+ {
+ sockaddr_in6_type* sin6ptr = gai_alloc<sockaddr_in6_type>();
+ if (sin6ptr == 0)
+ return EAI_MEMORY;
+ sin6ptr->sin6_family = AF_INET6;
+ memcpy(&sin6ptr->sin6_addr, addr, sizeof(in6_addr_type));
+ ai->ai_addr = reinterpret_cast<sockaddr*>(sin6ptr);
+ ai->ai_addrlen = sizeof(sockaddr_in6_type);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+inline addrinfo_type* gai_clone(addrinfo_type* ai)
+{
+ using namespace std;
+
+ addrinfo_type* new_ai = gai_alloc<addrinfo_type>();
+ if (new_ai == 0)
+ return new_ai;
+
+ new_ai->ai_next = ai->ai_next;
+ ai->ai_next = new_ai;
+
+ new_ai->ai_flags = 0;
+ new_ai->ai_family = ai->ai_family;
+ new_ai->ai_socktype = ai->ai_socktype;
+ new_ai->ai_protocol = ai->ai_protocol;
+ new_ai->ai_canonname = 0;
+ new_ai->ai_addrlen = ai->ai_addrlen;
+ new_ai->ai_addr = gai_alloc<sockaddr>(ai->ai_addrlen);
+ memcpy(new_ai->ai_addr, ai->ai_addr, ai->ai_addrlen);
+
+ return new_ai;
+}
+
+inline int gai_port(addrinfo_type* aihead, int port, int socktype)
+{
+ int num_found = 0;
+
+ for (addrinfo_type* ai = aihead; ai; ai = ai->ai_next)
+ {
+ if (ai->ai_flags & gai_clone_flag)
+ {
+ if (ai->ai_socktype != 0)
+ {
+ ai = gai_clone(ai);
+ if (ai == 0)
+ return -1;
+ // ai now points to newly cloned entry.
+ }
+ }
+ else if (ai->ai_socktype != socktype)
+ {
+ // Ignore if mismatch on socket type.
+ continue;
+ }
+
+ ai->ai_socktype = socktype;
+
+ switch (ai->ai_family)
+ {
+ case AF_INET:
+ {
+ sockaddr_in4_type* sinptr =
+ reinterpret_cast<sockaddr_in4_type*>(ai->ai_addr);
+ sinptr->sin_port = port;
+ ++num_found;
+ break;
+ }
+ case AF_INET6:
+ {
+ sockaddr_in6_type* sin6ptr =
+ reinterpret_cast<sockaddr_in6_type*>(ai->ai_addr);
+ sin6ptr->sin6_port = port;
+ ++num_found;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ return num_found;
+}
+
+inline int gai_serv(addrinfo_type* aihead,
+ const addrinfo_type* hints, const char* serv)
+{
+ using namespace std;
+
+ int num_found = 0;
+
+ if (
+#if defined(AI_NUMERICSERV)
+ (hints->ai_flags & AI_NUMERICSERV) ||
+#endif
+ isdigit(serv[0]))
+ {
+ int port = htons(atoi(serv));
+ if (hints->ai_socktype)
+ {
+ // Caller specifies socket type.
+ int rc = gai_port(aihead, port, hints->ai_socktype);
+ if (rc < 0)
+ return EAI_MEMORY;
+ num_found += rc;
+ }
+ else
+ {
+ // Caller does not specify socket type.
+ int rc = gai_port(aihead, port, SOCK_STREAM);
+ if (rc < 0)
+ return EAI_MEMORY;
+ num_found += rc;
+ rc = gai_port(aihead, port, SOCK_DGRAM);
+ if (rc < 0)
+ return EAI_MEMORY;
+ num_found += rc;
+ }
+ }
+ else
+ {
+ // Try service name with TCP first, then UDP.
+ if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_STREAM)
+ {
+ servent* sptr = getservbyname(serv, "tcp");
+ if (sptr != 0)
+ {
+ int rc = gai_port(aihead, sptr->s_port, SOCK_STREAM);
+ if (rc < 0)
+ return EAI_MEMORY;
+ num_found += rc;
+ }
+ }
+ if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_DGRAM)
+ {
+ servent* sptr = getservbyname(serv, "udp");
+ if (sptr != 0)
+ {
+ int rc = gai_port(aihead, sptr->s_port, SOCK_DGRAM);
+ if (rc < 0)
+ return EAI_MEMORY;
+ num_found += rc;
+ }
+ }
+ }
+
+ if (num_found == 0)
+ {
+ if (hints->ai_socktype == 0)
+ {
+ // All calls to getservbyname() failed.
+ return EAI_NONAME;
+ }
+ else
+ {
+ // Service not supported for socket type.
+ return EAI_SERVICE;
+ }
+ }
+
+ return 0;
+}
+
+inline int gai_echeck(const char* host, const char* service,
+ int flags, int family, int socktype, int protocol)
+{
+ (void)(flags);
+ (void)(protocol);
+
+ // Host or service must be specified.
+ if (host == 0 || host[0] == '\0')
+ if (service == 0 || service[0] == '\0')
+ return EAI_NONAME;
+
+ // Check combination of family and socket type.
+ switch (family)
+ {
+ case AF_UNSPEC:
+ break;
+ case AF_INET:
+ case AF_INET6:
+ if (socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM)
+ return EAI_SOCKTYPE;
+ break;
+ default:
+ return EAI_FAMILY;
+ }
+
+ return 0;
+}
+
+inline void freeaddrinfo_emulation(addrinfo_type* aihead)
+{
+ addrinfo_type* ai = aihead;
+ while (ai)
+ {
+ gai_free(ai->ai_addr);
+ gai_free(ai->ai_canonname);
+ addrinfo_type* ainext = ai->ai_next;
+ gai_free(ai);
+ ai = ainext;
+ }
+}
+
+inline int getaddrinfo_emulation(const char* host, const char* service,
+ const addrinfo_type* hintsp, addrinfo_type** result)
+{
+ // Set up linked list of addrinfo structures.
+ addrinfo_type* aihead = 0;
+ addrinfo_type** ainext = &aihead;
+ char* canon = 0;
+
+ // Supply default hints if not specified by caller.
+ addrinfo_type hints = addrinfo_type();
+ hints.ai_family = AF_UNSPEC;
+ if (hintsp)
+ hints = *hintsp;
+
+ // If the resolution is not specifically for AF_INET6, remove the AI_V4MAPPED
+ // and AI_ALL flags.
+#if defined(AI_V4MAPPED)
+ if (hints.ai_family != AF_INET6)
+ hints.ai_flags &= ~AI_V4MAPPED;
+#endif
+#if defined(AI_ALL)
+ if (hints.ai_family != AF_INET6)
+ hints.ai_flags &= ~AI_ALL;
+#endif
+
+ // Basic error checking.
+ int rc = gai_echeck(host, service, hints.ai_flags, hints.ai_family,
+ hints.ai_socktype, hints.ai_protocol);
+ if (rc != 0)
+ {
+ freeaddrinfo_emulation(aihead);
+ return rc;
+ }
+
+ gai_search search[2];
+ int search_count = gai_nsearch(host, &hints, search);
+ for (gai_search* sptr = search; sptr < search + search_count; ++sptr)
+ {
+ // Check for IPv4 dotted decimal string.
+ in4_addr_type inaddr;
+ boost::system::error_code ec;
+ if (socket_ops::inet_pton(AF_INET, sptr->host, &inaddr, 0, ec) == 1)
+ {
+ if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET)
+ {
+ freeaddrinfo_emulation(aihead);
+ gai_free(canon);
+ return EAI_FAMILY;
+ }
+ if (sptr->family == AF_INET)
+ {
+ rc = gai_aistruct(&ainext, &hints, &inaddr, AF_INET);
+ if (rc != 0)
+ {
+ freeaddrinfo_emulation(aihead);
+ gai_free(canon);
+ return rc;
+ }
+ }
+ continue;
+ }
+
+ // Check for IPv6 hex string.
+ in6_addr_type in6addr;
+ if (socket_ops::inet_pton(AF_INET6, sptr->host, &in6addr, 0, ec) == 1)
+ {
+ if (hints.ai_family != AF_UNSPEC && hints.ai_family != AF_INET6)
+ {
+ freeaddrinfo_emulation(aihead);
+ gai_free(canon);
+ return EAI_FAMILY;
+ }
+ if (sptr->family == AF_INET6)
+ {
+ rc = gai_aistruct(&ainext, &hints, &in6addr, AF_INET6);
+ if (rc != 0)
+ {
+ freeaddrinfo_emulation(aihead);
+ gai_free(canon);
+ return rc;
+ }
+ }
+ continue;
+ }
+
+ // Look up hostname.
+ hostent hent;
+ char hbuf[8192] = "";
+ hostent* hptr = socket_ops::gethostbyname(sptr->host,
+ sptr->family, &hent, hbuf, sizeof(hbuf), hints.ai_flags, ec);
+ if (hptr == 0)
+ {
+ if (search_count == 2)
+ {
+ // Failure is OK if there are multiple searches.
+ continue;
+ }
+ freeaddrinfo_emulation(aihead);
+ gai_free(canon);
+ if (ec == boost::asio::error::host_not_found)
+ return EAI_NONAME;
+ if (ec == boost::asio::error::host_not_found_try_again)
+ return EAI_AGAIN;
+ if (ec == boost::asio::error::no_recovery)
+ return EAI_FAIL;
+ if (ec == boost::asio::error::no_data)
+ return EAI_NONAME;
+ return EAI_NONAME;
+ }
+
+ // Check for address family mismatch if one was specified.
+ if (hints.ai_family != AF_UNSPEC && hints.ai_family != hptr->h_addrtype)
+ {
+ freeaddrinfo_emulation(aihead);
+ gai_free(canon);
+ socket_ops::freehostent(hptr);
+ return EAI_FAMILY;
+ }
+
+ // Save canonical name first time.
+ if (host != 0 && host[0] != '\0' && hptr->h_name && hptr->h_name[0]
+ && (hints.ai_flags & AI_CANONNAME) && canon == 0)
+ {
+ std::size_t canon_len = strlen(hptr->h_name) + 1;
+ canon = gai_alloc<char>(canon_len);
+ if (canon == 0)
+ {
+ freeaddrinfo_emulation(aihead);
+ socket_ops::freehostent(hptr);
+ return EAI_MEMORY;
+ }
+ gai_strcpy(canon, hptr->h_name, canon_len);
+ }
+
+ // Create an addrinfo structure for each returned address.
+ for (char** ap = hptr->h_addr_list; *ap; ++ap)
+ {
+ rc = gai_aistruct(&ainext, &hints, *ap, hptr->h_addrtype);
+ if (rc != 0)
+ {
+ freeaddrinfo_emulation(aihead);
+ gai_free(canon);
+ socket_ops::freehostent(hptr);
+ return EAI_FAMILY;
+ }
+ }
+
+ socket_ops::freehostent(hptr);
+ }
+
+ // Check if we found anything.
+ if (aihead == 0)
+ {
+ gai_free(canon);
+ return EAI_NONAME;
+ }
+
+ // Return canonical name in first entry.
+ if (host != 0 && host[0] != '\0' && (hints.ai_flags & AI_CANONNAME))
+ {
+ if (canon)
+ {
+ aihead->ai_canonname = canon;
+ canon = 0;
+ }
+ else
+ {
+ std::size_t canonname_len = strlen(search[0].host) + 1;
+ aihead->ai_canonname = gai_alloc<char>(canonname_len);
+ if (aihead->ai_canonname == 0)
+ {
+ freeaddrinfo_emulation(aihead);
+ return EAI_MEMORY;
+ }
+ gai_strcpy(aihead->ai_canonname, search[0].host, canonname_len);
+ }
+ }
+ gai_free(canon);
+
+ // Process the service name.
+ if (service != 0 && service[0] != '\0')
+ {
+ rc = gai_serv(aihead, &hints, service);
+ if (rc != 0)
+ {
+ freeaddrinfo_emulation(aihead);
+ return rc;
+ }
+ }
+
+ // Return result to caller.
+ *result = aihead;
+ return 0;
+}
+
+inline boost::system::error_code getnameinfo_emulation(
+ const socket_addr_type* sa, std::size_t salen, char* host,
+ std::size_t hostlen, char* serv, std::size_t servlen, int flags,
+ boost::system::error_code& ec)
+{
+ using namespace std;
+
+ const char* addr;
+ size_t addr_len;
+ unsigned short port;
+ switch (sa->sa_family)
+ {
+ case AF_INET:
+ if (salen != sizeof(sockaddr_in4_type))
+ {
+ return ec = boost::asio::error::invalid_argument;
+ }
+ addr = reinterpret_cast<const char*>(
+ &reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_addr);
+ addr_len = sizeof(in4_addr_type);
+ port = reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_port;
+ break;
+ case AF_INET6:
+ if (salen != sizeof(sockaddr_in6_type))
+ {
+ return ec = boost::asio::error::invalid_argument;
+ }
+ addr = reinterpret_cast<const char*>(
+ &reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_addr);
+ addr_len = sizeof(in6_addr_type);
+ port = reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_port;
+ break;
+ default:
+ return ec = boost::asio::error::address_family_not_supported;
+ }
+
+ if (host && hostlen > 0)
+ {
+ if (flags & NI_NUMERICHOST)
+ {
+ if (socket_ops::inet_ntop(sa->sa_family, addr, host, hostlen, 0, ec) == 0)
+ {
+ return ec;
+ }
+ }
+ else
+ {
+ hostent hent;
+ char hbuf[8192] = "";
+ hostent* hptr = socket_ops::gethostbyaddr(addr,
+ static_cast<int>(addr_len), sa->sa_family,
+ &hent, hbuf, sizeof(hbuf), ec);
+ if (hptr && hptr->h_name && hptr->h_name[0] != '\0')
+ {
+ if (flags & NI_NOFQDN)
+ {
+ char* dot = strchr(hptr->h_name, '.');
+ if (dot)
+ {
+ *dot = 0;
+ }
+ }
+ gai_strcpy(host, hptr->h_name, hostlen);
+ socket_ops::freehostent(hptr);
+ }
+ else
+ {
+ socket_ops::freehostent(hptr);
+ if (flags & NI_NAMEREQD)
+ {
+ return ec = boost::asio::error::host_not_found;
+ }
+ if (socket_ops::inet_ntop(sa->sa_family,
+ addr, host, hostlen, 0, ec) == 0)
+ {
+ return ec;
+ }
+ }
+ }
+ }
+
+ if (serv && servlen > 0)
+ {
+ if (flags & NI_NUMERICSERV)
+ {
+ if (servlen < 6)
+ {
+ return ec = boost::asio::error::no_buffer_space;
+ }
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
+ sprintf_s(serv, servlen, "%u", ntohs(port));
+#else
+ sprintf(serv, "%u", ntohs(port));
+#endif
+ }
+ else
+ {
+#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
+ static ::pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+ ::pthread_mutex_lock(&mutex);
+#endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
+ servent* sptr = ::getservbyport(port, (flags & NI_DGRAM) ? "udp" : 0);
+ if (sptr && sptr->s_name && sptr->s_name[0] != '\0')
+ {
+ gai_strcpy(serv, sptr->s_name, servlen);
+ }
+ else
+ {
+ if (servlen < 6)
+ {
+ return ec = boost::asio::error::no_buffer_space;
+ }
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) && !defined(UNDER_CE)
+ sprintf_s(serv, servlen, "%u", ntohs(port));
+#else
+ sprintf(serv, "%u", ntohs(port));
+#endif
+ }
+#if defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
+ ::pthread_mutex_unlock(&mutex);
+#endif // defined(BOOST_HAS_THREADS) && defined(BOOST_HAS_PTHREADS)
+ }
+ }
+
+ clear_error(ec);
+ return ec;
+}
+
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ // || defined(__MACH__) && defined(__APPLE__)
+
+inline boost::system::error_code translate_addrinfo_error(int error)
+{
+ switch (error)
+ {
+ case 0:
+ return boost::system::error_code();
+ case EAI_AGAIN:
+ return boost::asio::error::host_not_found_try_again;
+ case EAI_BADFLAGS:
+ return boost::asio::error::invalid_argument;
+ case EAI_FAIL:
+ return boost::asio::error::no_recovery;
+ case EAI_FAMILY:
+ return boost::asio::error::address_family_not_supported;
+ case EAI_MEMORY:
+ return boost::asio::error::no_memory;
+ case EAI_NONAME:
+#if defined(EAI_ADDRFAMILY)
+ case EAI_ADDRFAMILY:
+#endif
+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
+ case EAI_NODATA:
+#endif
+ return boost::asio::error::host_not_found;
+ case EAI_SERVICE:
+ return boost::asio::error::service_not_found;
+ case EAI_SOCKTYPE:
+ return boost::asio::error::socket_type_not_supported;
+ default: // Possibly the non-portable EAI_SYSTEM.
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ return boost::system::error_code(
+ WSAGetLastError(), boost::asio::error::get_system_category());
+#else
+ return boost::system::error_code(
+ errno, boost::asio::error::get_system_category());
+#endif
+ }
+}
+
+inline boost::system::error_code getaddrinfo(const char* host,
+ const char* service, const addrinfo_type* hints, addrinfo_type** result,
+ boost::system::error_code& ec)
+{
+ clear_error(ec);
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
+ // Building for Windows XP, Windows Server 2003, or later.
+ int error = ::getaddrinfo(host, service, hints, result);
+ return ec = translate_addrinfo_error(error);
+# else
+ // Building for Windows 2000 or earlier.
+ typedef int (WSAAPI *gai_t)(const char*,
+ const char*, const addrinfo_type*, addrinfo_type**);
+ if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
+ {
+ if (gai_t gai = (gai_t)::GetProcAddress(winsock_module, "getaddrinfo"))
+ {
+ int error = gai(host, service, hints, result);
+ return ec = translate_addrinfo_error(error);
+ }
+ }
+ int error = getaddrinfo_emulation(host, service, hints, result);
+ return ec = translate_addrinfo_error(error);
+# endif
+#elif defined(__MACH__) && defined(__APPLE__)
+ int error = getaddrinfo_emulation(host, service, hints, result);
+ return ec = translate_addrinfo_error(error);
+#else
+ int error = ::getaddrinfo(host, service, hints, result);
+ return ec = translate_addrinfo_error(error);
+#endif
+}
+
+inline void freeaddrinfo(addrinfo_type* ai)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
+ // Building for Windows XP, Windows Server 2003, or later.
+ ::freeaddrinfo(ai);
+# else
+ // Building for Windows 2000 or earlier.
+ typedef int (WSAAPI *fai_t)(addrinfo_type*);
+ if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
+ {
+ if (fai_t fai = (fai_t)::GetProcAddress(winsock_module, "freeaddrinfo"))
+ {
+ fai(ai);
+ return;
+ }
+ }
+ freeaddrinfo_emulation(ai);
+# endif
+#elif defined(__MACH__) && defined(__APPLE__)
+ freeaddrinfo_emulation(ai);
+#else
+ ::freeaddrinfo(ai);
+#endif
+}
+
+inline boost::system::error_code getnameinfo(const socket_addr_type* addr,
+ std::size_t addrlen, char* host, std::size_t hostlen,
+ char* serv, std::size_t servlen, int flags, boost::system::error_code& ec)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) || defined(UNDER_CE)
+ // Building for Windows XP, Windows Server 2003, or later.
+ clear_error(ec);
+ int error = ::getnameinfo(addr, static_cast<socklen_t>(addrlen),
+ host, static_cast<DWORD>(hostlen),
+ serv, static_cast<DWORD>(servlen), flags);
+ return ec = translate_addrinfo_error(error);
+# else
+ // Building for Windows 2000 or earlier.
+ typedef int (WSAAPI *gni_t)(const socket_addr_type*,
+ int, char*, DWORD, char*, DWORD, int);
+ if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))
+ {
+ if (gni_t gni = (gni_t)::GetProcAddress(winsock_module, "getnameinfo"))
+ {
+ clear_error(ec);
+ int error = gni(addr, static_cast<int>(addrlen),
+ host, static_cast<DWORD>(hostlen),
+ serv, static_cast<DWORD>(servlen), flags);
+ return ec = translate_addrinfo_error(error);
+ }
+ }
+ clear_error(ec);
+ return getnameinfo_emulation(addr, addrlen,
+ host, hostlen, serv, servlen, flags, ec);
+# endif
+#elif defined(__MACH__) && defined(__APPLE__)
+ using namespace std; // For memcpy.
+ sockaddr_storage_type tmp_addr;
+ memcpy(&tmp_addr, addr, addrlen);
+ tmp_addr.ss_len = addrlen;
+ addr = reinterpret_cast<socket_addr_type*>(&tmp_addr);
+ clear_error(ec);
+ return getnameinfo_emulation(addr, addrlen,
+ host, hostlen, serv, servlen, flags, ec);
+#else
+ clear_error(ec);
+ int error = ::getnameinfo(addr, addrlen, host, hostlen, serv, servlen, flags);
+ return ec = translate_addrinfo_error(error);
+#endif
+}
+
+inline u_long_type network_to_host_long(u_long_type value)
+{
+ return ntohl(value);
+}
+
+inline u_long_type host_to_network_long(u_long_type value)
+{
+ return htonl(value);
+}
+
+inline u_short_type network_to_host_short(u_short_type value)
+{
+ return ntohs(value);
+}
+
+inline u_short_type host_to_network_short(u_short_type value)
+{
+ return htons(value);
+}
+
+} // namespace socket_ops
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SOCKET_OPS_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/socket_option.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/socket_option.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,311 @@
+//
+// socket_option.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_SOCKET_OPTION_HPP
+#define BOOST_ASIO_DETAIL_SOCKET_OPTION_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <stdexcept>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/socket_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+namespace socket_option {
+
+// Helper template for implementing boolean-based options.
+template <int Level, int Name>
+class boolean
+{
+public:
+ // Default constructor.
+ boolean()
+ : value_(0)
+ {
+ }
+
+ // Construct with a specific option value.
+ explicit boolean(bool v)
+ : value_(v ? 1 : 0)
+ {
+ }
+
+ // Set the current value of the boolean.
+ boolean& operator=(bool v)
+ {
+ value_ = v ? 1 : 0;
+ return *this;
+ }
+
+ // Get the current value of the boolean.
+ bool value() const
+ {
+ return !!value_;
+ }
+
+ // Convert to bool.
+ operator bool() const
+ {
+ return !!value_;
+ }
+
+ // Test for false.
+ bool operator!() const
+ {
+ return !value_;
+ }
+
+ // Get the level of the socket option.
+ template <typename Protocol>
+ int level(const Protocol&) const
+ {
+ return Level;
+ }
+
+ // Get the name of the socket option.
+ template <typename Protocol>
+ int name(const Protocol&) const
+ {
+ return Name;
+ }
+
+ // Get the address of the boolean data.
+ template <typename Protocol>
+ int* data(const Protocol&)
+ {
+ return &value_;
+ }
+
+ // Get the address of the boolean data.
+ template <typename Protocol>
+ const int* data(const Protocol&) const
+ {
+ return &value_;
+ }
+
+ // Get the size of the boolean data.
+ template <typename Protocol>
+ std::size_t size(const Protocol&) const
+ {
+ return sizeof(value_);
+ }
+
+ // Set the size of the boolean data.
+ template <typename Protocol>
+ void resize(const Protocol&, std::size_t s)
+ {
+ // On some platforms (e.g. Windows Vista), the getsockopt function will
+ // return the size of a boolean socket option as one byte, even though a
+ // four byte integer was passed in.
+ switch (s)
+ {
+ case sizeof(char):
+ value_ = *reinterpret_cast<char*>(&value_) ? 1 : 0;
+ break;
+ case sizeof(value_):
+ break;
+ default:
+ throw std::length_error("boolean socket option resize");
+ }
+ }
+
+private:
+ int value_;
+};
+
+// Helper template for implementing integer options.
+template <int Level, int Name>
+class integer
+{
+public:
+ // Default constructor.
+ integer()
+ : value_(0)
+ {
+ }
+
+ // Construct with a specific option value.
+ explicit integer(int v)
+ : value_(v)
+ {
+ }
+
+ // Set the value of the int option.
+ integer& operator=(int v)
+ {
+ value_ = v;
+ return *this;
+ }
+
+ // Get the current value of the int option.
+ int value() const
+ {
+ return value_;
+ }
+
+ // Get the level of the socket option.
+ template <typename Protocol>
+ int level(const Protocol&) const
+ {
+ return Level;
+ }
+
+ // Get the name of the socket option.
+ template <typename Protocol>
+ int name(const Protocol&) const
+ {
+ return Name;
+ }
+
+ // Get the address of the int data.
+ template <typename Protocol>
+ int* data(const Protocol&)
+ {
+ return &value_;
+ }
+
+ // Get the address of the int data.
+ template <typename Protocol>
+ const int* data(const Protocol&) const
+ {
+ return &value_;
+ }
+
+ // Get the size of the int data.
+ template <typename Protocol>
+ std::size_t size(const Protocol&) const
+ {
+ return sizeof(value_);
+ }
+
+ // Set the size of the int data.
+ template <typename Protocol>
+ void resize(const Protocol&, std::size_t s)
+ {
+ if (s != sizeof(value_))
+ throw std::length_error("integer socket option resize");
+ }
+
+private:
+ int value_;
+};
+
+// Helper template for implementing linger options.
+template <int Level, int Name>
+class linger
+{
+public:
+ // Default constructor.
+ linger()
+ {
+ value_.l_onoff = 0;
+ value_.l_linger = 0;
+ }
+
+ // Construct with specific option values.
+ linger(bool e, int t)
+ {
+ enabled(e);
+ timeout(t);
+ }
+
+ // Set the value for whether linger is enabled.
+ void enabled(bool value)
+ {
+ value_.l_onoff = value ? 1 : 0;
+ }
+
+ // Get the value for whether linger is enabled.
+ bool enabled() const
+ {
+ return value_.l_onoff != 0;
+ }
+
+ // Set the value for the linger timeout.
+ void timeout(int value)
+ {
+#if defined(WIN32)
+ value_.l_linger = static_cast<u_short>(value);
+#else
+ value_.l_linger = value;
+#endif
+ }
+
+ // Get the value for the linger timeout.
+ int timeout() const
+ {
+ return static_cast<int>(value_.l_linger);
+ }
+
+ // Get the level of the socket option.
+ template <typename Protocol>
+ int level(const Protocol&) const
+ {
+ return Level;
+ }
+
+ // Get the name of the socket option.
+ template <typename Protocol>
+ int name(const Protocol&) const
+ {
+ return Name;
+ }
+
+ // Get the address of the linger data.
+ template <typename Protocol>
+ ::linger* data(const Protocol&)
+ {
+ return &value_;
+ }
+
+ // Get the address of the linger data.
+ template <typename Protocol>
+ const ::linger* data(const Protocol&) const
+ {
+ return &value_;
+ }
+
+ // Get the size of the linger data.
+ template <typename Protocol>
+ std::size_t size(const Protocol&) const
+ {
+ return sizeof(value_);
+ }
+
+ // Set the size of the int data.
+ template <typename Protocol>
+ void resize(const Protocol&, std::size_t s)
+ {
+ if (s != sizeof(value_))
+ throw std::length_error("linger socket option resize");
+ }
+
+private:
+ ::linger value_;
+};
+
+} // namespace socket_option
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SOCKET_OPTION_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/socket_select_interrupter.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/socket_select_interrupter.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,189 @@
+//
+// socket_select_interrupter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP
+#define BOOST_ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstdlib>
+#include <boost/throw_exception.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/socket_holder.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class socket_select_interrupter
+{
+public:
+ // Constructor.
+ socket_select_interrupter()
+ {
+ boost::system::error_code ec;
+ socket_holder acceptor(socket_ops::socket(
+ AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));
+ if (acceptor.get() == invalid_socket)
+ {
+ boost::system::system_error e(ec, "socket_select_interrupter");
+ boost::throw_exception(e);
+ }
+
+ int opt = 1;
+ socket_ops::setsockopt(acceptor.get(),
+ SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt), ec);
+
+ using namespace std; // For memset.
+ sockaddr_in4_type addr;
+ std::size_t addr_len = sizeof(addr);
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = inet_addr("127.0.0.1");
+ addr.sin_port = 0;
+ if (socket_ops::bind(acceptor.get(), (const socket_addr_type*)&addr,
+ addr_len, ec) == socket_error_retval)
+ {
+ boost::system::system_error e(ec, "socket_select_interrupter");
+ boost::throw_exception(e);
+ }
+
+ if (socket_ops::getsockname(acceptor.get(), (socket_addr_type*)&addr,
+ &addr_len, ec) == socket_error_retval)
+ {
+ boost::system::system_error e(ec, "socket_select_interrupter");
+ boost::throw_exception(e);
+ }
+
+ if (socket_ops::listen(acceptor.get(),
+ SOMAXCONN, ec) == socket_error_retval)
+ {
+ boost::system::system_error e(ec, "socket_select_interrupter");
+ boost::throw_exception(e);
+ }
+
+ socket_holder client(socket_ops::socket(
+ AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));
+ if (client.get() == invalid_socket)
+ {
+ boost::system::system_error e(ec, "socket_select_interrupter");
+ boost::throw_exception(e);
+ }
+
+ if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr,
+ addr_len, ec) == socket_error_retval)
+ {
+ boost::system::system_error e(ec, "socket_select_interrupter");
+ boost::throw_exception(e);
+ }
+
+ socket_holder server(socket_ops::accept(acceptor.get(), 0, 0, ec));
+ if (server.get() == invalid_socket)
+ {
+ boost::system::system_error e(ec, "socket_select_interrupter");
+ boost::throw_exception(e);
+ }
+
+ ioctl_arg_type non_blocking = 1;
+ if (socket_ops::ioctl(client.get(), FIONBIO, &non_blocking, ec))
+ {
+ boost::system::system_error e(ec, "socket_select_interrupter");
+ boost::throw_exception(e);
+ }
+
+ opt = 1;
+ socket_ops::setsockopt(client.get(),
+ IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
+
+ non_blocking = 1;
+ if (socket_ops::ioctl(server.get(), FIONBIO, &non_blocking, ec))
+ {
+ boost::system::system_error e(ec, "socket_select_interrupter");
+ boost::throw_exception(e);
+ }
+
+ opt = 1;
+ socket_ops::setsockopt(server.get(),
+ IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);
+
+ read_descriptor_ = server.release();
+ write_descriptor_ = client.release();
+ }
+
+ // Destructor.
+ ~socket_select_interrupter()
+ {
+ boost::system::error_code ec;
+ if (read_descriptor_ != invalid_socket)
+ socket_ops::close(read_descriptor_, ec);
+ if (write_descriptor_ != invalid_socket)
+ socket_ops::close(write_descriptor_, ec);
+ }
+
+ // Interrupt the select call.
+ void interrupt()
+ {
+ char byte = 0;
+ socket_ops::buf b;
+ socket_ops::init_buf(b, &byte, 1);
+ boost::system::error_code ec;
+ socket_ops::send(write_descriptor_, &b, 1, 0, ec);
+ }
+
+ // Reset the select interrupt. Returns true if the call was interrupted.
+ bool reset()
+ {
+ char data[1024];
+ socket_ops::buf b;
+ socket_ops::init_buf(b, data, sizeof(data));
+ boost::system::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;
+ }
+
+ // Get the read descriptor to be passed to select.
+ socket_type read_descriptor() const
+ {
+ return read_descriptor_;
+ }
+
+private:
+ // The read end of a connection used to interrupt the select call. This file
+ // descriptor is passed to select such that when it is time to stop, a single
+ // byte will be written on the other end of the connection and this
+ // descriptor will become readable.
+ socket_type read_descriptor_;
+
+ // The write end of a connection used to interrupt the select call. A single
+ // byte may be written to this to wake up the select which is waiting for the
+ // other end to become readable.
+ socket_type write_descriptor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/socket_types.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/socket_types.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,203 @@
+//
+// socket_types.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_SOCKET_TYPES_HPP
+#define BOOST_ASIO_DETAIL_SOCKET_TYPES_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# if defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)
+# error WinSock.h has already been included
+# endif // defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)
+# if !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
+# if defined(_MSC_VER) || defined(__BORLANDC__)
+# pragma message("Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately")
+# pragma message("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 Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target)
+# endif // defined(_MSC_VER) || defined(__BORLANDC__)
+# define _WIN32_WINNT 0x0501
+# endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
+# if defined(_MSC_VER)
+# if defined(_WIN32) && !defined(WIN32)
+# if !defined(_WINSOCK2API_)
+# define WIN32 // Needed for correct types in winsock2.h
+# else // !defined(_WINSOCK2API_)
+# error Please define the macro WIN32 in your compiler options
+# endif // !defined(_WINSOCK2API_)
+# endif // defined(_WIN32) && !defined(WIN32)
+# endif // defined(_MSC_VER)
+# if defined(__BORLANDC__)
+# include <stdlib.h> // Needed for __errno
+# if defined(__WIN32__) && !defined(WIN32)
+# if !defined(_WINSOCK2API_)
+# define WIN32 // Needed for correct types in winsock2.h
+# else // !defined(_WINSOCK2API_)
+# error Please define the macro WIN32 in your compiler options
+# endif // !defined(_WINSOCK2API_)
+# endif // defined(__WIN32__) && !defined(WIN32)
+# if !defined(_WSPIAPI_H_)
+# define _WSPIAPI_H_
+# define BOOST_ASIO_WSPIAPI_H_DEFINED
+# endif // !defined(_WSPIAPI_H_)
+# endif // defined(__BORLANDC__)
+# if !defined(BOOST_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(BOOST_ASIO_NO_WIN32_LEAN_AND_MEAN)
+# 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)
+# if !defined(NOMINMAX)
+# define NOMINMAX 1
+# endif // !defined(NOMINMAX)
+# endif // defined(__CYGWIN__)
+# include <winsock2.h>
+# include <ws2tcpip.h>
+# include <mswsock.h>
+# if defined(BOOST_ASIO_WSPIAPI_H_DEFINED)
+# undef _WSPIAPI_H_
+# undef BOOST_ASIO_WSPIAPI_H_DEFINED
+# endif // defined(BOOST_ASIO_WSPIAPI_H_DEFINED)
+# if !defined(BOOST_ASIO_NO_DEFAULT_LINKED_LIBS)
+# if defined(UNDER_CE)
+# pragma comment(lib, "ws2.lib")
+# elif defined(_MSC_VER) || defined(__BORLANDC__)
+# pragma comment(lib, "ws2_32.lib")
+# pragma comment(lib, "mswsock.lib")
+# endif // defined(_MSC_VER) || defined(__BORLANDC__)
+# endif // !defined(BOOST_ASIO_NO_DEFAULT_LINKED_LIBS)
+# include <boost/asio/detail/old_win_sdk_compat.hpp>
+#else
+# include <sys/ioctl.h>
+# include <sys/poll.h>
+# include <sys/types.h>
+# if defined(__hpux) && !defined(__HP_aCC)
+# include <sys/time.h>
+# else
+# include <sys/select.h>
+# endif
+# include <sys/socket.h>
+# include <sys/uio.h>
+# include <sys/un.h>
+# include <netinet/in.h>
+# include <netinet/tcp.h>
+# include <arpa/inet.h>
+# include <netdb.h>
+# include <net/if.h>
+# include <limits.h>
+# if defined(__sun)
+# include <sys/filio.h>
+# include <sys/sockio.h>
+# endif
+#endif
+#include <boost/asio/detail/pop_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+typedef SOCKET socket_type;
+const SOCKET invalid_socket = INVALID_SOCKET;
+const int socket_error_retval = SOCKET_ERROR;
+const int max_addr_v4_str_len = 256;
+const int max_addr_v6_str_len = 256;
+typedef sockaddr socket_addr_type;
+typedef in_addr in4_addr_type;
+typedef ip_mreq in4_mreq_type;
+typedef sockaddr_in sockaddr_in4_type;
+# if defined(BOOST_ASIO_HAS_OLD_WIN_SDK)
+typedef in6_addr_emulation in6_addr_type;
+typedef ipv6_mreq_emulation in6_mreq_type;
+typedef sockaddr_in6_emulation sockaddr_in6_type;
+typedef sockaddr_storage_emulation sockaddr_storage_type;
+typedef addrinfo_emulation addrinfo_type;
+# else
+typedef in6_addr in6_addr_type;
+typedef ipv6_mreq in6_mreq_type;
+typedef sockaddr_in6 sockaddr_in6_type;
+typedef sockaddr_storage sockaddr_storage_type;
+typedef addrinfo addrinfo_type;
+# endif
+typedef unsigned long ioctl_arg_type;
+typedef u_long u_long_type;
+typedef u_short u_short_type;
+const int shutdown_receive = SD_RECEIVE;
+const int shutdown_send = SD_SEND;
+const int shutdown_both = SD_BOTH;
+const int message_peek = MSG_PEEK;
+const int message_out_of_band = MSG_OOB;
+const int message_do_not_route = MSG_DONTROUTE;
+# if defined (_WIN32_WINNT)
+const int max_iov_len = 64;
+# else
+const int max_iov_len = 16;
+# endif
+#else
+typedef int socket_type;
+const int invalid_socket = -1;
+const int socket_error_retval = -1;
+const int max_addr_v4_str_len = INET_ADDRSTRLEN;
+const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE;
+typedef sockaddr socket_addr_type;
+typedef in_addr in4_addr_type;
+# if defined(__hpux)
+// HP-UX doesn't provide ip_mreq when _XOPEN_SOURCE_EXTENDED is defined.
+struct in4_mreq_type
+{
+ struct in_addr imr_multiaddr;
+ struct in_addr imr_interface;
+};
+# else
+typedef ip_mreq in4_mreq_type;
+# endif
+typedef sockaddr_in sockaddr_in4_type;
+typedef in6_addr in6_addr_type;
+typedef ipv6_mreq in6_mreq_type;
+typedef sockaddr_in6 sockaddr_in6_type;
+typedef sockaddr_storage sockaddr_storage_type;
+typedef sockaddr_un sockaddr_un_type;
+typedef addrinfo addrinfo_type;
+typedef int ioctl_arg_type;
+typedef uint32_t u_long_type;
+typedef uint16_t u_short_type;
+const int shutdown_receive = SHUT_RD;
+const int shutdown_send = SHUT_WR;
+const int shutdown_both = SHUT_RDWR;
+const int message_peek = MSG_PEEK;
+const int message_out_of_band = MSG_OOB;
+const int message_do_not_route = MSG_DONTROUTE;
+const int max_iov_len = IOV_MAX;
+#endif
+const int custom_socket_option_level = 0xA5100000;
+const int enable_connection_aborted_option = 1;
+const int always_fail_option = 2;
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_SOCKET_TYPES_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/strand_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/strand_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,532 @@
+//
+// strand_service.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_STRAND_SERVICE_HPP
+#define BOOST_ASIO_DETAIL_STRAND_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/aligned_storage.hpp>
+#include <boost/assert.hpp>
+#include <boost/detail/atomic_count.hpp>
+#include <boost/intrusive_ptr.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/call_stack.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/service_base.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// Default service implementation for a strand.
+class strand_service
+ : public boost::asio::detail::service_base<strand_service>
+{
+public:
+ class handler_base;
+ class invoke_current_handler;
+ class post_next_waiter_on_exit;
+
+ // The underlying implementation of a strand.
+ class strand_impl
+ {
+#if defined (__BORLANDC__)
+ public:
+#else
+ private:
+#endif
+ void add_ref()
+ {
+ ++ref_count_;
+ }
+
+ void release()
+ {
+ if (--ref_count_ == 0)
+ delete this;
+ }
+
+ private:
+ // Only this service will have access to the internal values.
+ friend class strand_service;
+ friend class post_next_waiter_on_exit;
+ friend class invoke_current_handler;
+
+ strand_impl(strand_service& owner)
+ : owner_(owner),
+ current_handler_(0),
+ first_waiter_(0),
+ last_waiter_(0),
+ ref_count_(0)
+ {
+ // Insert implementation into linked list of all implementations.
+ boost::asio::detail::mutex::scoped_lock lock(owner_.mutex_);
+ next_ = owner_.impl_list_;
+ prev_ = 0;
+ if (owner_.impl_list_)
+ owner_.impl_list_->prev_ = this;
+ owner_.impl_list_ = this;
+ }
+
+ ~strand_impl()
+ {
+ // Remove implementation from linked list of all implementations.
+ boost::asio::detail::mutex::scoped_lock lock(owner_.mutex_);
+ if (owner_.impl_list_ == this)
+ owner_.impl_list_ = next_;
+ if (prev_)
+ prev_->next_ = next_;
+ if (next_)
+ next_->prev_= prev_;
+ next_ = 0;
+ prev_ = 0;
+ lock.unlock();
+
+ if (current_handler_)
+ {
+ current_handler_->destroy();
+ }
+
+ while (first_waiter_)
+ {
+ handler_base* next = first_waiter_->next_;
+ first_waiter_->destroy();
+ first_waiter_ = next;
+ }
+ }
+
+ // Mutex to protect access to internal data.
+ boost::asio::detail::mutex mutex_;
+
+ // The service that owns this implementation.
+ strand_service& owner_;
+
+ // The handler that is ready to execute. If this pointer is non-null then it
+ // indicates that a handler holds the lock.
+ handler_base* current_handler_;
+
+ // The start of the list of waiting handlers for the strand.
+ handler_base* first_waiter_;
+
+ // The end of the list of waiting handlers for the strand.
+ handler_base* last_waiter_;
+
+ // Storage for posted handlers.
+ typedef boost::aligned_storage<128> handler_storage_type;
+#if defined(__BORLANDC__)
+ boost::aligned_storage<128> handler_storage_;
+#else
+ handler_storage_type handler_storage_;
+#endif
+
+ // Pointers to adjacent socket implementations in linked list.
+ strand_impl* next_;
+ strand_impl* prev_;
+
+ // The reference count on the strand implementation.
+ boost::detail::atomic_count ref_count_;
+
+#if !defined(__BORLANDC__)
+ friend void intrusive_ptr_add_ref(strand_impl* p)
+ {
+ p->add_ref();
+ }
+
+ friend void intrusive_ptr_release(strand_impl* p)
+ {
+ p->release();
+ }
+#endif
+ };
+
+ friend class strand_impl;
+
+ typedef boost::intrusive_ptr<strand_impl> implementation_type;
+
+ // Base class for all handler types.
+ class handler_base
+ {
+ public:
+ typedef void (*invoke_func_type)(handler_base*,
+ strand_service&, implementation_type&);
+ typedef void (*destroy_func_type)(handler_base*);
+
+ handler_base(invoke_func_type invoke_func, destroy_func_type destroy_func)
+ : next_(0),
+ invoke_func_(invoke_func),
+ destroy_func_(destroy_func)
+ {
+ }
+
+ void invoke(strand_service& service_impl, implementation_type& impl)
+ {
+ invoke_func_(this, service_impl, impl);
+ }
+
+ void destroy()
+ {
+ destroy_func_(this);
+ }
+
+ protected:
+ ~handler_base()
+ {
+ }
+
+ private:
+ friend class strand_service;
+ friend class strand_impl;
+ friend class post_next_waiter_on_exit;
+ handler_base* next_;
+ invoke_func_type invoke_func_;
+ destroy_func_type destroy_func_;
+ };
+
+ // Helper class to allow handlers to be dispatched.
+ class invoke_current_handler
+ {
+ public:
+ invoke_current_handler(strand_service& service_impl,
+ const implementation_type& impl)
+ : service_impl_(service_impl),
+ impl_(impl)
+ {
+ }
+
+ void operator()()
+ {
+ impl_->current_handler_->invoke(service_impl_, impl_);
+ }
+
+ friend void* asio_handler_allocate(std::size_t size,
+ invoke_current_handler* this_handler)
+ {
+ return this_handler->do_handler_allocate(size);
+ }
+
+ friend void asio_handler_deallocate(void*, std::size_t,
+ invoke_current_handler*)
+ {
+ }
+
+ void* do_handler_allocate(std::size_t size)
+ {
+#if defined(__BORLANDC__)
+ BOOST_ASSERT(size <= boost::aligned_storage<128>::size);
+#else
+ BOOST_ASSERT(size <= strand_impl::handler_storage_type::size);
+#endif
+ (void)size;
+ return impl_->handler_storage_.address();
+ }
+
+ // The asio_handler_invoke hook is not defined here since the default one
+ // provides the correct behaviour, and including it here breaks MSVC 7.1
+ // in some situations.
+
+ private:
+ strand_service& service_impl_;
+ implementation_type impl_;
+ };
+
+ // Helper class to automatically enqueue next waiter on block exit.
+ class post_next_waiter_on_exit
+ {
+ public:
+ post_next_waiter_on_exit(strand_service& service_impl,
+ implementation_type& impl)
+ : service_impl_(service_impl),
+ impl_(impl),
+ cancelled_(false)
+ {
+ }
+
+ ~post_next_waiter_on_exit()
+ {
+ if (!cancelled_)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(impl_->mutex_);
+ impl_->current_handler_ = impl_->first_waiter_;
+ if (impl_->current_handler_)
+ {
+ impl_->first_waiter_ = impl_->first_waiter_->next_;
+ if (impl_->first_waiter_ == 0)
+ impl_->last_waiter_ = 0;
+ lock.unlock();
+ service_impl_.get_io_service().post(
+ invoke_current_handler(service_impl_, impl_));
+ }
+ }
+ }
+
+ void cancel()
+ {
+ cancelled_ = true;
+ }
+
+ private:
+ strand_service& service_impl_;
+ implementation_type& impl_;
+ bool cancelled_;
+ };
+
+ // Class template for a waiter.
+ template <typename Handler>
+ class handler_wrapper
+ : public handler_base
+ {
+ public:
+ handler_wrapper(Handler handler)
+ : handler_base(&handler_wrapper<Handler>::do_invoke,
+ &handler_wrapper<Handler>::do_destroy),
+ handler_(handler)
+ {
+ }
+
+ static void do_invoke(handler_base* base,
+ strand_service& service_impl, implementation_type& impl)
+ {
+ // Take ownership of the handler object.
+ typedef handler_wrapper<Handler> this_type;
+ this_type* h(static_cast<this_type*>(base));
+ typedef handler_alloc_traits<Handler, this_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(h->handler_, h);
+
+ post_next_waiter_on_exit p1(service_impl, impl);
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made.
+ Handler handler(h->handler_);
+
+ // A handler object must still be valid when the next waiter is posted
+ // since destroying the last handler might cause the strand object to be
+ // destroyed. Therefore we create a second post_next_waiter_on_exit object
+ // that will be destroyed before the handler object.
+ p1.cancel();
+ post_next_waiter_on_exit p2(service_impl, impl);
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+
+ // Indicate that this strand is executing on the current thread.
+ call_stack<strand_impl>::context ctx(impl.get());
+
+ // Make the upcall.
+ boost_asio_handler_invoke_helpers::invoke(handler, &handler);
+ }
+
+ static void do_destroy(handler_base* base)
+ {
+ // Take ownership of the handler object.
+ typedef handler_wrapper<Handler> this_type;
+ this_type* h(static_cast<this_type*>(base));
+ typedef handler_alloc_traits<Handler, this_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(h->handler_, h);
+
+ // 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_);
+ (void)handler;
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+ }
+
+ private:
+ Handler handler_;
+ };
+
+ // Construct a new strand service for the specified io_service.
+ explicit strand_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<strand_service>(io_service),
+ mutex_(),
+ impl_list_(0)
+ {
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ // Construct a list of all handlers to be destroyed.
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ strand_impl* impl = impl_list_;
+ handler_base* first_handler = 0;
+ while (impl)
+ {
+ if (impl->current_handler_)
+ {
+ impl->current_handler_->next_ = first_handler;
+ first_handler = impl->current_handler_;
+ impl->current_handler_ = 0;
+ }
+ if (impl->first_waiter_)
+ {
+ impl->last_waiter_->next_ = first_handler;
+ first_handler = impl->first_waiter_;
+ impl->first_waiter_ = 0;
+ impl->last_waiter_ = 0;
+ }
+ impl = impl->next_;
+ }
+
+ // Destroy all handlers without holding the lock.
+ lock.unlock();
+ while (first_handler)
+ {
+ handler_base* next = first_handler->next_;
+ first_handler->destroy();
+ first_handler = next;
+ }
+ }
+
+ // Construct a new strand implementation.
+ void construct(implementation_type& impl)
+ {
+ impl = implementation_type(new strand_impl(*this));
+ }
+
+ // Destroy a strand implementation.
+ void destroy(implementation_type& impl)
+ {
+ implementation_type().swap(impl);
+ }
+
+ // Request the io_service to invoke the given handler.
+ template <typename Handler>
+ void dispatch(implementation_type& impl, Handler handler)
+ {
+ if (call_stack<strand_impl>::contains(impl.get()))
+ {
+ boost_asio_handler_invoke_helpers::invoke(handler, &handler);
+ }
+ else
+ {
+ // Allocate and construct an object to wrap the handler.
+ typedef handler_wrapper<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);
+
+ boost::asio::detail::mutex::scoped_lock lock(impl->mutex_);
+
+ if (impl->current_handler_ == 0)
+ {
+ // This handler now has the lock, so can be dispatched immediately.
+ impl->current_handler_ = ptr.release();
+ lock.unlock();
+ this->get_io_service().dispatch(invoke_current_handler(*this, impl));
+ }
+ else
+ {
+ // Another handler already holds the lock, so this handler must join
+ // the list of waiters. The handler will be posted automatically when
+ // its turn comes.
+ if (impl->last_waiter_)
+ {
+ impl->last_waiter_->next_ = ptr.get();
+ impl->last_waiter_ = impl->last_waiter_->next_;
+ }
+ else
+ {
+ impl->first_waiter_ = ptr.get();
+ impl->last_waiter_ = ptr.get();
+ }
+ ptr.release();
+ }
+ }
+ }
+
+ // Request the io_service to invoke the given handler and return immediately.
+ template <typename Handler>
+ void post(implementation_type& impl, Handler handler)
+ {
+ // Allocate and construct an object to wrap the handler.
+ typedef handler_wrapper<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);
+
+ boost::asio::detail::mutex::scoped_lock lock(impl->mutex_);
+
+ if (impl->current_handler_ == 0)
+ {
+ // This handler now has the lock, so can be dispatched immediately.
+ impl->current_handler_ = ptr.release();
+ lock.unlock();
+ this->get_io_service().post(invoke_current_handler(*this, impl));
+ }
+ else
+ {
+ // Another handler already holds the lock, so this handler must join the
+ // list of waiters. The handler will be posted automatically when its turn
+ // comes.
+ if (impl->last_waiter_)
+ {
+ impl->last_waiter_->next_ = ptr.get();
+ impl->last_waiter_ = impl->last_waiter_->next_;
+ }
+ else
+ {
+ impl->first_waiter_ = ptr.get();
+ impl->last_waiter_ = ptr.get();
+ }
+ ptr.release();
+ }
+ }
+
+private:
+ // Mutex to protect access to the linked list of implementations.
+ boost::asio::detail::mutex mutex_;
+
+ // The head of a linked list of all implementations.
+ strand_impl* impl_list_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#if defined(__BORLANDC__)
+
+namespace boost {
+
+inline void intrusive_ptr_add_ref(
+ boost::asio::detail::strand_service::strand_impl* p)
+{
+ p->add_ref();
+}
+
+inline void intrusive_ptr_release(
+ boost::asio::detail::strand_service::strand_impl* p)
+{
+ p->release();
+}
+
+} // namespace boost
+
+#endif // defined(__BORLANDC__)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_STRAND_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/task_io_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/task_io_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,427 @@
+//
+// task_io_service.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_TASK_IO_SERVICE_HPP
+#define BOOST_ASIO_DETAIL_TASK_IO_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#if defined(BOOST_ASIO_ENABLE_TWO_LOCK_QUEUE)
+#include <boost/asio/detail/task_io_service_2lock.hpp>
+#else // defined(BOOST_ASIO_ENABLE_TWO_LOCK_QUEUE)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/call_stack.hpp>
+#include <boost/asio/detail/event.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/handler_queue.hpp>
+#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/task_io_service_fwd.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Task>
+class task_io_service
+ : public boost::asio::detail::service_base<task_io_service<Task> >
+{
+public:
+ // Constructor.
+ task_io_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<task_io_service<Task> >(io_service),
+ mutex_(),
+ task_(use_service<Task>(io_service)),
+ task_interrupted_(true),
+ outstanding_work_(0),
+ stopped_(false),
+ shutdown_(false),
+ first_idle_thread_(0)
+ {
+ handler_queue_.push(&task_handler_);
+ }
+
+ void init(size_t /*concurrency_hint*/)
+ {
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ shutdown_ = true;
+ lock.unlock();
+
+ // Destroy handler objects.
+ while (!handler_queue_.empty())
+ {
+ handler_queue::handler* h = handler_queue_.front();
+ handler_queue_.pop();
+ if (h != &task_handler_)
+ h->destroy();
+ }
+
+ // Reset handler queue to initial state.
+ handler_queue_.push(&task_handler_);
+ }
+
+ // Run the event loop until interrupted or no more work.
+ size_t run(boost::system::error_code& ec)
+ {
+ typename call_stack<task_io_service>::context ctx(this);
+
+ idle_thread_info this_idle_thread;
+ this_idle_thread.next = 0;
+
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ size_t n = 0;
+ while (do_one(lock, &this_idle_thread, ec))
+ if (n != (std::numeric_limits<size_t>::max)())
+ ++n;
+ return n;
+ }
+
+ // Run until interrupted or one operation is performed.
+ size_t run_one(boost::system::error_code& ec)
+ {
+ typename call_stack<task_io_service>::context ctx(this);
+
+ idle_thread_info this_idle_thread;
+ this_idle_thread.next = 0;
+
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ return do_one(lock, &this_idle_thread, ec);
+ }
+
+ // Poll for operations without blocking.
+ size_t poll(boost::system::error_code& ec)
+ {
+ typename call_stack<task_io_service>::context ctx(this);
+
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ size_t n = 0;
+ while (do_one(lock, 0, ec))
+ if (n != (std::numeric_limits<size_t>::max)())
+ ++n;
+ return n;
+ }
+
+ // Poll for one operation without blocking.
+ size_t poll_one(boost::system::error_code& ec)
+ {
+ typename call_stack<task_io_service>::context ctx(this);
+
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ return do_one(lock, 0, ec);
+ }
+
+ // Interrupt the event processing loop.
+ void stop()
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ stop_all_threads(lock);
+ }
+
+ // Reset in preparation for a subsequent run invocation.
+ void reset()
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ stopped_ = false;
+ }
+
+ // Notify that some work has started.
+ void work_started()
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ ++outstanding_work_;
+ }
+
+ // Notify that some work has finished.
+ void work_finished()
+ {
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ if (--outstanding_work_ == 0)
+ stop_all_threads(lock);
+ }
+
+ // Request invocation of the given handler.
+ template <typename Handler>
+ void dispatch(Handler handler)
+ {
+ if (call_stack<task_io_service>::contains(this))
+ boost_asio_handler_invoke_helpers::invoke(handler, &handler);
+ else
+ post(handler);
+ }
+
+ // Request invocation of the given handler and return immediately.
+ template <typename Handler>
+ void post(Handler handler)
+ {
+ // Allocate and construct an operation to wrap the handler.
+ handler_queue::scoped_ptr ptr(handler_queue::wrap(handler));
+
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ // If the service has been shut down we silently discard the handler.
+ if (shutdown_)
+ return;
+
+ // Add the handler to the end of the queue.
+ handler_queue_.push(ptr.get());
+ ptr.release();
+
+ // An undelivered handler is treated as unfinished work.
+ ++outstanding_work_;
+
+ // Wake up a thread to execute the handler.
+ if (!interrupt_one_idle_thread(lock))
+ {
+ if (!task_interrupted_)
+ {
+ task_interrupted_ = true;
+ task_.interrupt();
+ }
+ }
+ }
+
+private:
+ struct idle_thread_info;
+
+ size_t do_one(boost::asio::detail::mutex::scoped_lock& lock,
+ idle_thread_info* this_idle_thread, boost::system::error_code& ec)
+ {
+ if (outstanding_work_ == 0 && !stopped_)
+ {
+ stop_all_threads(lock);
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ bool polling = !this_idle_thread;
+ bool task_has_run = false;
+ while (!stopped_)
+ {
+ if (!handler_queue_.empty())
+ {
+ // Prepare to execute first handler from queue.
+ handler_queue::handler* h = handler_queue_.front();
+ handler_queue_.pop();
+
+ if (h == &task_handler_)
+ {
+ bool more_handlers = (!handler_queue_.empty());
+ 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;
+ handler_queue_.push(&task_handler_);
+ ec = boost::system::error_code();
+ return 0;
+ }
+ task_has_run = true;
+
+ lock.unlock();
+ task_cleanup c(lock, *this);
+
+ // Run the task. May throw an exception. Only block if the handler
+ // queue is empty and we have an idle_thread_info object, otherwise
+ // we want to return as soon as possible.
+ task_.run(!more_handlers && !polling);
+ }
+ else
+ {
+ lock.unlock();
+ handler_cleanup c(lock, *this);
+
+ // Invoke the handler. May throw an exception.
+ h->invoke(); // invoke() deletes the handler object
+
+ ec = boost::system::error_code();
+ 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
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+ }
+
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ // Stop the task and all idle threads.
+ void stop_all_threads(
+ boost::asio::detail::mutex::scoped_lock& lock)
+ {
+ stopped_ = true;
+ interrupt_all_idle_threads(lock);
+ if (!task_interrupted_)
+ {
+ task_interrupted_ = true;
+ task_.interrupt();
+ }
+ }
+
+ // Interrupt a single idle thread. Returns true if a thread was interrupted,
+ // false if no running thread could be found to interrupt.
+ bool interrupt_one_idle_thread(
+ boost::asio::detail::mutex::scoped_lock& lock)
+ {
+ if (first_idle_thread_)
+ {
+ idle_thread_info* idle_thread = first_idle_thread_;
+ first_idle_thread_ = idle_thread->next;
+ idle_thread->next = 0;
+ idle_thread->wakeup_event.signal(lock);
+ return true;
+ }
+ return false;
+ }
+
+ // Interrupt all idle threads.
+ void interrupt_all_idle_threads(
+ boost::asio::detail::mutex::scoped_lock& lock)
+ {
+ 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);
+ }
+ }
+
+ // Helper class to perform task-related operations on block exit.
+ class task_cleanup;
+ friend class task_cleanup;
+ class task_cleanup
+ {
+ public:
+ task_cleanup(boost::asio::detail::mutex::scoped_lock& lock,
+ task_io_service& task_io_svc)
+ : lock_(lock),
+ task_io_service_(task_io_svc)
+ {
+ }
+
+ ~task_cleanup()
+ {
+ // Reinsert the task at the end of the handler queue.
+ lock_.lock();
+ task_io_service_.task_interrupted_ = true;
+ task_io_service_.handler_queue_.push(&task_io_service_.task_handler_);
+ }
+
+ private:
+ boost::asio::detail::mutex::scoped_lock& lock_;
+ task_io_service& task_io_service_;
+ };
+
+ // Helper class to perform handler-related operations on block exit.
+ class handler_cleanup;
+ friend class handler_cleanup;
+ class handler_cleanup
+ {
+ public:
+ handler_cleanup(boost::asio::detail::mutex::scoped_lock& lock,
+ task_io_service& task_io_svc)
+ : lock_(lock),
+ task_io_service_(task_io_svc)
+ {
+ }
+
+ ~handler_cleanup()
+ {
+ lock_.lock();
+ if (--task_io_service_.outstanding_work_ == 0)
+ task_io_service_.stop_all_threads(lock_);
+ }
+
+ private:
+ boost::asio::detail::mutex::scoped_lock& lock_;
+ task_io_service& task_io_service_;
+ };
+
+ // Mutex to protect access to internal data.
+ boost::asio::detail::mutex mutex_;
+
+ // The task to be run by this service.
+ Task& task_;
+
+ // Handler object to represent the position of the task in the queue.
+ class task_handler
+ : public handler_queue::handler
+ {
+ public:
+ task_handler()
+ : handler_queue::handler(0, 0)
+ {
+ }
+ } task_handler_;
+
+ // Whether the task has been interrupted.
+ bool task_interrupted_;
+
+ // The count of unfinished work.
+ int outstanding_work_;
+
+ // The queue of handlers that are ready to be delivered.
+ handler_queue handler_queue_;
+
+ // Flag to indicate that the dispatcher has been stopped.
+ bool stopped_;
+
+ // Flag to indicate that the dispatcher has been shut down.
+ bool shutdown_;
+
+ // Structure containing information about an idle thread.
+ struct idle_thread_info
+ {
+ event wakeup_event;
+ idle_thread_info* next;
+ };
+
+ // The number of threads that are currently idle.
+ idle_thread_info* first_idle_thread_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/system/error_code.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // defined(BOOST_ASIO_ENABLE_TWO_LOCK_QUEUE)
+
+#endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/task_io_service_2lock.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/task_io_service_2lock.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,464 @@
+//
+// task_io_service_2lock.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP
+#define BOOST_ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/call_stack.hpp>
+#include <boost/asio/detail/event.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/indirect_handler_queue.hpp>
+#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/task_io_service_fwd.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/detail/atomic_count.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// An alternative task_io_service implementation based on a two-lock queue.
+
+template <typename Task>
+class task_io_service
+ : public boost::asio::detail::service_base<task_io_service<Task> >
+{
+public:
+ typedef indirect_handler_queue handler_queue;
+
+ // Constructor.
+ task_io_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<task_io_service<Task> >(io_service),
+ front_mutex_(),
+ back_mutex_(),
+ task_(use_service<Task>(io_service)),
+ outstanding_work_(0),
+ front_stopped_(false),
+ back_stopped_(false),
+ back_shutdown_(false),
+ back_first_idle_thread_(0),
+ back_task_thread_(0)
+ {
+ handler_queue_.push(&task_handler_);
+ }
+
+ void init(size_t /*concurrency_hint*/)
+ {
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_);
+ back_shutdown_ = true;
+ back_lock.unlock();
+
+ // Destroy handler objects.
+ while (handler_queue::handler* h = handler_queue_.pop())
+ if (h != &task_handler_)
+ h->destroy();
+
+ // Reset handler queue to initial state.
+ handler_queue_.push(&task_handler_);
+ }
+
+ // Run the event loop until interrupted or no more work.
+ size_t run(boost::system::error_code& ec)
+ {
+ if (outstanding_work_ == 0)
+ {
+ stop();
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ typename call_stack<task_io_service>::context ctx(this);
+
+ idle_thread_info this_idle_thread;
+ this_idle_thread.next = 0;
+
+ size_t n = 0;
+ while (do_one(&this_idle_thread, ec))
+ if (n != (std::numeric_limits<size_t>::max)())
+ ++n;
+ return n;
+ }
+
+ // Run until interrupted or one operation is performed.
+ size_t run_one(boost::system::error_code& ec)
+ {
+ if (outstanding_work_ == 0)
+ {
+ stop();
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ typename call_stack<task_io_service>::context ctx(this);
+
+ idle_thread_info this_idle_thread;
+ this_idle_thread.next = 0;
+
+ return do_one(&this_idle_thread, ec);
+ }
+
+ // Poll for operations without blocking.
+ size_t poll(boost::system::error_code& ec)
+ {
+ if (outstanding_work_ == 0)
+ {
+ stop();
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ typename call_stack<task_io_service>::context ctx(this);
+
+ size_t n = 0;
+ while (do_one(0, ec))
+ if (n != (std::numeric_limits<size_t>::max)())
+ ++n;
+ return n;
+ }
+
+ // Poll for one operation without blocking.
+ size_t poll_one(boost::system::error_code& ec)
+ {
+ if (outstanding_work_ == 0)
+ {
+ stop();
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ typename call_stack<task_io_service>::context ctx(this);
+
+ return do_one(0, ec);
+ }
+
+ // Interrupt the event processing loop.
+ void stop()
+ {
+ boost::asio::detail::mutex::scoped_lock front_lock(front_mutex_);
+ front_stopped_ = true;
+ front_lock.unlock();
+
+ boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_);
+ back_stopped_ = true;
+ interrupt_all_idle_threads(back_lock);
+ }
+
+ // Reset in preparation for a subsequent run invocation.
+ void reset()
+ {
+ boost::asio::detail::mutex::scoped_lock front_lock(front_mutex_);
+ front_stopped_ = false;
+ front_lock.unlock();
+
+ boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_);
+ back_stopped_ = false;
+ }
+
+ // Notify that some work has started.
+ void work_started()
+ {
+ ++outstanding_work_;
+ }
+
+ // Notify that some work has finished.
+ void work_finished()
+ {
+ if (--outstanding_work_ == 0)
+ stop();
+ }
+
+ // Request invocation of the given handler.
+ template <typename Handler>
+ void dispatch(Handler handler)
+ {
+ if (call_stack<task_io_service>::contains(this))
+ boost_asio_handler_invoke_helpers::invoke(handler, &handler);
+ else
+ post(handler);
+ }
+
+ // Request invocation of the given handler and return immediately.
+ template <typename Handler>
+ void post(Handler handler)
+ {
+ // Allocate and construct an operation to wrap the handler.
+ handler_queue::scoped_ptr ptr(handler_queue::wrap(handler));
+
+ boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_);
+
+ // If the service has been shut down we silently discard the handler.
+ if (back_shutdown_)
+ return;
+
+ // Add the handler to the end of the queue.
+ handler_queue_.push(ptr.get());
+ ptr.release();
+
+ // An undelivered handler is treated as unfinished work.
+ ++outstanding_work_;
+
+ // Wake up a thread to execute the handler.
+ interrupt_one_idle_thread(back_lock);
+ }
+
+private:
+ struct idle_thread_info;
+
+ size_t do_one(idle_thread_info* this_idle_thread,
+ boost::system::error_code& ec)
+ {
+ bool task_has_run = false;
+ for (;;)
+ {
+ // The front lock must be held before we can pop items from the queue.
+ boost::asio::detail::mutex::scoped_lock front_lock(front_mutex_);
+ if (front_stopped_)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ if (handler_queue::handler* h = handler_queue_.pop())
+ {
+ if (h == &task_handler_)
+ {
+ bool more_handlers = handler_queue_.poppable();
+ unsigned long front_version = handler_queue_.front_version();
+ front_lock.unlock();
+
+ // The task is always added to the back of the queue when we exit
+ // this block.
+ task_cleanup c(*this);
+
+ // If we're polling and the task has already run then we're done.
+ bool polling = !this_idle_thread;
+ if (task_has_run && polling)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ // If we're considering going idle we need to check whether the queue
+ // is still empty. If it is, add the thread to the list of idle
+ // threads.
+ if (!more_handlers && !polling)
+ {
+ boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_);
+ if (back_stopped_)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+ else if (front_version == handler_queue_.back_version())
+ {
+ back_task_thread_ = this_idle_thread;
+ }
+ else
+ {
+ more_handlers = true;
+ }
+ }
+
+ // Run the task. May throw an exception. Only block if the handler
+ // queue is empty and we're not polling, otherwise we want to return
+ // as soon as possible.
+ task_has_run = true;
+ task_.run(!more_handlers && !polling);
+ }
+ else
+ {
+ front_lock.unlock();
+ handler_cleanup c(*this);
+
+ // Invoke the handler. May throw an exception.
+ h->invoke(); // invoke() deletes the handler object
+
+ ec = boost::system::error_code();
+ return 1;
+ }
+ }
+ else if (this_idle_thread)
+ {
+ unsigned long front_version = handler_queue_.front_version();
+ front_lock.unlock();
+
+ // If we're considering going idle we need to check whether the queue
+ // is still empty. If it is, add the thread to the list of idle
+ // threads.
+ boost::asio::detail::mutex::scoped_lock back_lock(back_mutex_);
+ if (back_stopped_)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+ else if (front_version == handler_queue_.back_version())
+ {
+ this_idle_thread->next = back_first_idle_thread_;
+ back_first_idle_thread_ = this_idle_thread;
+ this_idle_thread->wakeup_event.clear(back_lock);
+ this_idle_thread->wakeup_event.wait(back_lock);
+ }
+ }
+ else
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+ }
+ }
+
+ // Interrupt a single idle thread.
+ void interrupt_one_idle_thread(
+ boost::asio::detail::mutex::scoped_lock& back_lock)
+ {
+ if (back_first_idle_thread_)
+ {
+ idle_thread_info* idle_thread = back_first_idle_thread_;
+ back_first_idle_thread_ = idle_thread->next;
+ idle_thread->next = 0;
+ idle_thread->wakeup_event.signal(back_lock);
+ }
+ else if (back_task_thread_)
+ {
+ back_task_thread_ = 0;
+ task_.interrupt();
+ }
+ }
+
+ // Interrupt all idle threads.
+ void interrupt_all_idle_threads(
+ boost::asio::detail::mutex::scoped_lock& back_lock)
+ {
+ while (back_first_idle_thread_)
+ {
+ idle_thread_info* idle_thread = back_first_idle_thread_;
+ back_first_idle_thread_ = idle_thread->next;
+ idle_thread->next = 0;
+ idle_thread->wakeup_event.signal(back_lock);
+ }
+
+ if (back_task_thread_)
+ {
+ back_task_thread_ = 0;
+ task_.interrupt();
+ }
+ }
+
+ // Helper class to perform task-related operations on block exit.
+ class task_cleanup;
+ friend class task_cleanup;
+ class task_cleanup
+ {
+ public:
+ task_cleanup(task_io_service& task_io_svc)
+ : task_io_service_(task_io_svc)
+ {
+ }
+
+ ~task_cleanup()
+ {
+ // Reinsert the task at the end of the handler queue.
+ boost::asio::detail::mutex::scoped_lock back_lock(
+ task_io_service_.back_mutex_);
+ task_io_service_.back_task_thread_ = 0;
+ task_io_service_.handler_queue_.push(&task_io_service_.task_handler_);
+ }
+
+ private:
+ task_io_service& task_io_service_;
+ };
+
+ // Helper class to perform handler-related operations on block exit.
+ class handler_cleanup
+ {
+ public:
+ handler_cleanup(task_io_service& task_io_svc)
+ : task_io_service_(task_io_svc)
+ {
+ }
+
+ ~handler_cleanup()
+ {
+ task_io_service_.work_finished();
+ }
+
+ private:
+ task_io_service& task_io_service_;
+ };
+
+ // Mutexes to protect access to internal data.
+ boost::asio::detail::mutex front_mutex_;
+ boost::asio::detail::mutex back_mutex_;
+
+ // The task to be run by this service.
+ Task& task_;
+
+ // Handler object to represent the position of the task in the queue.
+ class task_handler
+ : public handler_queue::handler
+ {
+ public:
+ task_handler()
+ : handler_queue::handler(0, 0)
+ {
+ }
+ } task_handler_;
+
+ // The count of unfinished work.
+ boost::detail::atomic_count outstanding_work_;
+
+ // The queue of handlers that are ready to be delivered.
+ handler_queue handler_queue_;
+
+ // Flag to indicate that the dispatcher has been stopped.
+ bool front_stopped_;
+ bool back_stopped_;
+
+ // Flag to indicate that the dispatcher has been shut down.
+ bool back_shutdown_;
+
+ // Structure containing information about an idle thread.
+ struct idle_thread_info
+ {
+ event wakeup_event;
+ idle_thread_info* next;
+ };
+
+ // The number of threads that are currently idle.
+ idle_thread_info* back_first_idle_thread_;
+
+ // The thread that is currently blocked on the task.
+ idle_thread_info* back_task_thread_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_2LOCK_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/task_io_service_fwd.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/task_io_service_fwd.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,33 @@
+//
+// task_io_service_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP
+#define BOOST_ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Task>
+class task_io_service;
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/thread.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/thread.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,60 @@
+//
+// thread.hpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_THREAD_HPP
+#define BOOST_ASIO_DETAIL_THREAD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if !defined(BOOST_HAS_THREADS)
+# include <boost/asio/detail/null_thread.hpp>
+#elif defined(BOOST_WINDOWS)
+# if defined(UNDER_CE)
+# include <boost/asio/detail/wince_thread.hpp>
+# else
+# include <boost/asio/detail/win_thread.hpp>
+# endif
+#elif defined(BOOST_HAS_PTHREADS)
+# include <boost/asio/detail/posix_thread.hpp>
+#else
+# error Only Windows and POSIX are supported!
+#endif
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+#if !defined(BOOST_HAS_THREADS)
+typedef null_thread thread;
+#elif defined(BOOST_WINDOWS)
+# if defined(UNDER_CE)
+typedef wince_thread thread;
+# else
+typedef win_thread thread;
+# endif
+#elif defined(BOOST_HAS_PTHREADS)
+typedef posix_thread thread;
+#endif
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_THREAD_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/throw_error.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/throw_error.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,46 @@
+//
+// throw_error.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_THROW_ERROR_HPP
+#define BOOST_ASIO_DETAIL_THROW_ERROR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+inline void throw_error(const boost::system::error_code& err)
+{
+ if (err)
+ {
+ boost::system::system_error e(err);
+ boost::throw_exception(e);
+ }
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_THROW_ERROR_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/timer_queue.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/timer_queue.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,438 @@
+//
+// timer_queue.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_TIMER_QUEUE_HPP
+#define BOOST_ASIO_DETAIL_TIMER_QUEUE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <functional>
+#include <limits>
+#include <memory>
+#include <vector>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/hash_map.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/timer_queue_base.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Time_Traits>
+class timer_queue
+ : public timer_queue_base
+{
+public:
+ // The time type.
+ typedef typename Time_Traits::time_type time_type;
+
+ // The duration type.
+ typedef typename Time_Traits::duration_type duration_type;
+
+ // Constructor.
+ timer_queue()
+ : timers_(),
+ heap_(),
+ cancelled_timers_(0),
+ complete_timers_(0)
+ {
+ }
+
+ // Add a new timer to the queue. Returns true if this is the timer that is
+ // earliest in the queue, in which case the reactor's event demultiplexing
+ // function call may need to be interrupted and restarted.
+ template <typename Handler>
+ bool enqueue_timer(const time_type& time, Handler handler, void* token)
+ {
+ // Ensure that there is space for the timer in the heap. We reserve here so
+ // that the push_back below will not throw due to a reallocation failure.
+ heap_.reserve(heap_.size() + 1);
+
+ // Create a new timer object.
+ std::auto_ptr<timer<Handler> > new_timer(
+ new timer<Handler>(time, handler, token));
+
+ // Insert the new timer into the hash.
+ typedef typename hash_map<void*, timer_base*>::iterator iterator;
+ typedef typename hash_map<void*, timer_base*>::value_type value_type;
+ std::pair<iterator, bool> result =
+ timers_.insert(value_type(token, new_timer.get()));
+ if (!result.second)
+ {
+ result.first->second->prev_ = new_timer.get();
+ new_timer->next_ = result.first->second;
+ result.first->second = new_timer.get();
+ }
+
+ // Put the timer at the correct position in the heap.
+ new_timer->heap_index_ = heap_.size();
+ heap_.push_back(new_timer.get());
+ up_heap(heap_.size() - 1);
+ bool is_first = (heap_[0] == new_timer.get());
+
+ // Ownership of the timer is transferred to the timer queue.
+ new_timer.release();
+
+ return is_first;
+ }
+
+ // Whether there are no timers in the queue.
+ virtual bool empty() const
+ {
+ return heap_.empty();
+ }
+
+ // Get the time for the timer that is earliest in the queue.
+ virtual boost::posix_time::time_duration wait_duration() const
+ {
+ if (heap_.empty())
+ return boost::posix_time::pos_infin;
+ return Time_Traits::to_posix_duration(
+ Time_Traits::subtract(heap_[0]->time_, Time_Traits::now()));
+ }
+
+ // Dispatch the timers that are earlier than the specified time.
+ virtual void dispatch_timers()
+ {
+ const time_type now = Time_Traits::now();
+ while (!heap_.empty() && !Time_Traits::less_than(now, heap_[0]->time_))
+ {
+ timer_base* t = heap_[0];
+ remove_timer(t);
+ t->result_ = boost::system::error_code();
+ t->prev_ = 0;
+ t->next_ = complete_timers_;
+ complete_timers_ = t;
+ }
+ }
+
+ // Cancel the timers with the given token. Any timers pending for the token
+ // will be notified that they have been cancelled next time
+ // dispatch_cancellations is called. Returns the number of timers that were
+ // cancelled.
+ std::size_t cancel_timer(void* timer_token)
+ {
+ std::size_t num_cancelled = 0;
+ typedef typename hash_map<void*, timer_base*>::iterator iterator;
+ iterator it = timers_.find(timer_token);
+ if (it != timers_.end())
+ {
+ timer_base* t = it->second;
+ while (t)
+ {
+ timer_base* next = t->next_;
+ remove_timer(t);
+ t->prev_ = 0;
+ t->next_ = cancelled_timers_;
+ cancelled_timers_ = t;
+ t = next;
+ ++num_cancelled;
+ }
+ }
+ return num_cancelled;
+ }
+
+ // Dispatch any pending cancels for timers.
+ virtual void dispatch_cancellations()
+ {
+ while (cancelled_timers_)
+ {
+ timer_base* this_timer = cancelled_timers_;
+ this_timer->result_ = boost::asio::error::operation_aborted;
+ cancelled_timers_ = this_timer->next_;
+ this_timer->next_ = complete_timers_;
+ complete_timers_ = this_timer;
+ }
+ }
+
+ // Complete any timers that are waiting to be completed.
+ virtual void complete_timers()
+ {
+ while (complete_timers_)
+ {
+ timer_base* this_timer = complete_timers_;
+ complete_timers_ = this_timer->next_;
+ this_timer->next_ = 0;
+ this_timer->complete();
+ }
+ }
+
+ // Destroy all timers.
+ virtual void destroy_timers()
+ {
+ typename hash_map<void*, timer_base*>::iterator i = timers_.begin();
+ typename hash_map<void*, timer_base*>::iterator end = timers_.end();
+ while (i != end)
+ {
+ timer_base* t = i->second;
+ typename hash_map<void*, timer_base*>::iterator old_i = i++;
+ timers_.erase(old_i);
+ destroy_timer_list(t);
+ }
+ heap_.clear();
+ timers_.clear();
+ destroy_timer_list(cancelled_timers_);
+ destroy_timer_list(complete_timers_);
+ }
+
+private:
+ // Base class for timer operations. Function pointers are used instead of
+ // virtual functions to avoid the associated overhead.
+ class timer_base
+ {
+ public:
+ // Delete the timer and post the handler.
+ void complete()
+ {
+ complete_func_(this, result_);
+ }
+
+ // Delete the timer.
+ void destroy()
+ {
+ destroy_func_(this);
+ }
+
+ protected:
+ typedef void (*complete_func_type)(timer_base*,
+ const boost::system::error_code&);
+ typedef void (*destroy_func_type)(timer_base*);
+
+ // Constructor.
+ timer_base(complete_func_type complete_func, destroy_func_type destroy_func,
+ const time_type& time, void* token)
+ : complete_func_(complete_func),
+ destroy_func_(destroy_func),
+ time_(time),
+ token_(token),
+ next_(0),
+ prev_(0),
+ heap_index_(
+ std::numeric_limits<size_t>::max BOOST_PREVENT_MACRO_SUBSTITUTION())
+ {
+ }
+
+ // Prevent deletion through this type.
+ ~timer_base()
+ {
+ }
+
+ private:
+ friend class timer_queue<Time_Traits>;
+
+ // The function to be called to delete the timer and post the handler.
+ complete_func_type complete_func_;
+
+ // The function to be called to delete the timer.
+ destroy_func_type destroy_func_;
+
+ // The result of the timer operation.
+ boost::system::error_code result_;
+
+ // The time when the timer should fire.
+ time_type time_;
+
+ // The token associated with the timer.
+ void* token_;
+
+ // The next timer known to the queue.
+ timer_base* next_;
+
+ // The previous timer known to the queue.
+ timer_base* prev_;
+
+ // The index of the timer in the heap.
+ size_t heap_index_;
+ };
+
+ // Adaptor class template for using handlers in timers.
+ template <typename Handler>
+ class timer
+ : public timer_base
+ {
+ public:
+ // Constructor.
+ timer(const time_type& time, Handler handler, void* token)
+ : timer_base(&timer<Handler>::complete_handler,
+ &timer<Handler>::destroy_handler, time, token),
+ handler_(handler)
+ {
+ }
+
+ // Delete the timer and post the handler.
+ static void complete_handler(timer_base* base,
+ const boost::system::error_code& result)
+ {
+ // Take ownership of the timer object.
+ typedef timer<Handler> this_type;
+ this_type* this_timer(static_cast<this_type*>(base));
+ typedef handler_alloc_traits<Handler, this_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(this_timer->handler_, this_timer);
+
+ // Make a copy of the error_code and the handler so that the memory can
+ // be deallocated before the upcall is made.
+ boost::system::error_code ec(result);
+ Handler handler(this_timer->handler_);
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+
+ // Make the upcall.
+ handler(ec);
+ }
+
+ // Delete the timer.
+ static void destroy_handler(timer_base* base)
+ {
+ // Take ownership of the timer object.
+ typedef timer<Handler> this_type;
+ this_type* this_timer(static_cast<this_type*>(base));
+ typedef handler_alloc_traits<Handler, this_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(this_timer->handler_, this_timer);
+
+ // 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(this_timer->handler_);
+ (void)handler;
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+ }
+
+ private:
+ Handler handler_;
+ };
+
+ // Move the item at the given index up the heap to its correct position.
+ void up_heap(size_t index)
+ {
+ size_t parent = (index - 1) / 2;
+ while (index > 0
+ && Time_Traits::less_than(heap_[index]->time_, heap_[parent]->time_))
+ {
+ swap_heap(index, parent);
+ index = parent;
+ parent = (index - 1) / 2;
+ }
+ }
+
+ // Move the item at the given index down the heap to its correct position.
+ void down_heap(size_t index)
+ {
+ size_t child = index * 2 + 1;
+ while (child < heap_.size())
+ {
+ size_t min_child = (child + 1 == heap_.size()
+ || Time_Traits::less_than(
+ heap_[child]->time_, heap_[child + 1]->time_))
+ ? child : child + 1;
+ if (Time_Traits::less_than(heap_[index]->time_, heap_[min_child]->time_))
+ break;
+ swap_heap(index, min_child);
+ index = min_child;
+ child = index * 2 + 1;
+ }
+ }
+
+ // Swap two entries in the heap.
+ void swap_heap(size_t index1, size_t index2)
+ {
+ timer_base* tmp = heap_[index1];
+ heap_[index1] = heap_[index2];
+ heap_[index2] = tmp;
+ heap_[index1]->heap_index_ = index1;
+ heap_[index2]->heap_index_ = index2;
+ }
+
+ // Remove a timer from the heap and list of timers.
+ void remove_timer(timer_base* t)
+ {
+ // Remove the timer from the heap.
+ size_t index = t->heap_index_;
+ if (!heap_.empty() && index < heap_.size())
+ {
+ if (index == heap_.size() - 1)
+ {
+ heap_.pop_back();
+ }
+ else
+ {
+ swap_heap(index, heap_.size() - 1);
+ heap_.pop_back();
+ size_t parent = (index - 1) / 2;
+ if (index > 0 && Time_Traits::less_than(
+ heap_[index]->time_, heap_[parent]->time_))
+ up_heap(index);
+ else
+ down_heap(index);
+ }
+ }
+
+ // Remove the timer from the hash.
+ typedef typename hash_map<void*, timer_base*>::iterator iterator;
+ iterator it = timers_.find(t->token_);
+ if (it != timers_.end())
+ {
+ if (it->second == t)
+ it->second = t->next_;
+ if (t->prev_)
+ t->prev_->next_ = t->next_;
+ if (t->next_)
+ t->next_->prev_ = t->prev_;
+ if (it->second == 0)
+ timers_.erase(it);
+ }
+ }
+
+ // Destroy all timers in a linked list.
+ void destroy_timer_list(timer_base*& t)
+ {
+ while (t)
+ {
+ timer_base* next = t->next_;
+ t->next_ = 0;
+ t->destroy();
+ t = next;
+ }
+ }
+
+ // A hash of timer token to linked lists of timers.
+ hash_map<void*, timer_base*> timers_;
+
+ // The heap of timers, with the earliest timer at the front.
+ std::vector<timer_base*> heap_;
+
+ // The list of timers to be cancelled.
+ timer_base* cancelled_timers_;
+
+ // The list of timers waiting to be completed.
+ timer_base* complete_timers_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_TIMER_QUEUE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/timer_queue_base.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/timer_queue_base.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,64 @@
+//
+// timer_queue_base.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_TIMER_QUEUE_BASE_HPP
+#define BOOST_ASIO_DETAIL_TIMER_QUEUE_BASE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/socket_types.hpp> // Must come before posix_time.
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class timer_queue_base
+ : private noncopyable
+{
+public:
+ // Destructor.
+ virtual ~timer_queue_base() {}
+
+ // Whether there are no timers in the queue.
+ virtual bool empty() const = 0;
+
+ // Get the time to wait until the next timer.
+ virtual boost::posix_time::time_duration wait_duration() const = 0;
+
+ // Dispatch all ready timers.
+ virtual void dispatch_timers() = 0;
+
+ // Dispatch any pending cancels for timers.
+ virtual void dispatch_cancellations() = 0;
+
+ // Complete all timers that are waiting to be completed.
+ virtual void complete_timers() = 0;
+
+ // Destroy all timers.
+ virtual void destroy_timers() = 0;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_TIMER_QUEUE_BASE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/tss_ptr.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/tss_ptr.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,67 @@
+//
+// tss_ptr.hpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_TSS_PTR_HPP
+#define BOOST_ASIO_DETAIL_TSS_PTR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if !defined(BOOST_HAS_THREADS)
+# include <boost/asio/detail/null_tss_ptr.hpp>
+#elif defined(BOOST_WINDOWS)
+# include <boost/asio/detail/win_tss_ptr.hpp>
+#elif defined(BOOST_HAS_PTHREADS)
+# include <boost/asio/detail/posix_tss_ptr.hpp>
+#else
+# error Only Windows and POSIX are supported!
+#endif
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename T>
+class tss_ptr
+#if !defined(BOOST_HAS_THREADS)
+ : public null_tss_ptr<T>
+#elif defined(BOOST_WINDOWS)
+ : public win_tss_ptr<T>
+#elif defined(BOOST_HAS_PTHREADS)
+ : public posix_tss_ptr<T>
+#endif
+{
+public:
+ void operator=(T* value)
+ {
+#if !defined(BOOST_HAS_THREADS)
+ null_tss_ptr<T>::operator=(value);
+#elif defined(BOOST_WINDOWS)
+ win_tss_ptr<T>::operator=(value);
+#elif defined(BOOST_HAS_PTHREADS)
+ posix_tss_ptr<T>::operator=(value);
+#endif
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_TSS_PTR_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/win_event.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/win_event.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,105 @@
+//
+// win_event.hpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_WIN_EVENT_HPP
+#define BOOST_ASIO_DETAIL_WIN_EVENT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_WINDOWS)
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/assert.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class win_event
+ : private noncopyable
+{
+public:
+ // Constructor.
+ win_event()
+ : event_(::CreateEvent(0, true, false, 0))
+ {
+ if (!event_)
+ {
+ DWORD last_error = ::GetLastError();
+ boost::system::system_error e(
+ boost::system::error_code(last_error,
+ boost::asio::error::get_system_category()),
+ "event");
+ boost::throw_exception(e);
+ }
+ }
+
+ // Destructor.
+ ~win_event()
+ {
+ ::CloseHandle(event_);
+ }
+
+ // Signal the event.
+ template <typename Lock>
+ void signal(Lock& lock)
+ {
+ BOOST_ASSERT(lock.locked());
+ (void)lock;
+ ::SetEvent(event_);
+ }
+
+ // Reset the event.
+ template <typename Lock>
+ void clear(Lock& lock)
+ {
+ BOOST_ASSERT(lock.locked());
+ (void)lock;
+ ::ResetEvent(event_);
+ }
+
+ // Wait for the event to become signalled.
+ template <typename Lock>
+ void wait(Lock& lock)
+ {
+ BOOST_ASSERT(lock.locked());
+ lock.unlock();
+ ::WaitForSingleObject(event_, INFINITE);
+ lock.lock();
+ }
+
+private:
+ HANDLE event_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_WINDOWS)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_WIN_EVENT_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/win_fd_set_adapter.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/win_fd_set_adapter.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,90 @@
+//
+// win_fd_set_adapter.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP
+#define BOOST_ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/socket_types.hpp>
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// Adapts the FD_SET type to meet the Descriptor_Set concept's requirements.
+class win_fd_set_adapter
+{
+public:
+ enum { win_fd_set_size = 1024 };
+
+ win_fd_set_adapter()
+ : max_descriptor_(invalid_socket)
+ {
+ fd_set_.fd_count = 0;
+ }
+
+ bool set(socket_type descriptor)
+ {
+ for (u_int i = 0; i < fd_set_.fd_count; ++i)
+ if (fd_set_.fd_array[i] == descriptor)
+ return true;
+ if (fd_set_.fd_count < win_fd_set_size)
+ {
+ fd_set_.fd_array[fd_set_.fd_count++] = descriptor;
+ return true;
+ }
+ return false;
+ }
+
+ bool is_set(socket_type descriptor) const
+ {
+ return !!__WSAFDIsSet(descriptor,
+ const_cast<fd_set*>(reinterpret_cast<const fd_set*>(&fd_set_)));
+ }
+
+ operator fd_set*()
+ {
+ return reinterpret_cast<fd_set*>(&fd_set_);
+ }
+
+ socket_type max_descriptor() const
+ {
+ return max_descriptor_;
+ }
+
+private:
+ // This structure is defined to be compatible with the Windows API fd_set
+ // structure, but without being dependent on the value of FD_SETSIZE.
+ struct win_fd_set
+ {
+ u_int fd_count;
+ SOCKET fd_array[win_fd_set_size];
+ };
+
+ win_fd_set fd_set_;
+ socket_type max_descriptor_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/win_iocp_handle_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/win_iocp_handle_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,834 @@
+//
+// win_iocp_handle_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info_at_[hidden])
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP
+#define BOOST_ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/win_iocp_io_service_fwd.hpp>
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/win_iocp_io_service.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class win_iocp_handle_service
+ : public boost::asio::detail::service_base<win_iocp_handle_service>
+{
+public:
+ // Base class for all operations.
+ typedef win_iocp_io_service::operation operation;
+
+ // The native type of a stream handle.
+ typedef HANDLE native_type;
+
+ // The implementation type of the stream handle.
+ class implementation_type
+ {
+ public:
+ // Default constructor.
+ implementation_type()
+ : handle_(INVALID_HANDLE_VALUE),
+ safe_cancellation_thread_id_(0),
+ next_(0),
+ prev_(0)
+ {
+ }
+
+ private:
+ // Only this service will have access to the internal values.
+ friend class win_iocp_handle_service;
+
+ // The native stream handle representation.
+ native_type handle_;
+
+ // The ID of the thread from which it is safe to cancel asynchronous
+ // operations. 0 means no asynchronous operations have been started yet.
+ // ~0 means asynchronous operations have been started from more than one
+ // thread, and cancellation is not supported for the handle.
+ DWORD safe_cancellation_thread_id_;
+
+ // Pointers to adjacent handle implementations in linked list.
+ implementation_type* next_;
+ implementation_type* prev_;
+ };
+
+ win_iocp_handle_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<win_iocp_handle_service>(io_service),
+ iocp_service_(boost::asio::use_service<win_iocp_io_service>(io_service)),
+ mutex_(),
+ impl_list_(0)
+ {
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ // Close all implementations, causing all operations to complete.
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ implementation_type* impl = impl_list_;
+ while (impl)
+ {
+ close_for_destruction(*impl);
+ impl = impl->next_;
+ }
+ }
+
+ // Construct a new handle implementation.
+ void construct(implementation_type& impl)
+ {
+ impl.handle_ = INVALID_HANDLE_VALUE;
+ impl.safe_cancellation_thread_id_ = 0;
+
+ // Insert implementation into linked list of all implementations.
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ impl.next_ = impl_list_;
+ impl.prev_ = 0;
+ if (impl_list_)
+ impl_list_->prev_ = &impl;
+ impl_list_ = &impl;
+ }
+
+ // Destroy a handle implementation.
+ void destroy(implementation_type& impl)
+ {
+ close_for_destruction(impl);
+
+ // Remove implementation from linked list of all implementations.
+ boost::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;
+ }
+
+ // Assign a native handle to a handle implementation.
+ boost::system::error_code assign(implementation_type& impl,
+ const native_type& native_handle, boost::system::error_code& ec)
+ {
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ if (iocp_service_.register_handle(native_handle, ec))
+ return ec;
+
+ impl.handle_ = native_handle;
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Determine whether the handle is open.
+ bool is_open(const implementation_type& impl) const
+ {
+ return impl.handle_ != INVALID_HANDLE_VALUE;
+ }
+
+ // Destroy a handle implementation.
+ boost::system::error_code close(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ if (is_open(impl))
+ {
+ if (!::CloseHandle(impl.handle_))
+ {
+ DWORD last_error = ::GetLastError();
+ ec = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ impl.handle_ = INVALID_HANDLE_VALUE;
+ impl.safe_cancellation_thread_id_ = 0;
+ }
+
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Get the native handle representation.
+ native_type native(const implementation_type& impl) const
+ {
+ return impl.handle_;
+ }
+
+ // Cancel all operations associated with the handle.
+ boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::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 = boost::system::error_code();
+ }
+ else
+ {
+ ec = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+ }
+ }
+ else
+ {
+ ec = boost::system::error_code();
+ }
+ }
+ else if (impl.safe_cancellation_thread_id_ == 0)
+ {
+ // No operations have been started, so there's nothing to cancel.
+ ec = boost::system::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 = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+ }
+ else
+ {
+ ec = boost::system::error_code();
+ }
+ }
+ else
+ {
+ // Asynchronous operations have been started from more than one thread,
+ // so cancellation is not safe.
+ ec = boost::asio::error::operation_not_supported;
+ }
+
+ return ec;
+ }
+
+ class overlapped_wrapper
+ : public OVERLAPPED
+ {
+ public:
+ explicit overlapped_wrapper(boost::system::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 = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+ }
+ }
+
+ ~overlapped_wrapper()
+ {
+ if (hEvent)
+ {
+ ::CloseHandle(hEvent);
+ }
+ }
+ };
+
+ // Write the given data. Returns the number of bytes written.
+ template <typename ConstBufferSequence>
+ size_t write_some(implementation_type& impl,
+ const ConstBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return write_some_at(impl, 0, buffers, ec);
+ }
+
+ // Write the given data at the specified offset. Returns the number of bytes
+ // written.
+ template <typename ConstBufferSequence>
+ size_t write_some_at(implementation_type& impl, boost::uint64_t offset,
+ const ConstBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Find first buffer of non-zero length.
+ boost::asio::const_buffer buffer;
+ typename ConstBufferSequence::const_iterator iter = buffers.begin();
+ typename ConstBufferSequence::const_iterator end = buffers.end();
+ for (DWORD i = 0; iter != end; ++iter, ++i)
+ {
+ buffer = boost::asio::const_buffer(*iter);
+ if (boost::asio::buffer_size(buffer) != 0)
+ break;
+ }
+
+ // A request to write 0 bytes on a handle is a no-op.
+ if (boost::asio::buffer_size(buffer) == 0)
+ {
+ ec = boost::system::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_,
+ boost::asio::buffer_cast<LPCVOID>(buffer),
+ static_cast<DWORD>(boost::asio::buffer_size(buffer)), 0, &overlapped);
+ if (!ok)
+ {
+ DWORD last_error = ::GetLastError();
+ if (last_error != ERROR_IO_PENDING)
+ {
+ ec = boost::system::error_code(last_error,
+ boost::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 = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+ }
+
+ ec = boost::system::error_code();
+ return bytes_transferred;
+ }
+
+ template <typename ConstBufferSequence, typename Handler>
+ class write_operation
+ : public operation
+ {
+ public:
+ write_operation(win_iocp_io_service& io_service,
+ const ConstBufferSequence& buffers, Handler handler)
+ : operation(io_service,
+ &write_operation<ConstBufferSequence, Handler>::do_completion_impl,
+ &write_operation<ConstBufferSequence, Handler>::destroy_impl),
+ work_(io_service.get_io_service()),
+ buffers_(buffers),
+ handler_(handler)
+ {
+ }
+
+ private:
+ static void do_completion_impl(operation* op,
+ DWORD last_error, size_t bytes_transferred)
+ {
+ // Take ownership of the operation object.
+ typedef write_operation<ConstBufferSequence, Handler> op_type;
+ op_type* handler_op(static_cast<op_type*>(op));
+ typedef handler_alloc_traits<Handler, op_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ // Check whether buffers are still valid.
+ typename ConstBufferSequence::const_iterator iter
+ = handler_op->buffers_.begin();
+ typename ConstBufferSequence::const_iterator end
+ = handler_op->buffers_.end();
+ while (iter != end)
+ {
+ boost::asio::const_buffer buffer(*iter);
+ boost::asio::buffer_cast<const char*>(buffer);
+ ++iter;
+ }
+#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made.
+ Handler handler(handler_op->handler_);
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+
+ // Call the handler.
+ boost::system::error_code ec(last_error,
+ boost::asio::error::get_system_category());
+ boost_asio_handler_invoke_helpers::invoke(
+ bind_handler(handler, ec, bytes_transferred), &handler);
+ }
+
+ static void destroy_impl(operation* op)
+ {
+ // Take ownership of the operation object.
+ typedef write_operation<ConstBufferSequence, Handler> op_type;
+ op_type* handler_op(static_cast<op_type*>(op));
+ typedef handler_alloc_traits<Handler, op_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+
+ // 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(handler_op->handler_);
+ (void)handler;
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+ }
+
+ boost::asio::io_service::work work_;
+ ConstBufferSequence buffers_;
+ Handler handler_;
+ };
+
+ // Start an asynchronous write. The data being written must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_write_some(implementation_type& impl,
+ const ConstBufferSequence& buffers, Handler handler)
+ {
+ async_write_some_at(impl, 0, buffers, handler);
+ }
+
+ // Start an asynchronous write at a specified offset. The data being written
+ // must be valid for the lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_write_some_at(implementation_type& impl, boost::uint64_t offset,
+ const ConstBufferSequence& buffers, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ return;
+ }
+
+ // Update the ID of the thread from which cancellation is safe.
+ 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);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef write_operation<ConstBufferSequence, Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, buffers, handler);
+
+ // Find first buffer of non-zero length.
+ boost::asio::const_buffer buffer;
+ typename ConstBufferSequence::const_iterator iter = buffers.begin();
+ typename ConstBufferSequence::const_iterator end = buffers.end();
+ for (DWORD i = 0; iter != end; ++iter, ++i)
+ {
+ buffer = boost::asio::const_buffer(*iter);
+ if (boost::asio::buffer_size(buffer) != 0)
+ break;
+ }
+
+ // A request to write 0 bytes on a handle is a no-op.
+ if (boost::asio::buffer_size(buffer) == 0)
+ {
+ boost::asio::io_service::work work(this->get_io_service());
+ ptr.reset();
+ boost::system::error_code error;
+ iocp_service_.post(bind_handler(handler, error, 0));
+ return;
+ }
+
+ // Write the data.
+ DWORD bytes_transferred = 0;
+ ptr.get()->Offset = offset & 0xFFFFFFFF;
+ ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
+ BOOL ok = ::WriteFile(impl.handle_,
+ boost::asio::buffer_cast<LPCVOID>(buffer),
+ static_cast<DWORD>(boost::asio::buffer_size(buffer)),
+ &bytes_transferred, ptr.get());
+ DWORD last_error = ::GetLastError();
+
+ // Check if the operation completed immediately.
+ if (!ok && last_error != ERROR_IO_PENDING)
+ {
+ boost::asio::io_service::work work(this->get_io_service());
+ ptr.reset();
+ boost::system::error_code ec(last_error,
+ boost::asio::error::get_system_category());
+ iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
+ }
+ else
+ {
+ ptr.release();
+ }
+ }
+
+ // Read some data. Returns the number of bytes received.
+ template <typename MutableBufferSequence>
+ size_t read_some(implementation_type& impl,
+ const MutableBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return read_some_at(impl, 0, buffers, ec);
+ }
+
+ // Read some data at a specified offset. Returns the number of bytes received.
+ template <typename MutableBufferSequence>
+ size_t read_some_at(implementation_type& impl, boost::uint64_t offset,
+ const MutableBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Find first buffer of non-zero length.
+ boost::asio::mutable_buffer buffer;
+ typename MutableBufferSequence::const_iterator iter = buffers.begin();
+ typename MutableBufferSequence::const_iterator end = buffers.end();
+ for (DWORD i = 0; iter != end; ++iter, ++i)
+ {
+ buffer = boost::asio::mutable_buffer(*iter);
+ if (boost::asio::buffer_size(buffer) != 0)
+ break;
+ }
+
+ // A request to read 0 bytes on a stream handle is a no-op.
+ if (boost::asio::buffer_size(buffer) == 0)
+ {
+ ec = boost::system::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_,
+ boost::asio::buffer_cast<LPVOID>(buffer),
+ static_cast<DWORD>(boost::asio::buffer_size(buffer)), 0, &overlapped);
+ if (!ok)
+ {
+ DWORD last_error = ::GetLastError();
+ if (last_error != ERROR_IO_PENDING)
+ {
+ if (last_error == ERROR_HANDLE_EOF)
+ {
+ ec = boost::asio::error::eof;
+ }
+ else
+ {
+ ec = boost::system::error_code(last_error,
+ boost::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 = boost::asio::error::eof;
+ }
+ else
+ {
+ ec = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+ }
+ }
+
+ ec = boost::system::error_code();
+ return bytes_transferred;
+ }
+
+ template <typename MutableBufferSequence, typename Handler>
+ class read_operation
+ : public operation
+ {
+ public:
+ read_operation(win_iocp_io_service& io_service,
+ const MutableBufferSequence& buffers, Handler handler)
+ : operation(io_service,
+ &read_operation<
+ MutableBufferSequence, Handler>::do_completion_impl,
+ &read_operation<
+ MutableBufferSequence, Handler>::destroy_impl),
+ work_(io_service.get_io_service()),
+ buffers_(buffers),
+ handler_(handler)
+ {
+ }
+
+ private:
+ static void do_completion_impl(operation* op,
+ DWORD last_error, size_t bytes_transferred)
+ {
+ // Take ownership of the operation object.
+ typedef read_operation<MutableBufferSequence, Handler> op_type;
+ op_type* handler_op(static_cast<op_type*>(op));
+ typedef handler_alloc_traits<Handler, op_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ // Check whether buffers are still valid.
+ typename MutableBufferSequence::const_iterator iter
+ = handler_op->buffers_.begin();
+ typename MutableBufferSequence::const_iterator end
+ = handler_op->buffers_.end();
+ while (iter != end)
+ {
+ boost::asio::mutable_buffer buffer(*iter);
+ boost::asio::buffer_cast<char*>(buffer);
+ ++iter;
+ }
+#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+
+ // Check for the end-of-file condition.
+ boost::system::error_code ec(last_error,
+ boost::asio::error::get_system_category());
+ if (!ec && bytes_transferred == 0 || last_error == ERROR_HANDLE_EOF)
+ {
+ ec = boost::asio::error::eof;
+ }
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made.
+ Handler handler(handler_op->handler_);
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+
+ // Call the handler.
+ boost_asio_handler_invoke_helpers::invoke(
+ bind_handler(handler, ec, bytes_transferred), &handler);
+ }
+
+ static void destroy_impl(operation* op)
+ {
+ // Take ownership of the operation object.
+ typedef read_operation<MutableBufferSequence, Handler> op_type;
+ op_type* handler_op(static_cast<op_type*>(op));
+ typedef boost::asio::detail::handler_alloc_traits<
+ Handler, op_type> alloc_traits;
+ boost::asio::detail::handler_ptr<alloc_traits> ptr(
+ handler_op->handler_, handler_op);
+
+ // 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(handler_op->handler_);
+ (void)handler;
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+ }
+
+ boost::asio::io_service::work work_;
+ MutableBufferSequence buffers_;
+ Handler handler_;
+ };
+
+ // Start an asynchronous read. The buffer for the data being received must be
+ // valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_read_some(implementation_type& impl,
+ const MutableBufferSequence& buffers, Handler handler)
+ {
+ async_read_some_at(impl, 0, buffers, handler);
+ }
+
+ // Start an asynchronous read at a specified offset. The buffer for the data
+ // being received must be valid for the lifetime of the asynchronous
+ // operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_read_some_at(implementation_type& impl, boost::uint64_t offset,
+ const MutableBufferSequence& buffers, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ return;
+ }
+
+ // Update the ID of the thread from which cancellation is safe.
+ 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);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef read_operation<MutableBufferSequence, Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, buffers, handler);
+
+ // Find first buffer of non-zero length.
+ boost::asio::mutable_buffer buffer;
+ typename MutableBufferSequence::const_iterator iter = buffers.begin();
+ typename MutableBufferSequence::const_iterator end = buffers.end();
+ for (DWORD i = 0; iter != end; ++iter, ++i)
+ {
+ buffer = boost::asio::mutable_buffer(*iter);
+ if (boost::asio::buffer_size(buffer) != 0)
+ break;
+ }
+
+ // A request to receive 0 bytes on a stream handle is a no-op.
+ if (boost::asio::buffer_size(buffer) == 0)
+ {
+ boost::asio::io_service::work work(this->get_io_service());
+ ptr.reset();
+ boost::system::error_code error;
+ iocp_service_.post(bind_handler(handler, error, 0));
+ return;
+ }
+
+ // Read some data.
+ DWORD bytes_transferred = 0;
+ ptr.get()->Offset = offset & 0xFFFFFFFF;
+ ptr.get()->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
+ BOOL ok = ::ReadFile(impl.handle_,
+ boost::asio::buffer_cast<LPVOID>(buffer),
+ static_cast<DWORD>(boost::asio::buffer_size(buffer)),
+ &bytes_transferred, ptr.get());
+ DWORD last_error = ::GetLastError();
+ if (!ok && last_error != ERROR_IO_PENDING)
+ {
+ boost::asio::io_service::work work(this->get_io_service());
+ ptr.reset();
+ boost::system::error_code ec(last_error,
+ boost::asio::error::get_system_category());
+ iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
+ }
+ else
+ {
+ ptr.release();
+ }
+ }
+
+private:
+ // Prevent the use of the null_buffers type with this service.
+ size_t write_some(implementation_type& impl,
+ const null_buffers& buffers, boost::system::error_code& ec);
+ size_t write_some_at(implementation_type& impl, boost::uint64_t offset,
+ const null_buffers& buffers, boost::system::error_code& ec);
+ template <typename Handler>
+ void async_write_some(implementation_type& impl,
+ const null_buffers& buffers, Handler handler);
+ template <typename Handler>
+ void async_write_some_at(implementation_type& impl, boost::uint64_t offset,
+ const null_buffers& buffers, Handler handler);
+ size_t read_some(implementation_type& impl,
+ const null_buffers& buffers, boost::system::error_code& ec);
+ size_t read_some_at(implementation_type& impl, boost::uint64_t offset,
+ const null_buffers& buffers, boost::system::error_code& ec);
+ template <typename Handler>
+ void async_read_some(implementation_type& impl,
+ const null_buffers& buffers, Handler handler);
+ template <typename Handler>
+ void async_read_some_at(implementation_type& impl, boost::uint64_t offset,
+ const null_buffers& buffers, Handler handler);
+
+ // Helper function to close a handle when the associated object is being
+ // destroyed.
+ void close_for_destruction(implementation_type& impl)
+ {
+ if (is_open(impl))
+ {
+ ::CloseHandle(impl.handle_);
+ impl.handle_ = INVALID_HANDLE_VALUE;
+ impl.safe_cancellation_thread_id_ = 0;
+ }
+ }
+
+ // The IOCP service used for running asynchronous operations and dispatching
+ // handlers.
+ win_iocp_io_service& iocp_service_;
+
+ // Mutex to protect access to the linked list of implementations.
+ boost::asio::detail::mutex mutex_;
+
+ // The head of a linked list of all implementations.
+ implementation_type* impl_list_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/win_iocp_io_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/win_iocp_io_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,730 @@
+//
+// win_iocp_io_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_WIN_IOCP_IO_SERVICE_HPP
+#define BOOST_ASIO_DETAIL_WIN_IOCP_IO_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/win_iocp_io_service_fwd.hpp>
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+#include <boost/asio/detail/push_options.hpp>
+#include <limits>
+#include <boost/throw_exception.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/call_stack.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/timer_queue.hpp>
+#include <boost/asio/detail/mutex.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class win_iocp_io_service
+ : public boost::asio::detail::service_base<win_iocp_io_service>
+{
+public:
+ // Base class for all operations. A function pointer is used instead of
+ // virtual functions to avoid the associated overhead.
+ //
+ // This class inherits from OVERLAPPED so that we can downcast to get back to
+ // the operation pointer from the LPOVERLAPPED out parameter of
+ // GetQueuedCompletionStatus.
+ class operation
+ : public OVERLAPPED
+ {
+ public:
+ typedef void (*invoke_func_type)(operation*, DWORD, size_t);
+ typedef void (*destroy_func_type)(operation*);
+
+ operation(win_iocp_io_service& iocp_service,
+ invoke_func_type invoke_func, destroy_func_type destroy_func)
+ : outstanding_operations_(&iocp_service.outstanding_operations_),
+ invoke_func_(invoke_func),
+ destroy_func_(destroy_func)
+ {
+ Internal = 0;
+ InternalHigh = 0;
+ Offset = 0;
+ OffsetHigh = 0;
+ hEvent = 0;
+
+ ::InterlockedIncrement(outstanding_operations_);
+ }
+
+ void do_completion(DWORD last_error, size_t bytes_transferred)
+ {
+ invoke_func_(this, last_error, bytes_transferred);
+ }
+
+ void destroy()
+ {
+ destroy_func_(this);
+ }
+
+ protected:
+ // Prevent deletion through this type.
+ ~operation()
+ {
+ ::InterlockedDecrement(outstanding_operations_);
+ }
+
+ private:
+ long* outstanding_operations_;
+ invoke_func_type invoke_func_;
+ destroy_func_type destroy_func_;
+ };
+
+
+ // Constructor.
+ win_iocp_io_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<win_iocp_io_service>(io_service),
+ iocp_(),
+ outstanding_work_(0),
+ outstanding_operations_(0),
+ stopped_(0),
+ shutdown_(0),
+ timer_thread_(0),
+ timer_interrupt_issued_(false)
+ {
+ }
+
+ void init(size_t concurrency_hint)
+ {
+ iocp_.handle = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0,
+ static_cast<DWORD>((std::min<size_t>)(concurrency_hint, DWORD(~0))));
+ if (!iocp_.handle)
+ {
+ DWORD last_error = ::GetLastError();
+ boost::system::system_error e(
+ boost::system::error_code(last_error,
+ boost::asio::error::get_system_category()),
+ "iocp");
+ boost::throw_exception(e);
+ }
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ ::InterlockedExchange(&shutdown_, 1);
+
+ while (::InterlockedExchangeAdd(&outstanding_operations_, 0) > 0)
+ {
+ DWORD bytes_transferred = 0;
+#if (WINVER < 0x0500)
+ DWORD completion_key = 0;
+#else
+ DWORD_PTR completion_key = 0;
+#endif
+ LPOVERLAPPED overlapped = 0;
+ ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
+ &completion_key, &overlapped, INFINITE);
+ if (overlapped)
+ static_cast<operation*>(overlapped)->destroy();
+ }
+
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ timer_queues_[i]->destroy_timers();
+ timer_queues_.clear();
+ }
+
+ // Register a handle with the IO completion port.
+ boost::system::error_code register_handle(
+ HANDLE handle, boost::system::error_code& ec)
+ {
+ if (::CreateIoCompletionPort(handle, iocp_.handle, 0, 0) == 0)
+ {
+ DWORD last_error = ::GetLastError();
+ ec = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+ }
+ else
+ {
+ ec = boost::system::error_code();
+ }
+ return ec;
+ }
+
+ // Run the event loop until stopped or no more work.
+ size_t run(boost::system::error_code& ec)
+ {
+ if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
+ {
+ ec = boost::system::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;
+ }
+
+ // Run until stopped or one operation is performed.
+ size_t run_one(boost::system::error_code& ec)
+ {
+ if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ call_stack<win_iocp_io_service>::context ctx(this);
+
+ return do_one(true, ec);
+ }
+
+ // Poll for operations without blocking.
+ size_t poll(boost::system::error_code& ec)
+ {
+ if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
+ {
+ ec = boost::system::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;
+ }
+
+ // Poll for one operation without blocking.
+ size_t poll_one(boost::system::error_code& ec)
+ {
+ if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ call_stack<win_iocp_io_service>::context ctx(this);
+
+ return do_one(false, ec);
+ }
+
+ // Stop the event processing loop.
+ void stop()
+ {
+ if (::InterlockedExchange(&stopped_, 1) == 0)
+ {
+ if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
+ {
+ DWORD last_error = ::GetLastError();
+ boost::system::system_error e(
+ boost::system::error_code(last_error,
+ boost::asio::error::get_system_category()),
+ "pqcs");
+ boost::throw_exception(e);
+ }
+ }
+ }
+
+ // Reset in preparation for a subsequent run invocation.
+ void reset()
+ {
+ ::InterlockedExchange(&stopped_, 0);
+ }
+
+ // Notify that some work has started.
+ void work_started()
+ {
+ ::InterlockedIncrement(&outstanding_work_);
+ }
+
+ // Notify that some work has finished.
+ void work_finished()
+ {
+ if (::InterlockedDecrement(&outstanding_work_) == 0)
+ stop();
+ }
+
+ // Request invocation of the given handler.
+ template <typename Handler>
+ void dispatch(Handler handler)
+ {
+ if (call_stack<win_iocp_io_service>::contains(this))
+ boost_asio_handler_invoke_helpers::invoke(handler, &handler);
+ else
+ post(handler);
+ }
+
+ // Request invocation of the given handler and return immediately.
+ template <typename Handler>
+ void post(Handler handler)
+ {
+ // If the service has been shut down we silently discard the handler.
+ if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
+ return;
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef handler_operation<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, *this, handler);
+
+ // Enqueue the operation on the I/O completion port.
+ if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, ptr.get()))
+ {
+ DWORD last_error = ::GetLastError();
+ boost::system::system_error e(
+ boost::system::error_code(last_error,
+ boost::asio::error::get_system_category()),
+ "pqcs");
+ boost::throw_exception(e);
+ }
+
+ // Operation has been successfully posted.
+ ptr.release();
+ }
+
+ // Request invocation of the given OVERLAPPED-derived operation.
+ void post_completion(operation* op, DWORD op_last_error,
+ DWORD bytes_transferred)
+ {
+ // Enqueue the operation on the I/O completion port.
+ if (!::PostQueuedCompletionStatus(iocp_.handle,
+ bytes_transferred, op_last_error, op))
+ {
+ DWORD last_error = ::GetLastError();
+ boost::system::system_error e(
+ boost::system::error_code(last_error,
+ boost::asio::error::get_system_category()),
+ "pqcs");
+ boost::throw_exception(e);
+ }
+ }
+
+ // Add a new timer queue to the service.
+ template <typename Time_Traits>
+ void add_timer_queue(timer_queue<Time_Traits>& timer_queue)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(timer_mutex_);
+ timer_queues_.push_back(&timer_queue);
+ }
+
+ // Remove a timer queue from the service.
+ template <typename Time_Traits>
+ void remove_timer_queue(timer_queue<Time_Traits>& timer_queue)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(timer_mutex_);
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ {
+ if (timer_queues_[i] == &timer_queue)
+ {
+ timer_queues_.erase(timer_queues_.begin() + i);
+ return;
+ }
+ }
+ }
+
+ // Schedule a timer in the given timer queue to expire at the specified
+ // absolute time. The handler object will be invoked when the timer expires.
+ template <typename Time_Traits, typename Handler>
+ void schedule_timer(timer_queue<Time_Traits>& timer_queue,
+ const typename Time_Traits::time_type& time, Handler handler, void* token)
+ {
+ // If the service has been shut down we silently discard the timer.
+ if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
+ return;
+
+ boost::asio::detail::mutex::scoped_lock lock(timer_mutex_);
+ if (timer_queue.enqueue_timer(time, handler, token))
+ {
+ if (!timer_interrupt_issued_)
+ {
+ timer_interrupt_issued_ = true;
+ lock.unlock();
+ ::PostQueuedCompletionStatus(iocp_.handle,
+ 0, steal_timer_dispatching, 0);
+ }
+ }
+ }
+
+ // Cancel the timer associated with the given token. Returns the number of
+ // handlers that have been posted or dispatched.
+ template <typename Time_Traits>
+ std::size_t cancel_timer(timer_queue<Time_Traits>& timer_queue, void* token)
+ {
+ // If the service has been shut down we silently ignore the cancellation.
+ if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)
+ return 0;
+
+ boost::asio::detail::mutex::scoped_lock lock(timer_mutex_);
+ std::size_t n = timer_queue.cancel_timer(token);
+ if (n > 0 && !timer_interrupt_issued_)
+ {
+ timer_interrupt_issued_ = true;
+ lock.unlock();
+ ::PostQueuedCompletionStatus(iocp_.handle,
+ 0, steal_timer_dispatching, 0);
+ }
+ return n;
+ }
+
+private:
+ // Dequeues at most one operation from the I/O completion port, and then
+ // executes it. Returns the number of operations that were dequeued (i.e.
+ // either 0 or 1).
+ size_t do_one(bool block, boost::system::error_code& ec)
+ {
+ long this_thread_id = static_cast<long>(::GetCurrentThreadId());
+
+ for (;;)
+ {
+ // Try to acquire responsibility for dispatching timers.
+ bool dispatching_timers = (::InterlockedCompareExchange(
+ &timer_thread_, this_thread_id, 0) == 0);
+
+ // Calculate timeout for GetQueuedCompletionStatus call.
+ DWORD timeout = max_timeout;
+ if (dispatching_timers)
+ {
+ boost::asio::detail::mutex::scoped_lock lock(timer_mutex_);
+ timer_interrupt_issued_ = false;
+ timeout = get_timeout();
+ }
+
+ // Get the next operation from the queue.
+ DWORD bytes_transferred = 0;
+#if (WINVER < 0x0500)
+ DWORD completion_key = 0;
+#else
+ DWORD_PTR completion_key = 0;
+#endif
+ LPOVERLAPPED overlapped = 0;
+ ::SetLastError(0);
+ BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
+ &completion_key, &overlapped, block ? timeout : 0);
+ DWORD last_error = ::GetLastError();
+
+ // Dispatch any pending timers.
+ if (dispatching_timers)
+ {
+ try
+ {
+ boost::asio::detail::mutex::scoped_lock lock(timer_mutex_);
+ timer_queues_copy_ = timer_queues_;
+ for (std::size_t i = 0; i < timer_queues_copy_.size(); ++i)
+ {
+ timer_queues_copy_[i]->dispatch_timers();
+ timer_queues_copy_[i]->dispatch_cancellations();
+ timer_queues_copy_[i]->complete_timers();
+ }
+ }
+ catch (...)
+ {
+ // Transfer responsibility for dispatching timers to another thread.
+ if (::InterlockedCompareExchange(&timer_thread_,
+ 0, this_thread_id) == this_thread_id)
+ {
+ ::PostQueuedCompletionStatus(iocp_.handle,
+ 0, transfer_timer_dispatching, 0);
+ }
+
+ throw;
+ }
+ }
+
+ if (!ok && overlapped == 0)
+ {
+ if (block && last_error == WAIT_TIMEOUT)
+ {
+ // Relinquish responsibility for dispatching timers.
+ if (dispatching_timers)
+ {
+ ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id);
+ }
+
+ continue;
+ }
+
+ // Transfer responsibility for dispatching timers to another thread.
+ if (dispatching_timers && ::InterlockedCompareExchange(
+ &timer_thread_, 0, this_thread_id) == this_thread_id)
+ {
+ ::PostQueuedCompletionStatus(iocp_.handle,
+ 0, transfer_timer_dispatching, 0);
+ }
+
+ ec = boost::system::error_code();
+ return 0;
+ }
+ else if (overlapped)
+ {
+ // We may have been passed a last_error value in the completion_key.
+ if (last_error == 0)
+ {
+ last_error = completion_key;
+ }
+
+ // Transfer responsibility for dispatching timers to another thread.
+ if (dispatching_timers && ::InterlockedCompareExchange(
+ &timer_thread_, 0, this_thread_id) == this_thread_id)
+ {
+ ::PostQueuedCompletionStatus(iocp_.handle,
+ 0, transfer_timer_dispatching, 0);
+ }
+
+ // Ensure that the io_service does not exit due to running out of work
+ // while we make the upcall.
+ auto_work work(*this);
+
+ // Dispatch the operation.
+ operation* op = static_cast<operation*>(overlapped);
+ op->do_completion(last_error, bytes_transferred);
+
+ ec = boost::system::error_code();
+ return 1;
+ }
+ else if (completion_key == transfer_timer_dispatching)
+ {
+ // Woken up to try to acquire responsibility for dispatching timers.
+ ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id);
+ }
+ else if (completion_key == steal_timer_dispatching)
+ {
+ // Woken up to steal responsibility for dispatching timers.
+ ::InterlockedExchange(&timer_thread_, 0);
+ }
+ else
+ {
+ // Relinquish responsibility for dispatching timers. If the io_service
+ // is not being stopped then the thread will get an opportunity to
+ // reacquire timer responsibility on the next loop iteration.
+ if (dispatching_timers)
+ {
+ ::InterlockedCompareExchange(&timer_thread_, 0, this_thread_id);
+ }
+
+ // The stopped_ flag is always checked to ensure that any leftover
+ // interrupts from a previous run invocation are ignored.
+ if (::InterlockedExchangeAdd(&stopped_, 0) != 0)
+ {
+ // Wake up next thread that is blocked on GetQueuedCompletionStatus.
+ if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
+ {
+ DWORD last_error = ::GetLastError();
+ ec = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+ return 0;
+ }
+
+ ec = boost::system::error_code();
+ return 0;
+ }
+ }
+ }
+ }
+
+ // Check if all timer queues are empty.
+ bool all_timer_queues_are_empty() const
+ {
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ if (!timer_queues_[i]->empty())
+ return false;
+ return true;
+ }
+
+ // Get the timeout value for the GetQueuedCompletionStatus call. The timeout
+ // value is returned as a number of milliseconds. We will wait no longer than
+ // 1000 milliseconds.
+ DWORD get_timeout()
+ {
+ if (all_timer_queues_are_empty())
+ return max_timeout;
+
+ boost::posix_time::time_duration minimum_wait_duration
+ = boost::posix_time::milliseconds(max_timeout);
+
+ for (std::size_t i = 0; i < timer_queues_.size(); ++i)
+ {
+ boost::posix_time::time_duration wait_duration
+ = timer_queues_[i]->wait_duration();
+ if (wait_duration < minimum_wait_duration)
+ minimum_wait_duration = wait_duration;
+ }
+
+ if (minimum_wait_duration > boost::posix_time::time_duration())
+ {
+ int milliseconds = minimum_wait_duration.total_milliseconds();
+ return static_cast<DWORD>(milliseconds > 0 ? milliseconds : 1);
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ struct auto_work
+ {
+ auto_work(win_iocp_io_service& io_service)
+ : io_service_(io_service)
+ {
+ io_service_.work_started();
+ }
+
+ ~auto_work()
+ {
+ io_service_.work_finished();
+ }
+
+ private:
+ win_iocp_io_service& io_service_;
+ };
+
+ template <typename Handler>
+ struct handler_operation
+ : public operation
+ {
+ handler_operation(win_iocp_io_service& io_service,
+ Handler handler)
+ : operation(io_service, &handler_operation<Handler>::do_completion_impl,
+ &handler_operation<Handler>::destroy_impl),
+ io_service_(io_service),
+ handler_(handler)
+ {
+ io_service_.work_started();
+ }
+
+ ~handler_operation()
+ {
+ io_service_.work_finished();
+ }
+
+ private:
+ // Prevent copying and assignment.
+ handler_operation(const handler_operation&);
+ void operator=(const handler_operation&);
+
+ static void do_completion_impl(operation* op, DWORD, size_t)
+ {
+ // Take ownership of the operation object.
+ typedef handler_operation<Handler> op_type;
+ op_type* handler_op(static_cast<op_type*>(op));
+ typedef handler_alloc_traits<Handler, op_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made.
+ Handler handler(handler_op->handler_);
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+
+ // Make the upcall.
+ boost_asio_handler_invoke_helpers::invoke(handler, &handler);
+ }
+
+ static void destroy_impl(operation* op)
+ {
+ // Take ownership of the operation object.
+ typedef handler_operation<Handler> op_type;
+ op_type* handler_op(static_cast<op_type*>(op));
+ typedef handler_alloc_traits<Handler, op_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+
+ // 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(handler_op->handler_);
+ (void)handler;
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+ }
+
+ win_iocp_io_service& io_service_;
+ Handler handler_;
+ };
+
+ // The IO completion port used for queueing operations.
+ struct iocp_holder
+ {
+ HANDLE handle;
+ iocp_holder() : handle(0) {}
+ ~iocp_holder() { if (handle) ::CloseHandle(handle); }
+ } iocp_;
+
+ // The count of unfinished work.
+ long outstanding_work_;
+
+ // The count of unfinished operations.
+ long outstanding_operations_;
+ friend class operation;
+
+ // Flag to indicate whether the event loop has been stopped.
+ long stopped_;
+
+ // Flag to indicate whether the service has been shut down.
+ long shutdown_;
+
+ enum
+ {
+ // Maximum GetQueuedCompletionStatus timeout, in milliseconds.
+ max_timeout = 500,
+
+ // Completion key value to indicate that responsibility for dispatching
+ // timers is being cooperatively transferred from one thread to another.
+ transfer_timer_dispatching = 1,
+
+ // Completion key value to indicate that responsibility for dispatching
+ // timers should be stolen from another thread.
+ steal_timer_dispatching = 2
+ };
+
+ // The thread that's currently in charge of dispatching timers.
+ long timer_thread_;
+
+ // Mutex for protecting access to the timer queues.
+ mutex timer_mutex_;
+
+ // Whether a thread has been interrupted to process a new timeout.
+ bool timer_interrupt_issued_;
+
+ // The timer queues.
+ std::vector<timer_queue_base*> timer_queues_;
+
+ // A copy of the timer queues, used when dispatching, cancelling and cleaning
+ // up timers. The copy is stored as a class data member to avoid unnecessary
+ // memory allocation.
+ std::vector<timer_queue_base*> timer_queues_copy_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_WIN_IOCP_IO_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/win_iocp_io_service_fwd.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/win_iocp_io_service_fwd.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,52 @@
+//
+// win_iocp_io_service_fwd.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_WIN_IOCP_IO_SERVICE_FWD_HPP
+#define BOOST_ASIO_DETAIL_WIN_IOCP_IO_SERVICE_FWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/socket_types.hpp>
+
+// This service is only supported on Win32 (NT4 and later).
+#if !defined(BOOST_ASIO_DISABLE_IOCP)
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
+#if !defined(UNDER_CE)
+
+// Define this to indicate that IOCP is supported on the target platform.
+#define BOOST_ASIO_HAS_IOCP 1
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class win_iocp_io_service;
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // !defined(UNDER_CE)
+#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+#endif // !defined(BOOST_ASIO_DISABLE_IOCP)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_WIN_IOCP_IO_SERVICE_FWD_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/win_iocp_serial_port_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/win_iocp_serial_port_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,294 @@
+//
+// win_iocp_serial_port_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info_at_[hidden])
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP
+#define BOOST_ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstring>
+#include <string>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/win_iocp_io_service_fwd.hpp>
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/win_iocp_handle_service.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// Extend win_iocp_handle_service to provide serial port support.
+class win_iocp_serial_port_service
+ : public boost::asio::detail::service_base<win_iocp_serial_port_service>
+{
+public:
+ // The native type of a stream handle.
+ typedef win_iocp_handle_service::native_type native_type;
+
+ // The implementation type of the stream handle.
+ typedef win_iocp_handle_service::implementation_type implementation_type;
+
+ win_iocp_serial_port_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ win_iocp_serial_port_service>(io_service),
+ handle_service_(
+ boost::asio::use_service<win_iocp_handle_service>(io_service))
+ {
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ // Construct a new handle implementation.
+ void construct(implementation_type& impl)
+ {
+ handle_service_.construct(impl);
+ }
+
+ // Destroy a handle implementation.
+ void destroy(implementation_type& impl)
+ {
+ handle_service_.destroy(impl);
+ }
+
+ // Open the serial port using the specified device name.
+ boost::system::error_code open(implementation_type& impl,
+ const std::string& device, boost::system::error_code& ec)
+ {
+ if (is_open(impl))
+ {
+ ec = boost::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 = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ // Determine the initial serial port parameters.
+ using namespace std; // For memcpy.
+ ::DCB dcb;
+ memset(&dcb, 0, sizeof(DCB));
+ dcb.DCBlength = sizeof(DCB);
+ if (!::GetCommState(handle, &dcb))
+ {
+ DWORD last_error = ::GetLastError();
+ ::CloseHandle(handle);
+ ec = boost::system::error_code(last_error,
+ boost::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 = boost::system::error_code(last_error,
+ boost::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 = boost::system::error_code(last_error,
+ boost::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;
+ }
+
+ // Assign a native handle to a handle implementation.
+ boost::system::error_code assign(implementation_type& impl,
+ const native_type& native_handle, boost::system::error_code& ec)
+ {
+ return handle_service_.assign(impl, native_handle, ec);
+ }
+
+ // Determine whether the handle is open.
+ bool is_open(const implementation_type& impl) const
+ {
+ return handle_service_.is_open(impl);
+ }
+
+ // Destroy a handle implementation.
+ boost::system::error_code close(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return handle_service_.close(impl, ec);
+ }
+
+ // Get the native handle representation.
+ native_type native(implementation_type& impl)
+ {
+ return handle_service_.native(impl);
+ }
+
+ // Cancel all operations associated with the handle.
+ boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return handle_service_.cancel(impl, ec);
+ }
+
+ // Set an option on the serial port.
+ template <typename SettableSerialPortOption>
+ boost::system::error_code set_option(implementation_type& impl,
+ const SettableSerialPortOption& option, boost::system::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 = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ if (option.store(dcb, ec))
+ return ec;
+
+ if (!::SetCommState(handle_service_.native(impl), &dcb))
+ {
+ DWORD last_error = ::GetLastError();
+ ec = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Get an option from the serial port.
+ template <typename GettableSerialPortOption>
+ boost::system::error_code get_option(const implementation_type& impl,
+ GettableSerialPortOption& option, boost::system::error_code& ec) const
+ {
+ using namespace std; // For memcpy.
+
+ ::DCB dcb;
+ memset(&dcb, 0, sizeof(DCB));
+ dcb.DCBlength = sizeof(DCB);
+ if (!::GetCommState(handle_service_.native(impl), &dcb))
+ {
+ DWORD last_error = ::GetLastError();
+ ec = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+ return ec;
+ }
+
+ return option.load(dcb, ec);
+ }
+
+ // Send a break sequence to the serial port.
+ boost::system::error_code send_break(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ ec = boost::asio::error::operation_not_supported;
+ return ec;
+ }
+
+ // Write the given data. Returns the number of bytes sent.
+ template <typename ConstBufferSequence>
+ size_t write_some(implementation_type& impl,
+ const ConstBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return handle_service_.write_some(impl, buffers, ec);
+ }
+
+ // Start an asynchronous write. The data being written must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_write_some(implementation_type& impl,
+ const ConstBufferSequence& buffers, Handler handler)
+ {
+ handle_service_.async_write_some(impl, buffers, handler);
+ }
+
+ // Read some data. Returns the number of bytes received.
+ template <typename MutableBufferSequence>
+ size_t read_some(implementation_type& impl,
+ const MutableBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return handle_service_.read_some(impl, buffers, ec);
+ }
+
+ // Start an asynchronous read. The buffer for the data being received must be
+ // valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_read_some(implementation_type& impl,
+ const MutableBufferSequence& buffers, Handler handler)
+ {
+ handle_service_.async_read_some(impl, buffers, handler);
+ }
+
+private:
+ // The handle service used for initiating asynchronous operations.
+ win_iocp_handle_service& handle_service_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/win_iocp_socket_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/win_iocp_socket_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,2415 @@
+//
+// win_iocp_socket_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP
+#define BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/win_iocp_io_service_fwd.hpp>
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstring>
+#include <boost/shared_ptr.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/select_reactor.hpp>
+#include <boost/asio/detail/socket_holder.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/win_iocp_io_service.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Protocol>
+class win_iocp_socket_service
+ : public boost::asio::detail::service_base<win_iocp_socket_service<Protocol> >
+{
+public:
+ // The protocol type.
+ typedef Protocol protocol_type;
+
+ // The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+ // Base class for all operations.
+ typedef win_iocp_io_service::operation operation;
+
+ struct noop_deleter { void operator()(void*) {} };
+ typedef boost::shared_ptr<void> shared_cancel_token_type;
+ typedef boost::weak_ptr<void> weak_cancel_token_type;
+
+ // The native type of a socket.
+ class native_type
+ {
+ public:
+ native_type(socket_type s)
+ : socket_(s),
+ have_remote_endpoint_(false)
+ {
+ }
+
+ native_type(socket_type s, const endpoint_type& ep)
+ : socket_(s),
+ have_remote_endpoint_(true),
+ remote_endpoint_(ep)
+ {
+ }
+
+ void operator=(socket_type s)
+ {
+ socket_ = s;
+ have_remote_endpoint_ = false;
+ remote_endpoint_ = endpoint_type();
+ }
+
+ operator socket_type() const
+ {
+ return socket_;
+ }
+
+ HANDLE as_handle() const
+ {
+ return reinterpret_cast<HANDLE>(socket_);
+ }
+
+ bool have_remote_endpoint() const
+ {
+ return have_remote_endpoint_;
+ }
+
+ endpoint_type remote_endpoint() const
+ {
+ return remote_endpoint_;
+ }
+
+ private:
+ socket_type socket_;
+ bool have_remote_endpoint_;
+ endpoint_type remote_endpoint_;
+ };
+
+ // The type of the reactor used for connect operations.
+ typedef detail::select_reactor<true> reactor_type;
+
+ // The implementation type of the socket.
+ class implementation_type
+ {
+ public:
+ // Default constructor.
+ implementation_type()
+ : socket_(invalid_socket),
+ flags_(0),
+ cancel_token_(),
+ protocol_(endpoint_type().protocol()),
+ next_(0),
+ prev_(0)
+ {
+ }
+
+ private:
+ // Only this service will have access to the internal values.
+ friend class win_iocp_socket_service;
+
+ // The native socket representation.
+ native_type socket_;
+
+ enum
+ {
+ enable_connection_aborted = 1, // User wants connection_aborted errors.
+ close_might_block = 2, // User set linger option for blocking close.
+ user_set_non_blocking = 4 // The user wants a non-blocking socket.
+ };
+
+ // Flags indicating the current state of the socket.
+ unsigned char flags_;
+
+ // We use a shared pointer as a cancellation token here to work around the
+ // broken Windows support for cancellation. MSDN says that when you call
+ // closesocket any outstanding WSARecv or WSASend operations will complete
+ // with the error ERROR_OPERATION_ABORTED. In practice they complete with
+ // ERROR_NETNAME_DELETED, which means you can't tell the difference between
+ // a local cancellation and the socket being hard-closed by the peer.
+ shared_cancel_token_type cancel_token_;
+
+ // The protocol associated with the socket.
+ protocol_type protocol_;
+
+ // Per-descriptor data used by the reactor.
+ reactor_type::per_descriptor_data reactor_data_;
+
+#if defined(BOOST_ASIO_ENABLE_CANCELIO)
+ // The ID of the thread from which it is safe to cancel asynchronous
+ // operations. 0 means no asynchronous operations have been started yet.
+ // ~0 means asynchronous operations have been started from more than one
+ // thread, and cancellation is not supported for the socket.
+ DWORD safe_cancellation_thread_id_;
+#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
+
+ // Pointers to adjacent socket implementations in linked list.
+ implementation_type* next_;
+ implementation_type* prev_;
+ };
+
+ // The maximum number of buffers to support in a single operation.
+ enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
+
+ // Constructor.
+ win_iocp_socket_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ win_iocp_socket_service<Protocol> >(io_service),
+ iocp_service_(boost::asio::use_service<win_iocp_io_service>(io_service)),
+ reactor_(0),
+ mutex_(),
+ impl_list_(0)
+ {
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ // Close all implementations, causing all operations to complete.
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ implementation_type* impl = impl_list_;
+ while (impl)
+ {
+ boost::system::error_code ignored_ec;
+ close_for_destruction(*impl);
+ impl = impl->next_;
+ }
+ }
+
+ // Construct a new socket implementation.
+ void construct(implementation_type& impl)
+ {
+ impl.socket_ = invalid_socket;
+ impl.flags_ = 0;
+ impl.cancel_token_.reset();
+#if defined(BOOST_ASIO_ENABLE_CANCELIO)
+ impl.safe_cancellation_thread_id_ = 0;
+#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
+
+ // Insert implementation into linked list of all implementations.
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ impl.next_ = impl_list_;
+ impl.prev_ = 0;
+ if (impl_list_)
+ impl_list_->prev_ = &impl;
+ impl_list_ = &impl;
+ }
+
+ // Destroy a socket implementation.
+ void destroy(implementation_type& impl)
+ {
+ close_for_destruction(impl);
+
+ // Remove implementation from linked list of all implementations.
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ if (impl_list_ == &impl)
+ impl_list_ = impl.next_;
+ if (impl.prev_)
+ impl.prev_->next_ = impl.next_;
+ if (impl.next_)
+ impl.next_->prev_= impl.prev_;
+ impl.next_ = 0;
+ impl.prev_ = 0;
+ }
+
+ // Open a new socket implementation.
+ boost::system::error_code open(implementation_type& impl,
+ const protocol_type& protocol, boost::system::error_code& ec)
+ {
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ socket_holder sock(socket_ops::socket(protocol.family(), protocol.type(),
+ protocol.protocol(), ec));
+ if (sock.get() == invalid_socket)
+ return ec;
+
+ HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock.get());
+ if (iocp_service_.register_handle(sock_as_handle, ec))
+ return ec;
+
+ impl.socket_ = sock.release();
+ impl.flags_ = 0;
+ impl.cancel_token_.reset(static_cast<void*>(0), noop_deleter());
+ impl.protocol_ = protocol;
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Assign a native socket to a socket implementation.
+ boost::system::error_code assign(implementation_type& impl,
+ const protocol_type& protocol, const native_type& native_socket,
+ boost::system::error_code& ec)
+ {
+ if (is_open(impl))
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ if (iocp_service_.register_handle(native_socket.as_handle(), ec))
+ return ec;
+
+ impl.socket_ = native_socket;
+ impl.flags_ = 0;
+ impl.cancel_token_.reset(static_cast<void*>(0), noop_deleter());
+ impl.protocol_ = protocol;
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Determine whether the socket is open.
+ bool is_open(const implementation_type& impl) const
+ {
+ return impl.socket_ != invalid_socket;
+ }
+
+ // Destroy a socket implementation.
+ boost::system::error_code close(implementation_type& impl,
+ boost::system::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_type* reactor = static_cast<reactor_type*>(
+ interlocked_compare_exchange_pointer(
+ reinterpret_cast<void**>(&reactor_), 0, 0));
+ if (reactor)
+ reactor->close_descriptor(impl.socket_, impl.reactor_data_);
+
+ if (socket_ops::close(impl.socket_, ec) == socket_error_retval)
+ return ec;
+
+ impl.socket_ = invalid_socket;
+ impl.flags_ = 0;
+ impl.cancel_token_.reset();
+#if defined(BOOST_ASIO_ENABLE_CANCELIO)
+ impl.safe_cancellation_thread_id_ = 0;
+#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
+ }
+
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Get the native socket representation.
+ native_type native(implementation_type& impl)
+ {
+ return impl.socket_;
+ }
+
+ // Cancel all operations associated with the socket.
+ boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::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 = boost::system::error_code();
+ }
+ else
+ {
+ ec = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+ }
+ }
+ else
+ {
+ ec = boost::system::error_code();
+ }
+ }
+#if defined(BOOST_ASIO_ENABLE_CANCELIO)
+ else if (impl.safe_cancellation_thread_id_ == 0)
+ {
+ // No operations have been started, so there's nothing to cancel.
+ ec = boost::system::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 = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+ }
+ else
+ {
+ ec = boost::system::error_code();
+ }
+ }
+ else
+ {
+ // Asynchronous operations have been started from more than one thread,
+ // so cancellation is not safe.
+ ec = boost::asio::error::operation_not_supported;
+ }
+#else // defined(BOOST_ASIO_ENABLE_CANCELIO)
+ else
+ {
+ // Cancellation is not supported as CancelIo may not be used.
+ ec = boost::asio::error::operation_not_supported;
+ }
+#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
+
+ return ec;
+ }
+
+ // Determine whether the socket is at the out-of-band data mark.
+ bool at_mark(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return false;
+ }
+
+ boost::asio::detail::ioctl_arg_type value = 0;
+ socket_ops::ioctl(impl.socket_, SIOCATMARK, &value, ec);
+ return ec ? false : value != 0;
+ }
+
+ // Determine the number of bytes available for reading.
+ std::size_t available(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ boost::asio::detail::ioctl_arg_type value = 0;
+ socket_ops::ioctl(impl.socket_, FIONREAD, &value, ec);
+ return ec ? static_cast<std::size_t>(0) : static_cast<std::size_t>(value);
+ }
+
+ // Bind the socket to the specified local endpoint.
+ boost::system::error_code bind(implementation_type& impl,
+ const endpoint_type& endpoint, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);
+ return ec;
+ }
+
+ // Place the socket into the state where it will listen for new connections.
+ boost::system::error_code listen(implementation_type& impl, int backlog,
+ boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ socket_ops::listen(impl.socket_, backlog, ec);
+ return ec;
+ }
+
+ // Set a socket option.
+ template <typename Option>
+ boost::system::error_code set_option(implementation_type& impl,
+ const Option& option, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ if (option.level(impl.protocol_) == custom_socket_option_level
+ && option.name(impl.protocol_) == enable_connection_aborted_option)
+ {
+ if (option.size(impl.protocol_) != sizeof(int))
+ {
+ ec = boost::asio::error::invalid_argument;
+ }
+ else
+ {
+ if (*reinterpret_cast<const int*>(option.data(impl.protocol_)))
+ impl.flags_ |= implementation_type::enable_connection_aborted;
+ else
+ impl.flags_ &= ~implementation_type::enable_connection_aborted;
+ ec = boost::system::error_code();
+ }
+ return ec;
+ }
+ else
+ {
+ if (option.level(impl.protocol_) == SOL_SOCKET
+ && option.name(impl.protocol_) == SO_LINGER)
+ {
+ const ::linger* linger_option =
+ reinterpret_cast<const ::linger*>(option.data(impl.protocol_));
+ if (linger_option->l_onoff != 0 && linger_option->l_linger != 0)
+ impl.flags_ |= implementation_type::close_might_block;
+ else
+ impl.flags_ &= ~implementation_type::close_might_block;
+ }
+
+ socket_ops::setsockopt(impl.socket_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), option.size(impl.protocol_), ec);
+ return ec;
+ }
+ }
+
+ // Set a socket option.
+ template <typename Option>
+ boost::system::error_code get_option(const implementation_type& impl,
+ Option& option, boost::system::error_code& ec) const
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ if (option.level(impl.protocol_) == custom_socket_option_level
+ && option.name(impl.protocol_) == enable_connection_aborted_option)
+ {
+ if (option.size(impl.protocol_) != sizeof(int))
+ {
+ ec = boost::asio::error::invalid_argument;
+ }
+ else
+ {
+ int* target = reinterpret_cast<int*>(option.data(impl.protocol_));
+ if (impl.flags_ & implementation_type::enable_connection_aborted)
+ *target = 1;
+ else
+ *target = 0;
+ option.resize(impl.protocol_, sizeof(int));
+ ec = boost::system::error_code();
+ }
+ return ec;
+ }
+ else
+ {
+ size_t size = option.size(impl.protocol_);
+ socket_ops::getsockopt(impl.socket_,
+ option.level(impl.protocol_), option.name(impl.protocol_),
+ option.data(impl.protocol_), &size, ec);
+ if (!ec)
+ option.resize(impl.protocol_, size);
+ return ec;
+ }
+ }
+
+ // Perform an IO control command on the socket.
+ template <typename IO_Control_Command>
+ boost::system::error_code io_control(implementation_type& impl,
+ IO_Control_Command& command, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ socket_ops::ioctl(impl.socket_, command.name(),
+ static_cast<ioctl_arg_type*>(command.data()), ec);
+
+ if (!ec && command.name() == static_cast<int>(FIONBIO))
+ {
+ if (command.get())
+ impl.flags_ |= implementation_type::user_set_non_blocking;
+ else
+ impl.flags_ &= ~implementation_type::user_set_non_blocking;
+ }
+
+ return ec;
+ }
+
+ // Get the local endpoint.
+ endpoint_type local_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return endpoint_type();
+ }
+
+ endpoint_type endpoint;
+ std::size_t addr_len = endpoint.capacity();
+ if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))
+ return endpoint_type();
+ endpoint.resize(addr_len);
+ return endpoint;
+ }
+
+ // Get the remote endpoint.
+ endpoint_type remote_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return endpoint_type();
+ }
+
+ if (impl.socket_.have_remote_endpoint())
+ {
+ // Check if socket is still connected.
+ DWORD connect_time = 0;
+ size_t connect_time_len = sizeof(connect_time);
+ if (socket_ops::getsockopt(impl.socket_, SOL_SOCKET, SO_CONNECT_TIME,
+ &connect_time, &connect_time_len, ec) == socket_error_retval)
+ {
+ return endpoint_type();
+ }
+ if (connect_time == 0xFFFFFFFF)
+ {
+ ec = boost::asio::error::not_connected;
+ return endpoint_type();
+ }
+
+ ec = boost::system::error_code();
+ return impl.socket_.remote_endpoint();
+ }
+ else
+ {
+ endpoint_type endpoint;
+ std::size_t addr_len = endpoint.capacity();
+ if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, ec))
+ return endpoint_type();
+ endpoint.resize(addr_len);
+ return endpoint;
+ }
+ }
+
+ /// Disable sends or receives on the socket.
+ boost::system::error_code shutdown(implementation_type& impl,
+ socket_base::shutdown_type what, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ socket_ops::shutdown(impl.socket_, what, ec);
+ return ec;
+ }
+
+ // Send the given data to the peer. Returns the number of bytes sent.
+ template <typename ConstBufferSequence>
+ size_t send(implementation_type& impl, const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Copy buffers into WSABUF array.
+ ::WSABUF bufs[max_buffers];
+ typename ConstBufferSequence::const_iterator iter = buffers.begin();
+ typename ConstBufferSequence::const_iterator end = buffers.end();
+ DWORD i = 0;
+ size_t total_buffer_size = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::const_buffer buffer(*iter);
+ bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));
+ bufs[i].buf = const_cast<char*>(
+ boost::asio::buffer_cast<const char*>(buffer));
+ total_buffer_size += boost::asio::buffer_size(buffer);
+ }
+
+ // A request to receive 0 bytes on a stream socket is a no-op.
+ if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ // Send the data.
+ DWORD bytes_transferred = 0;
+ int result = ::WSASend(impl.socket_, bufs,
+ i, &bytes_transferred, flags, 0, 0);
+ if (result != 0)
+ {
+ DWORD last_error = ::WSAGetLastError();
+ if (last_error == ERROR_NETNAME_DELETED)
+ last_error = WSAECONNRESET;
+ else if (last_error == ERROR_PORT_UNREACHABLE)
+ last_error = WSAECONNREFUSED;
+ ec = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+ return 0;
+ }
+
+ ec = boost::system::error_code();
+ return bytes_transferred;
+ }
+
+ // Wait until data can be sent without blocking.
+ size_t send(implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Wait for socket to become ready.
+ socket_ops::poll_write(impl.socket_, ec);
+
+ return 0;
+ }
+
+ template <typename ConstBufferSequence, typename Handler>
+ class send_operation
+ : public operation
+ {
+ public:
+ send_operation(win_iocp_io_service& io_service,
+ weak_cancel_token_type cancel_token,
+ const ConstBufferSequence& buffers, Handler handler)
+ : operation(io_service,
+ &send_operation<ConstBufferSequence, Handler>::do_completion_impl,
+ &send_operation<ConstBufferSequence, Handler>::destroy_impl),
+ work_(io_service.get_io_service()),
+ cancel_token_(cancel_token),
+ buffers_(buffers),
+ handler_(handler)
+ {
+ }
+
+ private:
+ static void do_completion_impl(operation* op,
+ DWORD last_error, size_t bytes_transferred)
+ {
+ // Take ownership of the operation object.
+ typedef send_operation<ConstBufferSequence, Handler> op_type;
+ op_type* handler_op(static_cast<op_type*>(op));
+ typedef handler_alloc_traits<Handler, op_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ // Check whether buffers are still valid.
+ typename ConstBufferSequence::const_iterator iter
+ = handler_op->buffers_.begin();
+ typename ConstBufferSequence::const_iterator end
+ = handler_op->buffers_.end();
+ while (iter != end)
+ {
+ boost::asio::const_buffer buffer(*iter);
+ boost::asio::buffer_cast<const char*>(buffer);
+ ++iter;
+ }
+#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+
+ // Map non-portable errors to their portable counterparts.
+ boost::system::error_code ec(last_error,
+ boost::asio::error::get_system_category());
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ {
+ if (handler_op->cancel_token_.expired())
+ ec = boost::asio::error::operation_aborted;
+ else
+ ec = boost::asio::error::connection_reset;
+ }
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = boost::asio::error::connection_refused;
+ }
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made.
+ Handler handler(handler_op->handler_);
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+
+ // Call the handler.
+ boost_asio_handler_invoke_helpers::invoke(
+ detail::bind_handler(handler, ec, bytes_transferred), &handler);
+ }
+
+ static void destroy_impl(operation* op)
+ {
+ // Take ownership of the operation object.
+ typedef send_operation<ConstBufferSequence, Handler> op_type;
+ op_type* handler_op(static_cast<op_type*>(op));
+ typedef handler_alloc_traits<Handler, op_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+
+ // 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(handler_op->handler_);
+ (void)handler;
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+ }
+
+ boost::asio::io_service::work work_;
+ weak_cancel_token_type cancel_token_;
+ ConstBufferSequence buffers_;
+ Handler handler_;
+ };
+
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_send(implementation_type& impl, const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ return;
+ }
+
+#if defined(BOOST_ASIO_ENABLE_CANCELIO)
+ // Update the ID of the thread from which cancellation is safe.
+ 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);
+#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef send_operation<ConstBufferSequence, Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_,
+ impl.cancel_token_, buffers, handler);
+
+ // Copy buffers into WSABUF array.
+ ::WSABUF bufs[max_buffers];
+ typename ConstBufferSequence::const_iterator iter = buffers.begin();
+ typename ConstBufferSequence::const_iterator end = buffers.end();
+ DWORD i = 0;
+ size_t total_buffer_size = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::const_buffer buffer(*iter);
+ bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));
+ bufs[i].buf = const_cast<char*>(
+ boost::asio::buffer_cast<const char*>(buffer));
+ total_buffer_size += boost::asio::buffer_size(buffer);
+ }
+
+ // A request to receive 0 bytes on a stream socket is a no-op.
+ if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
+ {
+ boost::asio::io_service::work work(this->get_io_service());
+ ptr.reset();
+ boost::system::error_code error;
+ iocp_service_.post(bind_handler(handler, error, 0));
+ return;
+ }
+
+ // Send the data.
+ DWORD bytes_transferred = 0;
+ int result = ::WSASend(impl.socket_, bufs, i,
+ &bytes_transferred, flags, ptr.get(), 0);
+ DWORD last_error = ::WSAGetLastError();
+
+ // Check if the operation completed immediately.
+ if (result != 0 && last_error != WSA_IO_PENDING)
+ {
+ boost::asio::io_service::work work(this->get_io_service());
+ ptr.reset();
+ boost::system::error_code ec(last_error,
+ boost::asio::error::get_system_category());
+ iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
+ }
+ else
+ {
+ ptr.release();
+ }
+ }
+
+ template <typename Handler>
+ class null_buffers_operation
+ {
+ public:
+ null_buffers_operation(boost::asio::io_service& io_service, Handler handler)
+ : work_(io_service),
+ handler_(handler)
+ {
+ }
+
+ bool perform(boost::system::error_code&,
+ std::size_t& bytes_transferred)
+ {
+ bytes_transferred = 0;
+ return true;
+ }
+
+ void complete(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ work_.get_io_service().post(bind_handler(
+ handler_, ec, bytes_transferred));
+ }
+
+ private:
+ boost::asio::io_service::work work_;
+ Handler handler_;
+ };
+
+ // Start an asynchronous wait until data can be sent without blocking.
+ template <typename Handler>
+ void async_send(implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ }
+ else
+ {
+ // Check if the reactor was already obtained from the io_service.
+ reactor_type* reactor = static_cast<reactor_type*>(
+ interlocked_compare_exchange_pointer(
+ reinterpret_cast<void**>(&reactor_), 0, 0));
+ if (!reactor)
+ {
+ reactor = &(boost::asio::use_service<reactor_type>(
+ this->get_io_service()));
+ interlocked_exchange_pointer(
+ reinterpret_cast<void**>(&reactor_), reactor);
+ }
+
+ reactor->start_write_op(impl.socket_, impl.reactor_data_,
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
+ false);
+ }
+ }
+
+ // Send a datagram to the specified endpoint. Returns the number of bytes
+ // sent.
+ template <typename ConstBufferSequence>
+ size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,
+ const endpoint_type& destination, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Copy buffers into WSABUF array.
+ ::WSABUF bufs[max_buffers];
+ typename ConstBufferSequence::const_iterator iter = buffers.begin();
+ typename ConstBufferSequence::const_iterator end = buffers.end();
+ DWORD i = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::const_buffer buffer(*iter);
+ bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));
+ bufs[i].buf = const_cast<char*>(
+ boost::asio::buffer_cast<const char*>(buffer));
+ }
+
+ // Send the data.
+ DWORD bytes_transferred = 0;
+ int result = ::WSASendTo(impl.socket_, bufs, i, &bytes_transferred,
+ flags, destination.data(), static_cast<int>(destination.size()), 0, 0);
+ if (result != 0)
+ {
+ DWORD last_error = ::WSAGetLastError();
+ if (last_error == ERROR_PORT_UNREACHABLE)
+ last_error = WSAECONNREFUSED;
+ ec = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+ return 0;
+ }
+
+ ec = boost::system::error_code();
+ return bytes_transferred;
+ }
+
+ // Wait until data can be sent without blocking.
+ size_t send_to(implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, const endpoint_type&,
+ boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Wait for socket to become ready.
+ socket_ops::poll_write(impl.socket_, ec);
+
+ return 0;
+ }
+
+ template <typename ConstBufferSequence, typename Handler>
+ class send_to_operation
+ : public operation
+ {
+ public:
+ send_to_operation(win_iocp_io_service& io_service,
+ const ConstBufferSequence& buffers, Handler handler)
+ : operation(io_service,
+ &send_to_operation<ConstBufferSequence, Handler>::do_completion_impl,
+ &send_to_operation<ConstBufferSequence, Handler>::destroy_impl),
+ work_(io_service.get_io_service()),
+ buffers_(buffers),
+ handler_(handler)
+ {
+ }
+
+ private:
+ static void do_completion_impl(operation* op,
+ DWORD last_error, size_t bytes_transferred)
+ {
+ // Take ownership of the operation object.
+ typedef send_to_operation<ConstBufferSequence, Handler> op_type;
+ op_type* handler_op(static_cast<op_type*>(op));
+ typedef handler_alloc_traits<Handler, op_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ // Check whether buffers are still valid.
+ typename ConstBufferSequence::const_iterator iter
+ = handler_op->buffers_.begin();
+ typename ConstBufferSequence::const_iterator end
+ = handler_op->buffers_.end();
+ while (iter != end)
+ {
+ boost::asio::const_buffer buffer(*iter);
+ boost::asio::buffer_cast<const char*>(buffer);
+ ++iter;
+ }
+#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+
+ // Map non-portable errors to their portable counterparts.
+ boost::system::error_code ec(last_error,
+ boost::asio::error::get_system_category());
+ if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = boost::asio::error::connection_refused;
+ }
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made.
+ Handler handler(handler_op->handler_);
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+
+ // Call the handler.
+ boost_asio_handler_invoke_helpers::invoke(
+ detail::bind_handler(handler, ec, bytes_transferred), &handler);
+ }
+
+ static void destroy_impl(operation* op)
+ {
+ // Take ownership of the operation object.
+ typedef send_to_operation<ConstBufferSequence, Handler> op_type;
+ op_type* handler_op(static_cast<op_type*>(op));
+ typedef handler_alloc_traits<Handler, op_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+
+ // 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(handler_op->handler_);
+ (void)handler;
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+ }
+
+ boost::asio::io_service::work work_;
+ ConstBufferSequence buffers_;
+ Handler handler_;
+ };
+
+ // Start an asynchronous send. The data being sent must be valid for the
+ // lifetime of the asynchronous operation.
+ template <typename ConstBufferSequence, typename Handler>
+ void async_send_to(implementation_type& impl,
+ const ConstBufferSequence& buffers, const endpoint_type& destination,
+ socket_base::message_flags flags, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ return;
+ }
+
+#if defined(BOOST_ASIO_ENABLE_CANCELIO)
+ // Update the ID of the thread from which cancellation is safe.
+ 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);
+#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef send_to_operation<ConstBufferSequence, Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ handler_ptr<alloc_traits> ptr(raw_ptr, iocp_service_, buffers, handler);
+
+ // Copy buffers into WSABUF array.
+ ::WSABUF bufs[max_buffers];
+ typename ConstBufferSequence::const_iterator iter = buffers.begin();
+ typename ConstBufferSequence::const_iterator end = buffers.end();
+ DWORD i = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::const_buffer buffer(*iter);
+ bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));
+ bufs[i].buf = const_cast<char*>(
+ boost::asio::buffer_cast<const char*>(buffer));
+ }
+
+ // Send the data.
+ DWORD bytes_transferred = 0;
+ int result = ::WSASendTo(impl.socket_, bufs, i, &bytes_transferred, flags,
+ destination.data(), static_cast<int>(destination.size()), ptr.get(), 0);
+ DWORD last_error = ::WSAGetLastError();
+
+ // Check if the operation completed immediately.
+ if (result != 0 && last_error != WSA_IO_PENDING)
+ {
+ boost::asio::io_service::work work(this->get_io_service());
+ ptr.reset();
+ boost::system::error_code ec(last_error,
+ boost::asio::error::get_system_category());
+ iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
+ }
+ else
+ {
+ ptr.release();
+ }
+ }
+
+ // Start an asynchronous wait until data can be sent without blocking.
+ template <typename Handler>
+ void async_send_to(implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, const endpoint_type&, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ }
+ else
+ {
+ // Check if the reactor was already obtained from the io_service.
+ reactor_type* reactor = static_cast<reactor_type*>(
+ interlocked_compare_exchange_pointer(
+ reinterpret_cast<void**>(&reactor_), 0, 0));
+ if (!reactor)
+ {
+ reactor = &(boost::asio::use_service<reactor_type>(
+ this->get_io_service()));
+ interlocked_exchange_pointer(
+ reinterpret_cast<void**>(&reactor_), reactor);
+ }
+
+ reactor->start_write_op(impl.socket_, impl.reactor_data_,
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
+ false);
+ }
+ }
+
+ // Receive some data from the peer. Returns the number of bytes received.
+ template <typename MutableBufferSequence>
+ size_t receive(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Copy buffers into WSABUF array.
+ ::WSABUF bufs[max_buffers];
+ typename MutableBufferSequence::const_iterator iter = buffers.begin();
+ typename MutableBufferSequence::const_iterator end = buffers.end();
+ DWORD i = 0;
+ size_t total_buffer_size = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::mutable_buffer buffer(*iter);
+ bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));
+ bufs[i].buf = boost::asio::buffer_cast<char*>(buffer);
+ total_buffer_size += boost::asio::buffer_size(buffer);
+ }
+
+ // A request to receive 0 bytes on a stream socket is a no-op.
+ if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ // Receive some data.
+ DWORD bytes_transferred = 0;
+ DWORD recv_flags = flags;
+ int result = ::WSARecv(impl.socket_, bufs, i,
+ &bytes_transferred, &recv_flags, 0, 0);
+ if (result != 0)
+ {
+ DWORD last_error = ::WSAGetLastError();
+ if (last_error == ERROR_NETNAME_DELETED)
+ last_error = WSAECONNRESET;
+ else if (last_error == ERROR_PORT_UNREACHABLE)
+ last_error = WSAECONNREFUSED;
+ ec = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+ return 0;
+ }
+ if (bytes_transferred == 0 && impl.protocol_.type() == SOCK_STREAM)
+ {
+ ec = boost::asio::error::eof;
+ return 0;
+ }
+
+ ec = boost::system::error_code();
+ return bytes_transferred;
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive(implementation_type& impl, const null_buffers&,
+ socket_base::message_flags, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, ec);
+
+ return 0;
+ }
+
+ template <typename MutableBufferSequence, typename Handler>
+ class receive_operation
+ : public operation
+ {
+ public:
+ receive_operation(int protocol_type, win_iocp_io_service& io_service,
+ weak_cancel_token_type cancel_token,
+ const MutableBufferSequence& buffers, Handler handler)
+ : operation(io_service,
+ &receive_operation<
+ MutableBufferSequence, Handler>::do_completion_impl,
+ &receive_operation<
+ MutableBufferSequence, Handler>::destroy_impl),
+ protocol_type_(protocol_type),
+ work_(io_service.get_io_service()),
+ cancel_token_(cancel_token),
+ buffers_(buffers),
+ handler_(handler)
+ {
+ }
+
+ private:
+ static void do_completion_impl(operation* op,
+ DWORD last_error, size_t bytes_transferred)
+ {
+ // Take ownership of the operation object.
+ typedef receive_operation<MutableBufferSequence, Handler> op_type;
+ op_type* handler_op(static_cast<op_type*>(op));
+ typedef handler_alloc_traits<Handler, op_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ // Check whether buffers are still valid.
+ typename MutableBufferSequence::const_iterator iter
+ = handler_op->buffers_.begin();
+ typename MutableBufferSequence::const_iterator end
+ = handler_op->buffers_.end();
+ while (iter != end)
+ {
+ boost::asio::mutable_buffer buffer(*iter);
+ boost::asio::buffer_cast<char*>(buffer);
+ ++iter;
+ }
+#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+
+ // Map non-portable errors to their portable counterparts.
+ boost::system::error_code ec(last_error,
+ boost::asio::error::get_system_category());
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ {
+ if (handler_op->cancel_token_.expired())
+ ec = boost::asio::error::operation_aborted;
+ else
+ ec = boost::asio::error::connection_reset;
+ }
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = boost::asio::error::connection_refused;
+ }
+
+ // Check for connection closed.
+ else if (!ec && bytes_transferred == 0
+ && handler_op->protocol_type_ == SOCK_STREAM
+ && !boost::is_same<MutableBufferSequence, null_buffers>::value)
+ {
+ ec = boost::asio::error::eof;
+ }
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made.
+ Handler handler(handler_op->handler_);
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+
+ // Call the handler.
+ boost_asio_handler_invoke_helpers::invoke(
+ detail::bind_handler(handler, ec, bytes_transferred), &handler);
+ }
+
+ static void destroy_impl(operation* op)
+ {
+ // Take ownership of the operation object.
+ typedef receive_operation<MutableBufferSequence, Handler> op_type;
+ op_type* handler_op(static_cast<op_type*>(op));
+ typedef handler_alloc_traits<Handler, op_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+
+ // 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(handler_op->handler_);
+ (void)handler;
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+ }
+
+ int protocol_type_;
+ boost::asio::io_service::work work_;
+ weak_cancel_token_type cancel_token_;
+ MutableBufferSequence buffers_;
+ Handler handler_;
+ };
+
+ // Start an asynchronous receive. The buffer for the data being received
+ // must be valid for the lifetime of the asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ return;
+ }
+
+#if defined(BOOST_ASIO_ENABLE_CANCELIO)
+ // Update the ID of the thread from which cancellation is safe.
+ 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);
+#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef receive_operation<MutableBufferSequence, Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ int protocol_type = impl.protocol_.type();
+ handler_ptr<alloc_traits> ptr(raw_ptr, protocol_type,
+ iocp_service_, impl.cancel_token_, buffers, handler);
+
+ // Copy buffers into WSABUF array.
+ ::WSABUF bufs[max_buffers];
+ typename MutableBufferSequence::const_iterator iter = buffers.begin();
+ typename MutableBufferSequence::const_iterator end = buffers.end();
+ DWORD i = 0;
+ size_t total_buffer_size = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::mutable_buffer buffer(*iter);
+ bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));
+ bufs[i].buf = boost::asio::buffer_cast<char*>(buffer);
+ total_buffer_size += boost::asio::buffer_size(buffer);
+ }
+
+ // A request to receive 0 bytes on a stream socket is a no-op.
+ if (impl.protocol_.type() == SOCK_STREAM && total_buffer_size == 0)
+ {
+ boost::asio::io_service::work work(this->get_io_service());
+ ptr.reset();
+ boost::system::error_code error;
+ iocp_service_.post(bind_handler(handler, error, 0));
+ return;
+ }
+
+ // Receive some data.
+ DWORD bytes_transferred = 0;
+ DWORD recv_flags = flags;
+ int result = ::WSARecv(impl.socket_, bufs, i,
+ &bytes_transferred, &recv_flags, ptr.get(), 0);
+ DWORD last_error = ::WSAGetLastError();
+ if (result != 0 && last_error != WSA_IO_PENDING)
+ {
+ boost::asio::io_service::work work(this->get_io_service());
+ ptr.reset();
+ boost::system::error_code ec(last_error,
+ boost::asio::error::get_system_category());
+ iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
+ }
+ else
+ {
+ ptr.release();
+ }
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler>
+ void async_receive(implementation_type& impl, const null_buffers& buffers,
+ socket_base::message_flags flags, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ }
+ else if (impl.protocol_.type() == SOCK_STREAM)
+ {
+ // For stream sockets on Windows, we may issue a 0-byte overlapped
+ // WSARecv to wait until there is data available on the socket.
+
+#if defined(BOOST_ASIO_ENABLE_CANCELIO)
+ // Update the ID of the thread from which cancellation is safe.
+ 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);
+#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef receive_operation<null_buffers, Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ int protocol_type = impl.protocol_.type();
+ handler_ptr<alloc_traits> ptr(raw_ptr, protocol_type,
+ iocp_service_, impl.cancel_token_, buffers, handler);
+
+ // Issue a receive operation with an empty buffer.
+ ::WSABUF buf = { 0, 0 };
+ DWORD bytes_transferred = 0;
+ DWORD recv_flags = flags;
+ int result = ::WSARecv(impl.socket_, &buf, 1,
+ &bytes_transferred, &recv_flags, ptr.get(), 0);
+ DWORD last_error = ::WSAGetLastError();
+ if (result != 0 && last_error != WSA_IO_PENDING)
+ {
+ boost::asio::io_service::work work(this->get_io_service());
+ ptr.reset();
+ boost::system::error_code ec(last_error,
+ boost::asio::error::get_system_category());
+ iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
+ }
+ else
+ {
+ ptr.release();
+ }
+ }
+ else
+ {
+ // Check if the reactor was already obtained from the io_service.
+ reactor_type* reactor = static_cast<reactor_type*>(
+ interlocked_compare_exchange_pointer(
+ reinterpret_cast<void**>(&reactor_), 0, 0));
+ if (!reactor)
+ {
+ reactor = &(boost::asio::use_service<reactor_type>(
+ this->get_io_service()));
+ interlocked_exchange_pointer(
+ reinterpret_cast<void**>(&reactor_), reactor);
+ }
+
+ if (flags & socket_base::message_out_of_band)
+ {
+ reactor->start_except_op(impl.socket_, impl.reactor_data_,
+ null_buffers_operation<Handler>(this->get_io_service(), handler));
+ }
+ else
+ {
+ reactor->start_read_op(impl.socket_, impl.reactor_data_,
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
+ false);
+ }
+ }
+ }
+
+ // Receive a datagram with the endpoint of the sender. Returns the number of
+ // bytes received.
+ template <typename MutableBufferSequence>
+ size_t receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ endpoint_type& sender_endpoint, socket_base::message_flags flags,
+ boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Copy buffers into WSABUF array.
+ ::WSABUF bufs[max_buffers];
+ typename MutableBufferSequence::const_iterator iter = buffers.begin();
+ typename MutableBufferSequence::const_iterator end = buffers.end();
+ DWORD i = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::mutable_buffer buffer(*iter);
+ bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));
+ bufs[i].buf = boost::asio::buffer_cast<char*>(buffer);
+ }
+
+ // Receive some data.
+ DWORD bytes_transferred = 0;
+ DWORD recv_flags = flags;
+ int endpoint_size = static_cast<int>(sender_endpoint.capacity());
+ int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred,
+ &recv_flags, sender_endpoint.data(), &endpoint_size, 0, 0);
+ if (result != 0)
+ {
+ DWORD last_error = ::WSAGetLastError();
+ if (last_error == ERROR_PORT_UNREACHABLE)
+ last_error = WSAECONNREFUSED;
+ ec = boost::system::error_code(last_error,
+ boost::asio::error::get_system_category());
+ return 0;
+ }
+ if (bytes_transferred == 0 && impl.protocol_.type() == SOCK_STREAM)
+ {
+ ec = boost::asio::error::eof;
+ return 0;
+ }
+
+ sender_endpoint.resize(static_cast<std::size_t>(endpoint_size));
+
+ ec = boost::system::error_code();
+ return bytes_transferred;
+ }
+
+ // Wait until data can be received without blocking.
+ size_t receive_from(implementation_type& impl,
+ const null_buffers&, endpoint_type& sender_endpoint,
+ socket_base::message_flags, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return 0;
+ }
+
+ // Wait for socket to become ready.
+ socket_ops::poll_read(impl.socket_, ec);
+
+ // Reset endpoint since it can be given no sensible value at this time.
+ sender_endpoint = endpoint_type();
+
+ return 0;
+ }
+
+ template <typename MutableBufferSequence, typename Handler>
+ class receive_from_operation
+ : public operation
+ {
+ public:
+ receive_from_operation(int protocol_type, win_iocp_io_service& io_service,
+ endpoint_type& endpoint, const MutableBufferSequence& buffers,
+ Handler handler)
+ : operation(io_service,
+ &receive_from_operation<
+ MutableBufferSequence, Handler>::do_completion_impl,
+ &receive_from_operation<
+ MutableBufferSequence, Handler>::destroy_impl),
+ protocol_type_(protocol_type),
+ endpoint_(endpoint),
+ endpoint_size_(static_cast<int>(endpoint.capacity())),
+ work_(io_service.get_io_service()),
+ buffers_(buffers),
+ handler_(handler)
+ {
+ }
+
+ int& endpoint_size()
+ {
+ return endpoint_size_;
+ }
+
+ private:
+ static void do_completion_impl(operation* op,
+ DWORD last_error, size_t bytes_transferred)
+ {
+ // Take ownership of the operation object.
+ typedef receive_from_operation<MutableBufferSequence, Handler> op_type;
+ op_type* handler_op(static_cast<op_type*>(op));
+ typedef handler_alloc_traits<Handler, op_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ // Check whether buffers are still valid.
+ typename MutableBufferSequence::const_iterator iter
+ = handler_op->buffers_.begin();
+ typename MutableBufferSequence::const_iterator end
+ = handler_op->buffers_.end();
+ while (iter != end)
+ {
+ boost::asio::mutable_buffer buffer(*iter);
+ boost::asio::buffer_cast<char*>(buffer);
+ ++iter;
+ }
+#endif // defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+
+ // Map non-portable errors to their portable counterparts.
+ boost::system::error_code ec(last_error,
+ boost::asio::error::get_system_category());
+ if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = boost::asio::error::connection_refused;
+ }
+
+ // Check for connection closed.
+ if (!ec && bytes_transferred == 0
+ && handler_op->protocol_type_ == SOCK_STREAM)
+ {
+ ec = boost::asio::error::eof;
+ }
+
+ // Record the size of the endpoint returned by the operation.
+ handler_op->endpoint_.resize(handler_op->endpoint_size_);
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made.
+ Handler handler(handler_op->handler_);
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+
+ // Call the handler.
+ boost_asio_handler_invoke_helpers::invoke(
+ detail::bind_handler(handler, ec, bytes_transferred), &handler);
+ }
+
+ static void destroy_impl(operation* op)
+ {
+ // Take ownership of the operation object.
+ typedef receive_from_operation<MutableBufferSequence, Handler> op_type;
+ op_type* handler_op(static_cast<op_type*>(op));
+ typedef handler_alloc_traits<Handler, op_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+
+ // 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(handler_op->handler_);
+ (void)handler;
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+ }
+
+ int protocol_type_;
+ endpoint_type& endpoint_;
+ int endpoint_size_;
+ boost::asio::io_service::work work_;
+ MutableBufferSequence buffers_;
+ Handler handler_;
+ };
+
+ // Start an asynchronous receive. The buffer for the data being received and
+ // the sender_endpoint object must both be valid for the lifetime of the
+ // asynchronous operation.
+ template <typename MutableBufferSequence, typename Handler>
+ void async_receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers, endpoint_type& sender_endp,
+ socket_base::message_flags flags, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ return;
+ }
+
+#if defined(BOOST_ASIO_ENABLE_CANCELIO)
+ // Update the ID of the thread from which cancellation is safe.
+ 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);
+#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef receive_from_operation<MutableBufferSequence, Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ int protocol_type = impl.protocol_.type();
+ handler_ptr<alloc_traits> ptr(raw_ptr, protocol_type,
+ iocp_service_, sender_endp, buffers, handler);
+
+ // Copy buffers into WSABUF array.
+ ::WSABUF bufs[max_buffers];
+ typename MutableBufferSequence::const_iterator iter = buffers.begin();
+ typename MutableBufferSequence::const_iterator end = buffers.end();
+ DWORD i = 0;
+ for (; iter != end && i < max_buffers; ++iter, ++i)
+ {
+ boost::asio::mutable_buffer buffer(*iter);
+ bufs[i].len = static_cast<u_long>(boost::asio::buffer_size(buffer));
+ bufs[i].buf = boost::asio::buffer_cast<char*>(buffer);
+ }
+
+ // Receive some data.
+ DWORD bytes_transferred = 0;
+ DWORD recv_flags = flags;
+ int result = ::WSARecvFrom(impl.socket_, bufs, i, &bytes_transferred,
+ &recv_flags, sender_endp.data(), &ptr.get()->endpoint_size(),
+ ptr.get(), 0);
+ DWORD last_error = ::WSAGetLastError();
+ if (result != 0 && last_error != WSA_IO_PENDING)
+ {
+ boost::asio::io_service::work work(this->get_io_service());
+ ptr.reset();
+ boost::system::error_code ec(last_error,
+ boost::asio::error::get_system_category());
+ iocp_service_.post(bind_handler(handler, ec, bytes_transferred));
+ }
+ else
+ {
+ ptr.release();
+ }
+ }
+
+ // Wait until data can be received without blocking.
+ template <typename Handler>
+ void async_receive_from(implementation_type& impl,
+ const null_buffers&, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor, 0));
+ }
+ else
+ {
+ // Check if the reactor was already obtained from the io_service.
+ reactor_type* reactor = static_cast<reactor_type*>(
+ interlocked_compare_exchange_pointer(
+ reinterpret_cast<void**>(&reactor_), 0, 0));
+ if (!reactor)
+ {
+ reactor = &(boost::asio::use_service<reactor_type>(
+ this->get_io_service()));
+ interlocked_exchange_pointer(
+ reinterpret_cast<void**>(&reactor_), reactor);
+ }
+
+ // Reset endpoint since it can be given no sensible value at this time.
+ sender_endpoint = endpoint_type();
+
+ if (flags & socket_base::message_out_of_band)
+ {
+ reactor->start_except_op(impl.socket_, impl.reactor_data_,
+ null_buffers_operation<Handler>(this->get_io_service(), handler));
+ }
+ else
+ {
+ reactor->start_read_op(impl.socket_, impl.reactor_data_,
+ null_buffers_operation<Handler>(this->get_io_service(), handler),
+ false);
+ }
+ }
+ }
+
+ // Accept a new connection.
+ template <typename Socket>
+ boost::system::error_code accept(implementation_type& impl, Socket& peer,
+ endpoint_type* peer_endpoint, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ // We cannot accept a socket that is already open.
+ if (peer.is_open())
+ {
+ ec = boost::asio::error::already_open;
+ return ec;
+ }
+
+ for (;;)
+ {
+ socket_holder new_socket;
+ std::size_t addr_len = 0;
+ if (peer_endpoint)
+ {
+ addr_len = peer_endpoint->capacity();
+ new_socket.reset(socket_ops::accept(impl.socket_,
+ peer_endpoint->data(), &addr_len, ec));
+ }
+ else
+ {
+ new_socket.reset(socket_ops::accept(impl.socket_, 0, 0, ec));
+ }
+
+ if (ec)
+ {
+ if (ec == boost::asio::error::connection_aborted
+ && !(impl.flags_ & implementation_type::enable_connection_aborted))
+ {
+ // Retry accept operation.
+ continue;
+ }
+ else
+ {
+ return ec;
+ }
+ }
+
+ if (peer_endpoint)
+ peer_endpoint->resize(addr_len);
+
+ peer.assign(impl.protocol_, new_socket.get(), ec);
+ if (!ec)
+ new_socket.release();
+ return ec;
+ }
+ }
+
+ template <typename Socket, typename Handler>
+ class accept_operation
+ : public operation
+ {
+ public:
+ accept_operation(win_iocp_io_service& io_service,
+ socket_type socket, socket_type new_socket, Socket& peer,
+ const protocol_type& protocol, endpoint_type* peer_endpoint,
+ bool enable_connection_aborted, Handler handler)
+ : operation(io_service,
+ &accept_operation<Socket, Handler>::do_completion_impl,
+ &accept_operation<Socket, Handler>::destroy_impl),
+ io_service_(io_service),
+ socket_(socket),
+ new_socket_(new_socket),
+ peer_(peer),
+ protocol_(protocol),
+ peer_endpoint_(peer_endpoint),
+ work_(io_service.get_io_service()),
+ enable_connection_aborted_(enable_connection_aborted),
+ handler_(handler)
+ {
+ }
+
+ socket_type new_socket()
+ {
+ return new_socket_.get();
+ }
+
+ void* output_buffer()
+ {
+ return output_buffer_;
+ }
+
+ DWORD address_length()
+ {
+ return sizeof(sockaddr_storage_type) + 16;
+ }
+
+ private:
+ static void do_completion_impl(operation* op, DWORD last_error, size_t)
+ {
+ // Take ownership of the operation object.
+ typedef accept_operation<Socket, Handler> op_type;
+ op_type* handler_op(static_cast<op_type*>(op));
+ typedef handler_alloc_traits<Handler, op_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+
+ // Map Windows error ERROR_NETNAME_DELETED to connection_aborted.
+ if (last_error == ERROR_NETNAME_DELETED)
+ {
+ last_error = WSAECONNABORTED;
+ }
+
+ // Restart the accept operation if we got the connection_aborted error
+ // and the enable_connection_aborted socket option is not set.
+ if (last_error == WSAECONNABORTED
+ && !ptr.get()->enable_connection_aborted_)
+ {
+ // Reset OVERLAPPED structure.
+ ptr.get()->Internal = 0;
+ ptr.get()->InternalHigh = 0;
+ ptr.get()->Offset = 0;
+ ptr.get()->OffsetHigh = 0;
+ ptr.get()->hEvent = 0;
+
+ // Create a new socket for the next connection, since the AcceptEx call
+ // fails with WSAEINVAL if we try to reuse the same socket.
+ boost::system::error_code ec;
+ ptr.get()->new_socket_.reset();
+ ptr.get()->new_socket_.reset(socket_ops::socket(
+ ptr.get()->protocol_.family(), ptr.get()->protocol_.type(),
+ ptr.get()->protocol_.protocol(), ec));
+ if (ptr.get()->new_socket() != invalid_socket)
+ {
+ // Accept a connection.
+ DWORD bytes_read = 0;
+ BOOL result = ::AcceptEx(ptr.get()->socket_, ptr.get()->new_socket(),
+ ptr.get()->output_buffer(), 0, ptr.get()->address_length(),
+ ptr.get()->address_length(), &bytes_read, ptr.get());
+ last_error = ::WSAGetLastError();
+
+ // Check if the operation completed immediately.
+ if (!result && last_error != WSA_IO_PENDING)
+ {
+ if (last_error == ERROR_NETNAME_DELETED
+ || last_error == WSAECONNABORTED)
+ {
+ // Post this handler so that operation will be restarted again.
+ ptr.get()->io_service_.post_completion(ptr.get(), last_error, 0);
+ ptr.release();
+ return;
+ }
+ else
+ {
+ // Operation already complete. Continue with rest of this handler.
+ }
+ }
+ else
+ {
+ // Asynchronous operation has been successfully restarted.
+ ptr.release();
+ return;
+ }
+ }
+ }
+
+ // Get the address of the peer.
+ endpoint_type peer_endpoint;
+ if (last_error == 0)
+ {
+ LPSOCKADDR local_addr = 0;
+ int local_addr_length = 0;
+ LPSOCKADDR remote_addr = 0;
+ int remote_addr_length = 0;
+ GetAcceptExSockaddrs(handler_op->output_buffer(), 0,
+ handler_op->address_length(), handler_op->address_length(),
+ &local_addr, &local_addr_length, &remote_addr, &remote_addr_length);
+ if (static_cast<std::size_t>(remote_addr_length)
+ > peer_endpoint.capacity())
+ {
+ last_error = WSAEINVAL;
+ }
+ else
+ {
+ using namespace std; // For memcpy.
+ memcpy(peer_endpoint.data(), remote_addr, remote_addr_length);
+ peer_endpoint.resize(static_cast<std::size_t>(remote_addr_length));
+ }
+ }
+
+ // Need to set the SO_UPDATE_ACCEPT_CONTEXT option so that getsockname
+ // and getpeername will work on the accepted socket.
+ if (last_error == 0)
+ {
+ SOCKET update_ctx_param = handler_op->socket_;
+ boost::system::error_code ec;
+ if (socket_ops::setsockopt(handler_op->new_socket_.get(),
+ SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
+ &update_ctx_param, sizeof(SOCKET), ec) != 0)
+ {
+ last_error = ec.value();
+ }
+ }
+
+ // If the socket was successfully accepted, transfer ownership of the
+ // socket to the peer object.
+ if (last_error == 0)
+ {
+ boost::system::error_code ec;
+ handler_op->peer_.assign(handler_op->protocol_,
+ native_type(handler_op->new_socket_.get(), peer_endpoint), ec);
+ if (ec)
+ last_error = ec.value();
+ else
+ handler_op->new_socket_.release();
+ }
+
+ // Pass endpoint back to caller.
+ if (handler_op->peer_endpoint_)
+ *handler_op->peer_endpoint_ = peer_endpoint;
+
+ // Make a copy of the handler so that the memory can be deallocated before
+ // the upcall is made.
+ Handler handler(handler_op->handler_);
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+
+ // Call the handler.
+ boost::system::error_code ec(last_error,
+ boost::asio::error::get_system_category());
+ boost_asio_handler_invoke_helpers::invoke(
+ detail::bind_handler(handler, ec), &handler);
+ }
+
+ static void destroy_impl(operation* op)
+ {
+ // Take ownership of the operation object.
+ typedef accept_operation<Socket, Handler> op_type;
+ op_type* handler_op(static_cast<op_type*>(op));
+ typedef handler_alloc_traits<Handler, op_type> alloc_traits;
+ handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
+
+ // 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(handler_op->handler_);
+ (void)handler;
+
+ // Free the memory associated with the handler.
+ ptr.reset();
+ }
+
+ win_iocp_io_service& io_service_;
+ socket_type socket_;
+ socket_holder new_socket_;
+ Socket& peer_;
+ protocol_type protocol_;
+ endpoint_type* peer_endpoint_;
+ boost::asio::io_service::work work_;
+ unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];
+ bool enable_connection_aborted_;
+ Handler handler_;
+ };
+
+ // Start an asynchronous accept. The peer and peer_endpoint objects
+ // must be valid until the accept's handler is invoked.
+ template <typename Socket, typename Handler>
+ void async_accept(implementation_type& impl, Socket& peer,
+ endpoint_type* peer_endpoint, Handler handler)
+ {
+ // Check whether acceptor has been initialised.
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor));
+ return;
+ }
+
+ // Check that peer socket has not already been opened.
+ if (peer.is_open())
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::already_open));
+ return;
+ }
+
+#if defined(BOOST_ASIO_ENABLE_CANCELIO)
+ // Update the ID of the thread from which cancellation is safe.
+ 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);
+#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
+
+ // Create a new socket for the connection.
+ boost::system::error_code ec;
+ socket_holder sock(socket_ops::socket(impl.protocol_.family(),
+ impl.protocol_.type(), impl.protocol_.protocol(), ec));
+ if (sock.get() == invalid_socket)
+ {
+ this->get_io_service().post(bind_handler(handler, ec));
+ return;
+ }
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef accept_operation<Socket, Handler> value_type;
+ typedef handler_alloc_traits<Handler, value_type> alloc_traits;
+ raw_handler_ptr<alloc_traits> raw_ptr(handler);
+ socket_type new_socket = sock.get();
+ bool enable_connection_aborted =
+ (impl.flags_ & implementation_type::enable_connection_aborted);
+ handler_ptr<alloc_traits> ptr(raw_ptr,
+ iocp_service_, impl.socket_, new_socket, peer, impl.protocol_,
+ peer_endpoint, enable_connection_aborted, handler);
+ sock.release();
+
+ // Accept a connection.
+ DWORD bytes_read = 0;
+ BOOL result = ::AcceptEx(impl.socket_, ptr.get()->new_socket(),
+ ptr.get()->output_buffer(), 0, ptr.get()->address_length(),
+ ptr.get()->address_length(), &bytes_read, ptr.get());
+ DWORD last_error = ::WSAGetLastError();
+
+ // Check if the operation completed immediately.
+ if (!result && last_error != WSA_IO_PENDING)
+ {
+ if (!enable_connection_aborted
+ && (last_error == ERROR_NETNAME_DELETED
+ || last_error == WSAECONNABORTED))
+ {
+ // Post handler so that operation will be restarted again. We do not
+ // perform the AcceptEx again here to avoid the possibility of starving
+ // other handlers.
+ iocp_service_.post_completion(ptr.get(), last_error, 0);
+ ptr.release();
+ }
+ else
+ {
+ boost::asio::io_service::work work(this->get_io_service());
+ ptr.reset();
+ boost::system::error_code ec(last_error,
+ boost::asio::error::get_system_category());
+ iocp_service_.post(bind_handler(handler, ec));
+ }
+ }
+ else
+ {
+ ptr.release();
+ }
+ }
+
+ // Connect the socket to the specified endpoint.
+ boost::system::error_code connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return ec;
+ }
+
+ // Perform the connect operation.
+ socket_ops::connect(impl.socket_,
+ peer_endpoint.data(), peer_endpoint.size(), ec);
+ return ec;
+ }
+
+ template <typename Handler>
+ class connect_operation
+ {
+ public:
+ connect_operation(socket_type socket, bool user_set_non_blocking,
+ boost::asio::io_service& io_service, Handler handler)
+ : socket_(socket),
+ user_set_non_blocking_(user_set_non_blocking),
+ io_service_(io_service),
+ work_(io_service),
+ handler_(handler)
+ {
+ }
+
+ bool perform(boost::system::error_code& ec,
+ std::size_t& bytes_transferred)
+ {
+ // Check whether the operation was successful.
+ if (ec)
+ return true;
+
+ // Get the error code from the connect operation.
+ int connect_error = 0;
+ size_t connect_error_len = sizeof(connect_error);
+ if (socket_ops::getsockopt(socket_, SOL_SOCKET, SO_ERROR,
+ &connect_error, &connect_error_len, ec) == socket_error_retval)
+ return true;
+
+ // If connection failed then post the handler with the error code.
+ if (connect_error)
+ {
+ ec = boost::system::error_code(connect_error,
+ boost::asio::error::get_system_category());
+ return true;
+ }
+
+ // Revert socket to blocking mode unless the user requested otherwise.
+ if (!user_set_non_blocking_)
+ {
+ ioctl_arg_type non_blocking = 0;
+ if (socket_ops::ioctl(socket_, FIONBIO, &non_blocking, ec))
+ return true;
+ }
+
+ // Post the result of the successful connection operation.
+ ec = boost::system::error_code();
+ return true;
+ }
+
+ void complete(const boost::system::error_code& ec, std::size_t)
+ {
+ io_service_.post(bind_handler(handler_, ec));
+ }
+
+ private:
+ socket_type socket_;
+ bool user_set_non_blocking_;
+ boost::asio::io_service& io_service_;
+ boost::asio::io_service::work work_;
+ Handler handler_;
+ };
+
+ // Start an asynchronous connect.
+ template <typename Handler>
+ void async_connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, Handler handler)
+ {
+ if (!is_open(impl))
+ {
+ this->get_io_service().post(bind_handler(handler,
+ boost::asio::error::bad_descriptor));
+ return;
+ }
+
+#if defined(BOOST_ASIO_ENABLE_CANCELIO)
+ // Update the ID of the thread from which cancellation is safe.
+ 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);
+#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
+
+ // Check if the reactor was already obtained from the io_service.
+ reactor_type* reactor = static_cast<reactor_type*>(
+ interlocked_compare_exchange_pointer(
+ reinterpret_cast<void**>(&reactor_), 0, 0));
+ if (!reactor)
+ {
+ reactor = &(boost::asio::use_service<reactor_type>(
+ this->get_io_service()));
+ interlocked_exchange_pointer(
+ reinterpret_cast<void**>(&reactor_), reactor);
+ }
+
+ // Mark the socket as non-blocking so that the connection will take place
+ // asynchronously.
+ ioctl_arg_type non_blocking = 1;
+ boost::system::error_code ec;
+ if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
+ {
+ this->get_io_service().post(bind_handler(handler, ec));
+ return;
+ }
+
+ // Start the connect operation.
+ if (socket_ops::connect(impl.socket_, peer_endpoint.data(),
+ peer_endpoint.size(), ec) == 0)
+ {
+ // Revert socket to blocking mode unless the user requested otherwise.
+ if (!(impl.flags_ & implementation_type::user_set_non_blocking))
+ {
+ non_blocking = 0;
+ socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec);
+ }
+
+ // The connect operation has finished successfully so we need to post the
+ // handler immediately.
+ this->get_io_service().post(bind_handler(handler, ec));
+ }
+ else if (ec == boost::asio::error::in_progress
+ || ec == boost::asio::error::would_block)
+ {
+ // The connection is happening in the background, and we need to wait
+ // until the socket becomes writeable.
+ boost::shared_ptr<bool> completed(new bool(false));
+ reactor->start_connect_op(impl.socket_, impl.reactor_data_,
+ connect_operation<Handler>(
+ impl.socket_,
+ (impl.flags_ & implementation_type::user_set_non_blocking) != 0,
+ this->get_io_service(), handler));
+ }
+ else
+ {
+ // Revert socket to blocking mode unless the user requested otherwise.
+ if (!(impl.flags_ & implementation_type::user_set_non_blocking))
+ {
+ non_blocking = 0;
+ boost::system::error_code ignored_ec;
+ socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec);
+ }
+
+ // The connect operation has failed, so post the handler immediately.
+ this->get_io_service().post(bind_handler(handler, ec));
+ }
+ }
+
+private:
+ // Helper function to close a socket when the associated object is being
+ // destroyed.
+ void close_for_destruction(implementation_type& impl)
+ {
+ if (is_open(impl))
+ {
+ // Check if the reactor was created, in which case we need to close the
+ // socket on the reactor as well to cancel any operations that might be
+ // running there.
+ reactor_type* reactor = static_cast<reactor_type*>(
+ interlocked_compare_exchange_pointer(
+ reinterpret_cast<void**>(&reactor_), 0, 0));
+ if (reactor)
+ reactor->close_descriptor(impl.socket_, impl.reactor_data_);
+
+ // The socket destructor must not block. If the user has changed the
+ // linger option to block in the foreground, we will change it back to the
+ // default so that the closure is performed in the background.
+ if (impl.flags_ & implementation_type::close_might_block)
+ {
+ ::linger opt;
+ opt.l_onoff = 0;
+ opt.l_linger = 0;
+ boost::system::error_code ignored_ec;
+ socket_ops::setsockopt(impl.socket_,
+ SOL_SOCKET, SO_LINGER, &opt, sizeof(opt), ignored_ec);
+ }
+
+ boost::system::error_code ignored_ec;
+ socket_ops::close(impl.socket_, ignored_ec);
+ impl.socket_ = invalid_socket;
+ impl.flags_ = 0;
+ impl.cancel_token_.reset();
+#if defined(BOOST_ASIO_ENABLE_CANCELIO)
+ impl.safe_cancellation_thread_id_ = 0;
+#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
+ }
+ }
+
+ // Helper function to emulate InterlockedCompareExchangePointer functionality
+ // for:
+ // - very old Platform SDKs; and
+ // - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
+ void* interlocked_compare_exchange_pointer(void** dest, void* exch, void* cmp)
+ {
+#if defined(_M_IX86)
+ return reinterpret_cast<void*>(InterlockedCompareExchange(
+ reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(exch),
+ reinterpret_cast<LONG>(cmp)));
+#else
+ return InterlockedCompareExchangePointer(dest, exch, cmp);
+#endif
+ }
+
+ // Helper function to emulate InterlockedExchangePointer functionality for:
+ // - very old Platform SDKs; and
+ // - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
+ void* interlocked_exchange_pointer(void** dest, void* val)
+ {
+#if defined(_M_IX86)
+ return reinterpret_cast<void*>(InterlockedExchange(
+ reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(val)));
+#else
+ return InterlockedExchangePointer(dest, val);
+#endif
+ }
+
+ // The IOCP service used for running asynchronous operations and dispatching
+ // handlers.
+ win_iocp_io_service& iocp_service_;
+
+ // The reactor used for performing connect operations. This object is created
+ // only if needed.
+ reactor_type* reactor_;
+
+ // Mutex to protect access to the linked list of implementations.
+ boost::asio::detail::mutex mutex_;
+
+ // The head of a linked list of all implementations.
+ implementation_type* impl_list_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/win_mutex.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/win_mutex.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,151 @@
+//
+// win_mutex.hpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_WIN_MUTEX_HPP
+#define BOOST_ASIO_DETAIL_WIN_MUTEX_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_WINDOWS)
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/scoped_lock.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class win_mutex
+ : private noncopyable
+{
+public:
+ typedef boost::asio::detail::scoped_lock<win_mutex> scoped_lock;
+
+ // Constructor.
+ win_mutex()
+ {
+ int error = do_init();
+ if (error != 0)
+ {
+ boost::system::system_error e(
+ boost::system::error_code(error,
+ boost::asio::error::get_system_category()),
+ "mutex");
+ boost::throw_exception(e);
+ }
+ }
+
+ // Destructor.
+ ~win_mutex()
+ {
+ ::DeleteCriticalSection(&crit_section_);
+ }
+
+ // Lock the mutex.
+ void lock()
+ {
+ int error = do_lock();
+ if (error != 0)
+ {
+ boost::system::system_error e(
+ boost::system::error_code(error,
+ boost::asio::error::get_system_category()),
+ "mutex");
+ boost::throw_exception(e);
+ }
+ }
+
+ // Unlock the mutex.
+ void unlock()
+ {
+ ::LeaveCriticalSection(&crit_section_);
+ }
+
+private:
+ // Initialisation must be performed in a separate function to the constructor
+ // since the compiler does not support the use of structured exceptions and
+ // C++ exceptions in the same function.
+ int do_init()
+ {
+#if defined(__MINGW32__)
+ // Not sure if MinGW supports structured exception handling, so for now
+ // we'll just call the Windows API and hope.
+ ::InitializeCriticalSection(&crit_section_);
+ return 0;
+#else
+ __try
+ {
+ ::InitializeCriticalSection(&crit_section_);
+ }
+ __except(GetExceptionCode() == STATUS_NO_MEMORY
+ ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ return ERROR_OUTOFMEMORY;
+ }
+
+ return 0;
+#endif
+ }
+
+ // Locking must be performed in a separate function to lock() since the
+ // compiler does not support the use of structured exceptions and C++
+ // exceptions in the same function.
+ int do_lock()
+ {
+#if defined(__MINGW32__)
+ // Not sure if MinGW supports structured exception handling, so for now
+ // we'll just call the Windows API and hope.
+ ::EnterCriticalSection(&crit_section_);
+ return 0;
+#else
+ __try
+ {
+ ::EnterCriticalSection(&crit_section_);
+ }
+ __except(GetExceptionCode() == STATUS_INVALID_HANDLE
+ || GetExceptionCode() == STATUS_NO_MEMORY
+ ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
+ {
+ if (GetExceptionCode() == STATUS_NO_MEMORY)
+ return ERROR_OUTOFMEMORY;
+ return ERROR_INVALID_HANDLE;
+ }
+
+ return 0;
+#endif
+ }
+
+ ::CRITICAL_SECTION crit_section_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_WINDOWS)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_WIN_MUTEX_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/win_signal_blocker.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/win_signal_blocker.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,69 @@
+//
+// win_signal_blocker.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_WIN_SIGNAL_BLOCKER_HPP
+#define BOOST_ASIO_DETAIL_WIN_SIGNAL_BLOCKER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#include <boost/asio/detail/noncopyable.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class win_signal_blocker
+ : private noncopyable
+{
+public:
+ // Constructor blocks all signals for the calling thread.
+ win_signal_blocker()
+ {
+ // No-op.
+ }
+
+ // Destructor restores the previous signal mask.
+ ~win_signal_blocker()
+ {
+ // No-op.
+ }
+
+ // Block all signals for the calling thread.
+ void block()
+ {
+ // No-op.
+ }
+
+ // Restore the previous signal mask.
+ void unblock()
+ {
+ // No-op.
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_WIN_SIGNAL_BLOCKER_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/win_thread.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/win_thread.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,196 @@
+//
+// win_thread.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_WIN_THREAD_HPP
+#define BOOST_ASIO_DETAIL_WIN_THREAD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_WINDOWS) && !defined(UNDER_CE)
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/throw_exception.hpp>
+#include <memory>
+#include <process.h>
+#include <boost/asio/detail/pop_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+unsigned int __stdcall win_thread_function(void* arg);
+
+class win_thread
+ : private noncopyable
+{
+public:
+ // The purpose of the thread.
+ enum purpose { internal, external };
+
+ // Constructor.
+ template <typename Function>
+ win_thread(Function f, purpose p = internal)
+ : exit_event_(0)
+ {
+ std::auto_ptr<func_base> arg(new func<Function>(f));
+
+ ::HANDLE entry_event = 0;
+ if (p == internal)
+ {
+ arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0);
+ if (!entry_event)
+ {
+ DWORD last_error = ::GetLastError();
+ boost::system::system_error e(
+ boost::system::error_code(last_error,
+ boost::asio::error::get_system_category()),
+ "thread.entry_event");
+ boost::throw_exception(e);
+ }
+
+ arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0);
+ if (!exit_event_)
+ {
+ DWORD last_error = ::GetLastError();
+ ::CloseHandle(entry_event);
+ boost::system::system_error e(
+ boost::system::error_code(last_error,
+ boost::asio::error::get_system_category()),
+ "thread.exit_event");
+ boost::throw_exception(e);
+ }
+ }
+
+ unsigned int thread_id = 0;
+ thread_ = reinterpret_cast<HANDLE>(::_beginthreadex(0, 0,
+ win_thread_function, arg.get(), 0, &thread_id));
+ if (!thread_)
+ {
+ DWORD last_error = ::GetLastError();
+ if (entry_event)
+ ::CloseHandle(entry_event);
+ if (exit_event_)
+ ::CloseHandle(exit_event_);
+ boost::system::system_error e(
+ boost::system::error_code(last_error,
+ boost::asio::error::get_system_category()),
+ "thread");
+ boost::throw_exception(e);
+ }
+ arg.release();
+
+ if (entry_event)
+ {
+ ::WaitForSingleObject(entry_event, INFINITE);
+ ::CloseHandle(entry_event);
+ }
+ }
+
+ // Destructor.
+ ~win_thread()
+ {
+ ::CloseHandle(thread_);
+
+ // The exit_event_ handle is deliberately allowed to leak here since it
+ // is an error for the owner of an internal thread not to join() it.
+ }
+
+ // Wait for the thread to exit.
+ void join()
+ {
+ if (exit_event_)
+ {
+ ::WaitForSingleObject(exit_event_, INFINITE);
+ ::CloseHandle(exit_event_);
+ ::TerminateThread(thread_, 0);
+ }
+ else
+ {
+ ::WaitForSingleObject(thread_, INFINITE);
+ }
+ }
+
+private:
+ friend unsigned int __stdcall win_thread_function(void* arg);
+
+ class func_base
+ {
+ public:
+ virtual ~func_base() {}
+ virtual void run() = 0;
+ ::HANDLE entry_event_;
+ ::HANDLE exit_event_;
+ };
+
+ template <typename Function>
+ class func
+ : public func_base
+ {
+ public:
+ func(Function f)
+ : f_(f)
+ {
+ }
+
+ virtual void run()
+ {
+ f_();
+ }
+
+ private:
+ Function f_;
+ };
+
+ ::HANDLE thread_;
+ ::HANDLE exit_event_;
+};
+
+inline unsigned int __stdcall win_thread_function(void* arg)
+{
+ std::auto_ptr<win_thread::func_base> func(
+ static_cast<win_thread::func_base*>(arg));
+
+ if (func->entry_event_)
+ ::SetEvent(func->entry_event_);
+
+ func->run();
+
+ if (HANDLE exit_event = func->exit_event_)
+ {
+ func.reset();
+ ::SetEvent(exit_event);
+ ::Sleep(INFINITE);
+ }
+
+ return 0;
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_WINDOWS) && !defined(UNDER_CE)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_WIN_THREAD_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/win_tss_ptr.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/win_tss_ptr.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,97 @@
+//
+// win_tss_ptr.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_WIN_TSS_PTR_HPP
+#define BOOST_ASIO_DETAIL_WIN_TSS_PTR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_WINDOWS)
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename T>
+class win_tss_ptr
+ : private noncopyable
+{
+public:
+#if defined(UNDER_CE)
+ enum { out_of_indexes = 0xFFFFFFFF };
+#else
+ enum { out_of_indexes = TLS_OUT_OF_INDEXES };
+#endif
+
+ // Constructor.
+ win_tss_ptr()
+ {
+ tss_key_ = ::TlsAlloc();
+ if (tss_key_ == out_of_indexes)
+ {
+ DWORD last_error = ::GetLastError();
+ boost::system::system_error e(
+ boost::system::error_code(last_error,
+ boost::asio::error::get_system_category()),
+ "tss");
+ boost::throw_exception(e);
+ }
+ }
+
+ // Destructor.
+ ~win_tss_ptr()
+ {
+ ::TlsFree(tss_key_);
+ }
+
+ // Get the value.
+ operator T*() const
+ {
+ return static_cast<T*>(::TlsGetValue(tss_key_));
+ }
+
+ // Set the value.
+ void operator=(T* value)
+ {
+ ::TlsSetValue(tss_key_, value);
+ }
+
+private:
+ // Thread-specific storage to allow unlocked access to determine whether a
+ // thread is a member of the pool.
+ DWORD tss_key_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_WINDOWS)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_WIN_TSS_PTR_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/wince_thread.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/wince_thread.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,129 @@
+//
+// wince_thread.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_WINCE_THREAD_HPP
+#define BOOST_ASIO_DETAIL_WINCE_THREAD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/throw_exception.hpp>
+#include <memory>
+#include <boost/asio/detail/pop_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+DWORD WINAPI wince_thread_function(LPVOID arg);
+
+class wince_thread
+ : private noncopyable
+{
+public:
+ // The purpose of the thread.
+ enum purpose { internal, external };
+
+ // Constructor.
+ template <typename Function>
+ wince_thread(Function f, purpose = internal)
+ {
+ std::auto_ptr<func_base> arg(new func<Function>(f));
+ DWORD thread_id = 0;
+ thread_ = ::CreateThread(0, 0, wince_thread_function,
+ arg.get(), 0, &thread_id);
+ if (!thread_)
+ {
+ DWORD last_error = ::GetLastError();
+ boost::system::system_error e(
+ boost::system::error_code(last_error,
+ boost::asio::error::get_system_category()),
+ "thread");
+ boost::throw_exception(e);
+ }
+ arg.release();
+ }
+
+ // Destructor.
+ ~wince_thread()
+ {
+ ::CloseHandle(thread_);
+ }
+
+ // Wait for the thread to exit.
+ void join()
+ {
+ ::WaitForSingleObject(thread_, INFINITE);
+ }
+
+private:
+ friend DWORD WINAPI wince_thread_function(LPVOID arg);
+
+ class func_base
+ {
+ public:
+ virtual ~func_base() {}
+ virtual void run() = 0;
+ };
+
+ template <typename Function>
+ class func
+ : public func_base
+ {
+ public:
+ func(Function f)
+ : f_(f)
+ {
+ }
+
+ virtual void run()
+ {
+ f_();
+ }
+
+ private:
+ Function f_;
+ };
+
+ ::HANDLE thread_;
+};
+
+inline DWORD WINAPI wince_thread_function(LPVOID arg)
+{
+ std::auto_ptr<wince_thread::func_base> func(
+ static_cast<wince_thread::func_base*>(arg));
+ func->run();
+ return 0;
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_WINDOWS) && defined(UNDER_CE)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_WINCE_THREAD_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/winsock_init.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/winsock_init.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,122 @@
+//
+// winsock_init.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_WINSOCK_INIT_HPP
+#define BOOST_ASIO_DETAIL_WINSOCK_INIT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <int Major = 2, int Minor = 0>
+class winsock_init
+ : private noncopyable
+{
+private:
+ // Structure to perform the actual initialisation.
+ struct do_init
+ {
+ do_init()
+ {
+ WSADATA wsa_data;
+ result_ = ::WSAStartup(MAKEWORD(Major, Minor), &wsa_data);
+ }
+
+ ~do_init()
+ {
+ ::WSACleanup();
+ }
+
+ int result() const
+ {
+ return result_;
+ }
+
+ // Helper function to manage a do_init singleton. The static instance of the
+ // winsock_init object ensures that this function is always called before
+ // main, and therefore before any other threads can get started. The do_init
+ // instance must be static in this function to ensure that it gets
+ // initialised before any other global objects try to use it.
+ static boost::shared_ptr<do_init> instance()
+ {
+ static boost::shared_ptr<do_init> init(new do_init);
+ return init;
+ }
+
+ private:
+ int result_;
+ };
+
+public:
+ // Constructor.
+ winsock_init()
+ : ref_(do_init::instance())
+ {
+ // Check whether winsock was successfully initialised. This check is not
+ // performed for the global instance since there will be nobody around to
+ // catch the exception.
+ if (this != &instance_ && ref_->result() != 0)
+ {
+ boost::system::system_error e(
+ boost::system::error_code(ref_->result(),
+ boost::asio::error::get_system_category()),
+ "winsock");
+ boost::throw_exception(e);
+ }
+ }
+
+ // Destructor.
+ ~winsock_init()
+ {
+ }
+
+private:
+ // Instance to force initialisation of winsock at global scope.
+ static winsock_init instance_;
+
+ // Reference to singleton do_init object to ensure that winsock does not get
+ // cleaned up until the last user has finished with it.
+ boost::shared_ptr<do_init> ref_;
+};
+
+template <int Major, int Minor>
+winsock_init<Major, Minor> winsock_init<Major, Minor>::instance_;
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_WINSOCK_INIT_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/detail/wrapped_handler.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/detail/wrapped_handler.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,211 @@
+//
+// wrapped_handler.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_WRAPPED_HANDLER_HPP
+#define BOOST_ASIO_DETAIL_WRAPPED_HANDLER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/type_traits.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Dispatcher, typename Handler>
+class wrapped_handler
+{
+public:
+ typedef void result_type;
+
+ wrapped_handler(
+ typename boost::add_reference<Dispatcher>::type dispatcher,
+ Handler handler)
+ : dispatcher_(dispatcher),
+ handler_(handler)
+ {
+ }
+
+ void operator()()
+ {
+ dispatcher_.dispatch(handler_);
+ }
+
+ void operator()() const
+ {
+ dispatcher_.dispatch(handler_);
+ }
+
+ template <typename Arg1>
+ void operator()(const Arg1& arg1)
+ {
+ dispatcher_.dispatch(detail::bind_handler(handler_, arg1));
+ }
+
+ template <typename Arg1>
+ void operator()(const Arg1& arg1) const
+ {
+ dispatcher_.dispatch(detail::bind_handler(handler_, arg1));
+ }
+
+ template <typename Arg1, typename Arg2>
+ void operator()(const Arg1& arg1, const Arg2& arg2)
+ {
+ dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2));
+ }
+
+ template <typename Arg1, typename Arg2>
+ void operator()(const Arg1& arg1, const Arg2& arg2) const
+ {
+ dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2));
+ }
+
+ template <typename Arg1, typename Arg2, typename Arg3>
+ void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3)
+ {
+ dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2, arg3));
+ }
+
+ template <typename Arg1, typename Arg2, typename Arg3>
+ void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) const
+ {
+ dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2, arg3));
+ }
+
+ template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+ void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3,
+ const Arg4& arg4)
+ {
+ dispatcher_.dispatch(
+ detail::bind_handler(handler_, arg1, arg2, arg3, arg4));
+ }
+
+ template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+ void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3,
+ const Arg4& arg4) const
+ {
+ dispatcher_.dispatch(
+ detail::bind_handler(handler_, arg1, arg2, arg3, arg4));
+ }
+
+ template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
+ typename Arg5>
+ void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3,
+ const Arg4& arg4, const Arg5& arg5)
+ {
+ dispatcher_.dispatch(
+ detail::bind_handler(handler_, arg1, arg2, arg3, arg4, arg5));
+ }
+
+ template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
+ typename Arg5>
+ void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3,
+ const Arg4& arg4, const Arg5& arg5) const
+ {
+ dispatcher_.dispatch(
+ detail::bind_handler(handler_, arg1, arg2, arg3, arg4, arg5));
+ }
+
+//private:
+ Dispatcher dispatcher_;
+ Handler handler_;
+};
+
+template <typename Handler, typename Context>
+class rewrapped_handler
+{
+public:
+ explicit rewrapped_handler(const Handler& handler, const Context& context)
+ : handler_(handler),
+ context_(context)
+ {
+ }
+
+ void operator()()
+ {
+ handler_();
+ }
+
+ void operator()() const
+ {
+ handler_();
+ }
+
+//private:
+ Handler handler_;
+ Context context_;
+};
+
+template <typename Dispatcher, typename Handler>
+inline void* asio_handler_allocate(std::size_t size,
+ wrapped_handler<Dispatcher, Handler>* this_handler)
+{
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+}
+
+template <typename Dispatcher, typename Handler>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ wrapped_handler<Dispatcher, Handler>* this_handler)
+{
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+}
+
+template <typename Function, typename Dispatcher, typename Handler>
+inline void asio_handler_invoke(const Function& function,
+ wrapped_handler<Dispatcher, Handler>* this_handler)
+{
+ this_handler->dispatcher_.dispatch(
+ rewrapped_handler<Function, Handler>(
+ function, this_handler->handler_));
+}
+
+template <typename Handler, typename Context>
+inline void* asio_handler_allocate(std::size_t size,
+ rewrapped_handler<Handler, Context>* this_handler)
+{
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->context_);
+}
+
+template <typename Handler, typename Context>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ rewrapped_handler<Handler, Context>* this_handler)
+{
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->context_);
+}
+
+template <typename Function, typename Handler, typename Context>
+inline void asio_handler_invoke(const Function& function,
+ rewrapped_handler<Handler, Context>* this_handler)
+{
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->context_);
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_WRAPPED_HANDLER_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/error.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/error.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,442 @@
+//
+// error.hpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_ERROR_HPP
+#define BOOST_ASIO_ERROR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/cerrno.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/socket_types.hpp>
+
+#if defined(GENERATING_DOCUMENTATION)
+/// INTERNAL ONLY.
+# define BOOST_ASIO_NATIVE_ERROR(e) implementation_defined
+/// INTERNAL ONLY.
+# define BOOST_ASIO_SOCKET_ERROR(e) implementation_defined
+/// INTERNAL ONLY.
+# define BOOST_ASIO_NETDB_ERROR(e) implementation_defined
+/// INTERNAL ONLY.
+# define BOOST_ASIO_GETADDRINFO_ERROR(e) implementation_defined
+/// INTERNAL ONLY.
+# define BOOST_ASIO_WIN_OR_POSIX(e_win, e_posix) implementation_defined
+#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# define BOOST_ASIO_NATIVE_ERROR(e) e
+# define BOOST_ASIO_SOCKET_ERROR(e) WSA ## e
+# define BOOST_ASIO_NETDB_ERROR(e) WSA ## e
+# define BOOST_ASIO_GETADDRINFO_ERROR(e) WSA ## e
+# define BOOST_ASIO_WIN_OR_POSIX(e_win, e_posix) e_win
+#else
+# define BOOST_ASIO_NATIVE_ERROR(e) e
+# define BOOST_ASIO_SOCKET_ERROR(e) e
+# define BOOST_ASIO_NETDB_ERROR(e) e
+# define BOOST_ASIO_GETADDRINFO_ERROR(e) e
+# define BOOST_ASIO_WIN_OR_POSIX(e_win, e_posix) e_posix
+#endif
+
+namespace boost {
+namespace asio {
+namespace error {
+
+enum basic_errors
+{
+ /// Permission denied.
+ access_denied = BOOST_ASIO_SOCKET_ERROR(EACCES),
+
+ /// Address family not supported by protocol.
+ address_family_not_supported = BOOST_ASIO_SOCKET_ERROR(EAFNOSUPPORT),
+
+ /// Address already in use.
+ address_in_use = BOOST_ASIO_SOCKET_ERROR(EADDRINUSE),
+
+ /// Transport endpoint is already connected.
+ already_connected = BOOST_ASIO_SOCKET_ERROR(EISCONN),
+
+ /// Operation already in progress.
+ already_started = BOOST_ASIO_SOCKET_ERROR(EALREADY),
+
+ /// Broken pipe.
+ broken_pipe = BOOST_ASIO_WIN_OR_POSIX(
+ BOOST_ASIO_NATIVE_ERROR(ERROR_BROKEN_PIPE),
+ BOOST_ASIO_NATIVE_ERROR(EPIPE)),
+
+ /// A connection has been aborted.
+ connection_aborted = BOOST_ASIO_SOCKET_ERROR(ECONNABORTED),
+
+ /// Connection refused.
+ connection_refused = BOOST_ASIO_SOCKET_ERROR(ECONNREFUSED),
+
+ /// Connection reset by peer.
+ connection_reset = BOOST_ASIO_SOCKET_ERROR(ECONNRESET),
+
+ /// Bad file descriptor.
+ bad_descriptor = BOOST_ASIO_SOCKET_ERROR(EBADF),
+
+ /// Bad address.
+ fault = BOOST_ASIO_SOCKET_ERROR(EFAULT),
+
+ /// No route to host.
+ host_unreachable = BOOST_ASIO_SOCKET_ERROR(EHOSTUNREACH),
+
+ /// Operation now in progress.
+ in_progress = BOOST_ASIO_SOCKET_ERROR(EINPROGRESS),
+
+ /// Interrupted system call.
+ interrupted = BOOST_ASIO_SOCKET_ERROR(EINTR),
+
+ /// Invalid argument.
+ invalid_argument = BOOST_ASIO_SOCKET_ERROR(EINVAL),
+
+ /// Message too long.
+ message_size = BOOST_ASIO_SOCKET_ERROR(EMSGSIZE),
+
+ /// The name was too long.
+ name_too_long = BOOST_ASIO_SOCKET_ERROR(ENAMETOOLONG),
+
+ /// Network is down.
+ network_down = BOOST_ASIO_SOCKET_ERROR(ENETDOWN),
+
+ /// Network dropped connection on reset.
+ network_reset = BOOST_ASIO_SOCKET_ERROR(ENETRESET),
+
+ /// Network is unreachable.
+ network_unreachable = BOOST_ASIO_SOCKET_ERROR(ENETUNREACH),
+
+ /// Too many open files.
+ no_descriptors = BOOST_ASIO_SOCKET_ERROR(EMFILE),
+
+ /// No buffer space available.
+ no_buffer_space = BOOST_ASIO_SOCKET_ERROR(ENOBUFS),
+
+ /// Cannot allocate memory.
+ no_memory = BOOST_ASIO_WIN_OR_POSIX(
+ BOOST_ASIO_NATIVE_ERROR(ERROR_OUTOFMEMORY),
+ BOOST_ASIO_NATIVE_ERROR(ENOMEM)),
+
+ /// Operation not permitted.
+ no_permission = BOOST_ASIO_WIN_OR_POSIX(
+ BOOST_ASIO_NATIVE_ERROR(ERROR_ACCESS_DENIED),
+ BOOST_ASIO_NATIVE_ERROR(EPERM)),
+
+ /// Protocol not available.
+ no_protocol_option = BOOST_ASIO_SOCKET_ERROR(ENOPROTOOPT),
+
+ /// Transport endpoint is not connected.
+ not_connected = BOOST_ASIO_SOCKET_ERROR(ENOTCONN),
+
+ /// Socket operation on non-socket.
+ not_socket = BOOST_ASIO_SOCKET_ERROR(ENOTSOCK),
+
+ /// Operation cancelled.
+ operation_aborted = BOOST_ASIO_WIN_OR_POSIX(
+ BOOST_ASIO_NATIVE_ERROR(ERROR_OPERATION_ABORTED),
+ BOOST_ASIO_NATIVE_ERROR(ECANCELED)),
+
+ /// Operation not supported.
+ operation_not_supported = BOOST_ASIO_SOCKET_ERROR(EOPNOTSUPP),
+
+ /// Cannot send after transport endpoint shutdown.
+ shut_down = BOOST_ASIO_SOCKET_ERROR(ESHUTDOWN),
+
+ /// Connection timed out.
+ timed_out = BOOST_ASIO_SOCKET_ERROR(ETIMEDOUT),
+
+ /// Resource temporarily unavailable.
+ try_again = BOOST_ASIO_WIN_OR_POSIX(
+ BOOST_ASIO_NATIVE_ERROR(ERROR_RETRY),
+ BOOST_ASIO_NATIVE_ERROR(EAGAIN)),
+
+ /// The socket is marked non-blocking and the requested operation would block.
+ would_block = BOOST_ASIO_SOCKET_ERROR(EWOULDBLOCK)
+};
+
+enum netdb_errors
+{
+ /// Host not found (authoritative).
+ host_not_found = BOOST_ASIO_NETDB_ERROR(HOST_NOT_FOUND),
+
+ /// Host not found (non-authoritative).
+ host_not_found_try_again = BOOST_ASIO_NETDB_ERROR(TRY_AGAIN),
+
+ /// The query is valid but does not have associated address data.
+ no_data = BOOST_ASIO_NETDB_ERROR(NO_DATA),
+
+ /// A non-recoverable error occurred.
+ no_recovery = BOOST_ASIO_NETDB_ERROR(NO_RECOVERY)
+};
+
+enum addrinfo_errors
+{
+ /// The service is not supported for the given socket type.
+ service_not_found = BOOST_ASIO_WIN_OR_POSIX(
+ BOOST_ASIO_NATIVE_ERROR(WSATYPE_NOT_FOUND),
+ BOOST_ASIO_GETADDRINFO_ERROR(EAI_SERVICE)),
+
+ /// The socket type is not supported.
+ socket_type_not_supported = BOOST_ASIO_WIN_OR_POSIX(
+ BOOST_ASIO_NATIVE_ERROR(WSAESOCKTNOSUPPORT),
+ BOOST_ASIO_GETADDRINFO_ERROR(EAI_SOCKTYPE))
+};
+
+enum misc_errors
+{
+ /// Already open.
+ already_open = 1,
+
+ /// End of file or stream.
+ eof,
+
+ /// Element not found.
+ not_found,
+
+ /// The descriptor cannot fit into the select system call's fd_set.
+ fd_set_failure
+};
+
+enum ssl_errors
+{
+};
+
+inline const boost::system::error_category& get_system_category()
+{
+ return boost::system::get_system_category();
+}
+
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+namespace detail {
+
+class netdb_category : public boost::system::error_category
+{
+public:
+ const char* name() const
+ {
+ return "asio.netdb";
+ }
+
+ std::string message(int value) const
+ {
+ if (value == error::host_not_found)
+ return "Host not found (authoritative)";
+ if (value == error::host_not_found_try_again)
+ return "Host not found (non-authoritative), try again later";
+ if (value == error::no_data)
+ return "The query is valid, but it does not have associated data";
+ if (value == error::no_recovery)
+ return "A non-recoverable error occurred during database lookup";
+ return "asio.netdb error";
+ }
+};
+
+} // namespace detail
+
+inline const boost::system::error_category& get_netdb_category()
+{
+ static detail::netdb_category instance;
+ return instance;
+}
+
+namespace detail {
+
+class addrinfo_category : public boost::system::error_category
+{
+public:
+ const char* name() const
+ {
+ return "asio.addrinfo";
+ }
+
+ std::string message(int value) const
+ {
+ if (value == error::service_not_found)
+ return "Service not found";
+ if (value == error::socket_type_not_supported)
+ return "Socket type not supported";
+ return "asio.addrinfo error";
+ }
+};
+
+} // namespace detail
+
+inline const boost::system::error_category& get_addrinfo_category()
+{
+ static detail::addrinfo_category instance;
+ return instance;
+}
+
+#else // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+inline const boost::system::error_category& get_netdb_category()
+{
+ return get_system_category();
+}
+
+inline const boost::system::error_category& get_addrinfo_category()
+{
+ return get_system_category();
+}
+
+#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+
+namespace detail {
+
+class misc_category : public boost::system::error_category
+{
+public:
+ const char* name() const
+ {
+ return "asio.misc";
+ }
+
+ std::string message(int value) const
+ {
+ if (value == error::already_open)
+ return "Already open";
+ if (value == error::eof)
+ return "End of file";
+ if (value == error::not_found)
+ return "Element not found";
+ if (value == error::fd_set_failure)
+ return "The descriptor does not fit into the select call's fd_set";
+ return "asio.misc error";
+ }
+};
+
+} // namespace detail
+
+inline const boost::system::error_category& get_misc_category()
+{
+ static detail::misc_category instance;
+ return instance;
+}
+
+namespace detail {
+
+class ssl_category : public boost::system::error_category
+{
+public:
+ const char* name() const
+ {
+ return "asio.ssl";
+ }
+
+ std::string message(int) const
+ {
+ return "asio.ssl error";
+ }
+};
+
+} // namespace detail
+
+inline const boost::system::error_category& get_ssl_category()
+{
+ static detail::ssl_category instance;
+ return instance;
+}
+
+static const boost::system::error_category& system_category
+ = boost::asio::error::get_system_category();
+static const boost::system::error_category& netdb_category
+ = boost::asio::error::get_netdb_category();
+static const boost::system::error_category& addrinfo_category
+ = boost::asio::error::get_addrinfo_category();
+static const boost::system::error_category& misc_category
+ = boost::asio::error::get_misc_category();
+static const boost::system::error_category& ssl_category
+ = boost::asio::error::get_ssl_category();
+
+} // namespace error
+} // namespace asio
+
+namespace system {
+
+template<> struct is_error_code_enum<boost::asio::error::basic_errors>
+{
+ static const bool value = true;
+};
+
+template<> struct is_error_code_enum<boost::asio::error::netdb_errors>
+{
+ static const bool value = true;
+};
+
+template<> struct is_error_code_enum<boost::asio::error::addrinfo_errors>
+{
+ static const bool value = true;
+};
+
+template<> struct is_error_code_enum<boost::asio::error::misc_errors>
+{
+ static const bool value = true;
+};
+
+template<> struct is_error_code_enum<boost::asio::error::ssl_errors>
+{
+ static const bool value = true;
+};
+
+} // namespace system
+
+namespace asio {
+namespace error {
+
+inline boost::system::error_code make_error_code(basic_errors e)
+{
+ return boost::system::error_code(
+ static_cast<int>(e), get_system_category());
+}
+
+inline boost::system::error_code make_error_code(netdb_errors e)
+{
+ return boost::system::error_code(
+ static_cast<int>(e), get_netdb_category());
+}
+
+inline boost::system::error_code make_error_code(addrinfo_errors e)
+{
+ return boost::system::error_code(
+ static_cast<int>(e), get_addrinfo_category());
+}
+
+inline boost::system::error_code make_error_code(misc_errors e)
+{
+ return boost::system::error_code(
+ static_cast<int>(e), get_misc_category());
+}
+
+inline boost::system::error_code make_error_code(ssl_errors e)
+{
+ return boost::system::error_code(
+ static_cast<int>(e), get_ssl_category());
+}
+
+} // namespace error
+} // namespace asio
+} // namespace boost
+
+#undef BOOST_ASIO_NATIVE_ERROR
+#undef BOOST_ASIO_SOCKET_ERROR
+#undef BOOST_ASIO_NETDB_ERROR
+#undef BOOST_ASIO_GETADDRINFO_ERROR
+#undef BOOST_ASIO_WIN_OR_POSIX
+
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_ERROR_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/handler_alloc_hook.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/handler_alloc_hook.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,90 @@
+//
+// handler_alloc_hook.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_HANDLER_ALLOC_HOOK_HPP
+#define BOOST_ASIO_HANDLER_ALLOC_HOOK_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Default allocation function for handlers.
+/**
+ * Asynchronous operations may need to allocate temporary objects. Since
+ * asynchronous operations have a handler function object, these temporary
+ * objects can be said to be associated with the handler.
+ *
+ * Implement asio_handler_allocate and asio_handler_deallocate for your own
+ * handlers to provide custom allocation for these temporary objects.
+ *
+ * This default implementation is simply:
+ * @code
+ * return ::operator new(bytes);
+ * @endcode
+ *
+ * @note All temporary objects associated with a handler will be deallocated
+ * before the upcall to the handler is performed. This allows the same memory to
+ * be reused for a subsequent asynchronous operation initiated by the handler.
+ *
+ * @par Example
+ * @code
+ * class my_handler;
+ *
+ * void* asio_handler_allocate(std::size_t size, my_handler* context)
+ * {
+ * return ::operator new(size);
+ * }
+ *
+ * void asio_handler_deallocate(void* pointer, std::size_t size,
+ * my_handler* context)
+ * {
+ * ::operator delete(pointer);
+ * }
+ * @endcode
+ */
+inline void* asio_handler_allocate(std::size_t size, ...)
+{
+ return ::operator new(size);
+}
+
+/// Default deallocation function for handlers.
+/**
+ * Implement asio_handler_allocate and asio_handler_deallocate for your own
+ * handlers to provide custom allocation for the associated temporary objects.
+ *
+ * This default implementation is simply:
+ * @code
+ * ::operator delete(pointer);
+ * @endcode
+ *
+ * @sa asio_handler_allocate.
+ */
+inline void asio_handler_deallocate(void* pointer, std::size_t size, ...)
+{
+ (void)(size);
+ ::operator delete(pointer);
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_HANDLER_ALLOC_HOOK_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/handler_invoke_hook.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/handler_invoke_hook.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,71 @@
+//
+// handler_invoke_hook.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_HANDLER_INVOKE_HOOK_HPP
+#define BOOST_ASIO_HANDLER_INVOKE_HOOK_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Default invoke function for handlers.
+/**
+ * Completion handlers for asynchronous operations are invoked by the
+ * io_service associated with the corresponding object (e.g. a socket or
+ * deadline_timer). Certain guarantees are made on when the handler may be
+ * invoked, in particular that a handler can only be invoked from a thread that
+ * is currently calling boost::asio::io_service::run() on the corresponding
+ * io_service object. Handlers may subsequently be invoked through other
+ * objects (such as boost::asio::strand objects) that provide additional
+ * guarantees.
+ *
+ * When asynchronous operations are composed from other asynchronous
+ * operations, all intermediate handlers should be invoked using the same
+ * method as the final handler. This is required to ensure that user-defined
+ * objects are not accessed in a way that may violate the guarantees. This
+ * hooking function ensures that the invoked method used for the final handler
+ * is accessible at each intermediate step.
+ *
+ * Implement asio_handler_invoke for your own handlers to specify a custom
+ * invocation strategy.
+ *
+ * This default implementation is simply:
+ * @code
+ * function();
+ * @endcode
+ *
+ * @par Example
+ * @code
+ * class my_handler;
+ *
+ * template <typename Function>
+ * void asio_handler_invoke(Function function, my_handler* context)
+ * {
+ * context->strand_.dispatch(function);
+ * }
+ * @endcode
+ */
+template <typename Function>
+inline void asio_handler_invoke(Function function, ...)
+{
+ function();
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_HANDLER_INVOKE_HOOK_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/impl/io_service.ipp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/impl/io_service.ipp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,226 @@
+//
+// io_service.ipp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IO_SERVICE_IPP
+#define BOOST_ASIO_IO_SERVICE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <limits>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/dev_poll_reactor.hpp>
+#include <boost/asio/detail/epoll_reactor.hpp>
+#include <boost/asio/detail/kqueue_reactor.hpp>
+#include <boost/asio/detail/select_reactor.hpp>
+#include <boost/asio/detail/service_registry.hpp>
+#include <boost/asio/detail/task_io_service.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/detail/win_iocp_io_service.hpp>
+
+namespace boost {
+namespace asio {
+
+inline io_service::io_service()
+ : service_registry_(new boost::asio::detail::service_registry(*this)),
+ impl_(service_registry_->use_service<impl_type>())
+{
+ impl_.init((std::numeric_limits<std::size_t>::max)());
+}
+
+inline io_service::io_service(std::size_t concurrency_hint)
+ : service_registry_(new boost::asio::detail::service_registry(*this)),
+ impl_(service_registry_->use_service<impl_type>())
+{
+ impl_.init(concurrency_hint);
+}
+
+inline io_service::~io_service()
+{
+ delete service_registry_;
+}
+
+inline std::size_t io_service::run()
+{
+ boost::system::error_code ec;
+ std::size_t s = impl_.run(ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+}
+
+inline std::size_t io_service::run(boost::system::error_code& ec)
+{
+ return impl_.run(ec);
+}
+
+inline std::size_t io_service::run_one()
+{
+ boost::system::error_code ec;
+ std::size_t s = impl_.run_one(ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+}
+
+inline std::size_t io_service::run_one(boost::system::error_code& ec)
+{
+ return impl_.run_one(ec);
+}
+
+inline std::size_t io_service::poll()
+{
+ boost::system::error_code ec;
+ std::size_t s = impl_.poll(ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+}
+
+inline std::size_t io_service::poll(boost::system::error_code& ec)
+{
+ return impl_.poll(ec);
+}
+
+inline std::size_t io_service::poll_one()
+{
+ boost::system::error_code ec;
+ std::size_t s = impl_.poll_one(ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+}
+
+inline std::size_t io_service::poll_one(boost::system::error_code& ec)
+{
+ return impl_.poll_one(ec);
+}
+
+inline void io_service::stop()
+{
+ impl_.stop();
+}
+
+inline void io_service::reset()
+{
+ impl_.reset();
+}
+
+template <typename Handler>
+inline void io_service::dispatch(Handler handler)
+{
+ impl_.dispatch(handler);
+}
+
+template <typename Handler>
+inline void io_service::post(Handler handler)
+{
+ impl_.post(handler);
+}
+
+template <typename Handler>
+#if defined(GENERATING_DOCUMENTATION)
+unspecified
+#else
+inline detail::wrapped_handler<io_service&, Handler>
+#endif
+io_service::wrap(Handler handler)
+{
+ return detail::wrapped_handler<io_service&, Handler>(*this, handler);
+}
+
+inline io_service::work::work(boost::asio::io_service& io_service)
+ : io_service_(io_service)
+{
+ io_service_.impl_.work_started();
+}
+
+inline io_service::work::work(const work& other)
+ : io_service_(other.io_service_)
+{
+ io_service_.impl_.work_started();
+}
+
+inline io_service::work::~work()
+{
+ io_service_.impl_.work_finished();
+}
+
+inline boost::asio::io_service& io_service::work::io_service()
+{
+ return io_service_;
+}
+
+inline boost::asio::io_service& io_service::work::get_io_service()
+{
+ return io_service_;
+}
+
+inline io_service::service::service(boost::asio::io_service& owner)
+ : owner_(owner),
+ type_info_(0),
+ next_(0)
+{
+}
+
+inline io_service::service::~service()
+{
+}
+
+inline boost::asio::io_service& io_service::service::io_service()
+{
+ return owner_;
+}
+
+inline boost::asio::io_service& io_service::service::get_io_service()
+{
+ return owner_;
+}
+
+template <typename Service>
+inline Service& use_service(io_service& ios)
+{
+ // Check that Service meets the necessary type requirements.
+ (void)static_cast<io_service::service*>(static_cast<Service*>(0));
+ (void)static_cast<const io_service::id*>(&Service::id);
+
+ return ios.service_registry_->template use_service<Service>();
+}
+
+template <typename Service>
+void add_service(io_service& ios, Service* svc)
+{
+ // Check that Service meets the necessary type requirements.
+ (void)static_cast<io_service::service*>(static_cast<Service*>(0));
+ (void)static_cast<const io_service::id*>(&Service::id);
+
+ if (&ios != &svc->io_service())
+ boost::throw_exception(invalid_service_owner());
+ if (!ios.service_registry_->template add_service<Service>(svc))
+ boost::throw_exception(service_already_exists());
+}
+
+template <typename Service>
+bool has_service(io_service& ios)
+{
+ // Check that Service meets the necessary type requirements.
+ (void)static_cast<io_service::service*>(static_cast<Service*>(0));
+ (void)static_cast<const io_service::id*>(&Service::id);
+
+ return ios.service_registry_->template has_service<Service>();
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IO_SERVICE_IPP
Added: branches/CMake/release/libs/asio/include/boost/asio/impl/read.ipp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/impl/read.ipp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,316 @@
+//
+// read.ipp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_READ_IPP
+#define BOOST_ASIO_READ_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <algorithm>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/completion_condition.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/consuming_buffers.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+
+template <typename SyncReadStream, typename MutableBufferSequence,
+ typename CompletionCondition>
+std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition, boost::system::error_code& ec)
+{
+ boost::asio::detail::consuming_buffers<
+ mutable_buffer, MutableBufferSequence> tmp(buffers);
+ std::size_t total_transferred = 0;
+ while (tmp.begin() != tmp.end())
+ {
+ std::size_t bytes_transferred = s.read_some(tmp, ec);
+ tmp.consume(bytes_transferred);
+ total_transferred += bytes_transferred;
+ if (completion_condition(ec, total_transferred))
+ return total_transferred;
+ }
+ ec = boost::system::error_code();
+ return total_transferred;
+}
+
+template <typename SyncReadStream, typename MutableBufferSequence>
+inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncReadStream, typename MutableBufferSequence,
+ typename CompletionCondition>
+inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read(s, buffers, completion_condition, ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncReadStream, typename Allocator,
+ typename CompletionCondition>
+std::size_t read(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, boost::system::error_code& ec)
+{
+ std::size_t total_transferred = 0;
+ for (;;)
+ {
+ std::size_t bytes_available =
+ std::min<std::size_t>(512, b.max_size() - b.size());
+ std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
+ b.commit(bytes_transferred);
+ total_transferred += bytes_transferred;
+ if (b.size() == b.max_size()
+ || completion_condition(ec, total_transferred))
+ return total_transferred;
+ }
+}
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read(s, b, transfer_all(), ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncReadStream, typename Allocator,
+ typename CompletionCondition>
+inline std::size_t read(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read(s, b, completion_condition, ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+namespace detail
+{
+ template <typename AsyncReadStream, typename MutableBufferSequence,
+ typename CompletionCondition, typename ReadHandler>
+ class read_handler
+ {
+ public:
+ typedef boost::asio::detail::consuming_buffers<
+ mutable_buffer, MutableBufferSequence> buffers_type;
+
+ read_handler(AsyncReadStream& stream, const buffers_type& buffers,
+ CompletionCondition completion_condition, ReadHandler handler)
+ : stream_(stream),
+ buffers_(buffers),
+ total_transferred_(0),
+ completion_condition_(completion_condition),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ total_transferred_ += bytes_transferred;
+ buffers_.consume(bytes_transferred);
+ if (completion_condition_(ec, total_transferred_)
+ || buffers_.begin() == buffers_.end())
+ {
+ handler_(ec, total_transferred_);
+ }
+ else
+ {
+ stream_.async_read_some(buffers_, *this);
+ }
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ buffers_type buffers_;
+ std::size_t total_transferred_;
+ CompletionCondition completion_condition_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncReadStream, typename MutableBufferSequence,
+ typename CompletionCondition, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_handler<AsyncReadStream, MutableBufferSequence,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream, typename MutableBufferSequence,
+ typename CompletionCondition, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_handler<AsyncReadStream, MutableBufferSequence,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream,
+ typename MutableBufferSequence, typename CompletionCondition,
+ typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_handler<AsyncReadStream, MutableBufferSequence,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncReadStream, typename MutableBufferSequence,
+ typename CompletionCondition, typename ReadHandler>
+inline void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition, ReadHandler handler)
+{
+ boost::asio::detail::consuming_buffers<
+ mutable_buffer, MutableBufferSequence> tmp(buffers);
+ s.async_read_some(tmp,
+ detail::read_handler<AsyncReadStream, MutableBufferSequence,
+ CompletionCondition, ReadHandler>(
+ s, tmp, completion_condition, handler));
+}
+
+template <typename AsyncReadStream, typename MutableBufferSequence,
+ typename ReadHandler>
+inline void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
+ ReadHandler handler)
+{
+ async_read(s, buffers, transfer_all(), handler);
+}
+
+namespace detail
+{
+ template <typename AsyncReadStream, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+ class read_streambuf_handler
+ {
+ public:
+ read_streambuf_handler(AsyncReadStream& stream,
+ basic_streambuf<Allocator>& streambuf,
+ CompletionCondition completion_condition, ReadHandler handler)
+ : stream_(stream),
+ streambuf_(streambuf),
+ total_transferred_(0),
+ completion_condition_(completion_condition),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ total_transferred_ += bytes_transferred;
+ streambuf_.commit(bytes_transferred);
+ if (streambuf_.size() == streambuf_.max_size()
+ || completion_condition_(ec, total_transferred_))
+ {
+ handler_(ec, total_transferred_);
+ }
+ else
+ {
+ std::size_t bytes_available =
+ std::min<std::size_t>(512, streambuf_.max_size() - streambuf_.size());
+ stream_.async_read_some(streambuf_.prepare(bytes_available), *this);
+ }
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ boost::asio::basic_streambuf<Allocator>& streambuf_;
+ std::size_t total_transferred_;
+ CompletionCondition completion_condition_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncReadStream, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_streambuf_handler<AsyncReadStream, Allocator,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_streambuf_handler<AsyncReadStream, Allocator,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream,
+ typename Allocator, typename CompletionCondition, typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_streambuf_handler<AsyncReadStream, Allocator,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncReadStream, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+inline void async_read(AsyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, ReadHandler handler)
+{
+ std::size_t bytes_available =
+ std::min<std::size_t>(512, b.max_size() - b.size());
+ s.async_read_some(b.prepare(bytes_available),
+ detail::read_streambuf_handler<AsyncReadStream, Allocator,
+ CompletionCondition, ReadHandler>(
+ s, b, completion_condition, handler));
+}
+
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+inline void async_read(AsyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, ReadHandler handler)
+{
+ async_read(s, b, transfer_all(), handler);
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_READ_IPP
Added: branches/CMake/release/libs/asio/include/boost/asio/impl/read_at.ipp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/impl/read_at.ipp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,339 @@
+//
+// read_at.ipp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_READ_AT_IPP
+#define BOOST_ASIO_READ_AT_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <algorithm>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/completion_condition.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/consuming_buffers.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+
+template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
+ typename CompletionCondition>
+std::size_t read_at(SyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition, boost::system::error_code& ec)
+{
+ boost::asio::detail::consuming_buffers<
+ mutable_buffer, MutableBufferSequence> tmp(buffers);
+ std::size_t total_transferred = 0;
+ while (tmp.begin() != tmp.end())
+ {
+ std::size_t bytes_transferred = d.read_some_at(
+ offset + total_transferred, tmp, ec);
+ tmp.consume(bytes_transferred);
+ total_transferred += bytes_transferred;
+ if (completion_condition(ec, total_transferred))
+ return total_transferred;
+ }
+ ec = boost::system::error_code();
+ return total_transferred;
+}
+
+template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
+inline std::size_t read_at(SyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, const MutableBufferSequence& buffers)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read_at(
+ d, offset, buffers, transfer_all(), ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
+ typename CompletionCondition>
+inline std::size_t read_at(SyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read_at(
+ d, offset, buffers, completion_condition, ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncRandomAccessReadDevice, typename Allocator,
+ typename CompletionCondition>
+std::size_t read_at(SyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, boost::system::error_code& ec)
+{
+ std::size_t total_transferred = 0;
+ for (;;)
+ {
+ std::size_t bytes_available =
+ std::min<std::size_t>(512, b.max_size() - b.size());
+ std::size_t bytes_transferred = d.read_some_at(
+ offset + total_transferred, b.prepare(bytes_available), ec);
+ b.commit(bytes_transferred);
+ total_transferred += bytes_transferred;
+ if (b.size() == b.max_size()
+ || completion_condition(ec, total_transferred))
+ return total_transferred;
+ }
+}
+
+template <typename SyncRandomAccessReadDevice, typename Allocator>
+inline std::size_t read_at(SyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, boost::asio::basic_streambuf<Allocator>& b)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read_at(
+ d, offset, b, transfer_all(), ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncRandomAccessReadDevice, typename Allocator,
+ typename CompletionCondition>
+inline std::size_t read_at(SyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read_at(
+ d, offset, b, completion_condition, ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+namespace detail
+{
+ template <typename AsyncRandomAccessReadDevice,
+ typename MutableBufferSequence, typename CompletionCondition,
+ typename ReadHandler>
+ class read_at_handler
+ {
+ public:
+ typedef boost::asio::detail::consuming_buffers<
+ mutable_buffer, MutableBufferSequence> buffers_type;
+
+ read_at_handler(AsyncRandomAccessReadDevice& stream,
+ boost::uint64_t offset, const buffers_type& buffers,
+ CompletionCondition completion_condition, ReadHandler handler)
+ : stream_(stream),
+ offset_(offset),
+ buffers_(buffers),
+ total_transferred_(0),
+ completion_condition_(completion_condition),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ total_transferred_ += bytes_transferred;
+ buffers_.consume(bytes_transferred);
+ if (completion_condition_(ec, total_transferred_)
+ || buffers_.begin() == buffers_.end())
+ {
+ handler_(ec, total_transferred_);
+ }
+ else
+ {
+ stream_.async_read_some_at(
+ offset_ + total_transferred_, buffers_, *this);
+ }
+ }
+
+ //private:
+ AsyncRandomAccessReadDevice& stream_;
+ boost::uint64_t offset_;
+ buffers_type buffers_;
+ std::size_t total_transferred_;
+ CompletionCondition completion_condition_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncRandomAccessReadDevice,
+ typename MutableBufferSequence, typename CompletionCondition,
+ typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_at_handler<AsyncRandomAccessReadDevice, MutableBufferSequence,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+ }
+
+ template <typename AsyncRandomAccessReadDevice,
+ typename MutableBufferSequence, typename CompletionCondition,
+ typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_at_handler<AsyncRandomAccessReadDevice, MutableBufferSequence,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncRandomAccessReadDevice,
+ typename MutableBufferSequence, typename CompletionCondition,
+ typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_at_handler<AsyncRandomAccessReadDevice, MutableBufferSequence,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
+ typename CompletionCondition, typename ReadHandler>
+inline void async_read_at(AsyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition, ReadHandler handler)
+{
+ boost::asio::detail::consuming_buffers<
+ mutable_buffer, MutableBufferSequence> tmp(buffers);
+ d.async_read_some_at(offset, tmp,
+ detail::read_at_handler<AsyncRandomAccessReadDevice,
+ MutableBufferSequence, CompletionCondition, ReadHandler>(
+ d, offset, tmp, completion_condition, handler));
+}
+
+template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
+ typename ReadHandler>
+inline void async_read_at(AsyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, const MutableBufferSequence& buffers,
+ ReadHandler handler)
+{
+ async_read_at(d, offset, buffers, transfer_all(), handler);
+}
+
+namespace detail
+{
+ template <typename AsyncRandomAccessReadDevice, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+ class read_at_streambuf_handler
+ {
+ public:
+ read_at_streambuf_handler(AsyncRandomAccessReadDevice& stream,
+ boost::uint64_t offset, basic_streambuf<Allocator>& streambuf,
+ CompletionCondition completion_condition, ReadHandler handler)
+ : stream_(stream),
+ offset_(offset),
+ streambuf_(streambuf),
+ total_transferred_(0),
+ completion_condition_(completion_condition),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ total_transferred_ += bytes_transferred;
+ streambuf_.commit(bytes_transferred);
+ if (streambuf_.size() == streambuf_.max_size()
+ || completion_condition_(ec, total_transferred_))
+ {
+ handler_(ec, total_transferred_);
+ }
+ else
+ {
+ std::size_t bytes_available =
+ std::min<std::size_t>(512, streambuf_.max_size() - streambuf_.size());
+ stream_.async_read_some_at(offset_ + total_transferred_,
+ streambuf_.prepare(bytes_available), *this);
+ }
+ }
+
+ //private:
+ AsyncRandomAccessReadDevice& stream_;
+ boost::uint64_t offset_;
+ boost::asio::basic_streambuf<Allocator>& streambuf_;
+ std::size_t total_transferred_;
+ CompletionCondition completion_condition_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncRandomAccessReadDevice, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_at_streambuf_handler<AsyncRandomAccessReadDevice, Allocator,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+ }
+
+ template <typename AsyncRandomAccessReadDevice, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_at_streambuf_handler<AsyncRandomAccessReadDevice, Allocator,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncRandomAccessReadDevice,
+ typename Allocator, typename CompletionCondition, typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_at_streambuf_handler<AsyncRandomAccessReadDevice, Allocator,
+ CompletionCondition, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncRandomAccessReadDevice, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+inline void async_read_at(AsyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, ReadHandler handler)
+{
+ std::size_t bytes_available =
+ std::min<std::size_t>(512, b.max_size() - b.size());
+ d.async_read_some_at(offset, b.prepare(bytes_available),
+ detail::read_at_streambuf_handler<AsyncRandomAccessReadDevice, Allocator,
+ CompletionCondition, ReadHandler>(
+ d, offset, b, completion_condition, handler));
+}
+
+template <typename AsyncRandomAccessReadDevice, typename Allocator,
+ typename ReadHandler>
+inline void async_read_at(AsyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
+ ReadHandler handler)
+{
+ async_read_at(d, offset, b, transfer_all(), handler);
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_READ_AT_IPP
Added: branches/CMake/release/libs/asio/include/boost/asio/impl/read_until.ipp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/impl/read_until.ipp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,998 @@
+//
+// read_until.ipp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_READ_UNTIL_IPP
+#define BOOST_ASIO_READ_UNTIL_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <algorithm>
+#include <limits>
+#include <string>
+#include <utility>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/buffers_iterator.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, char delim)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read_until(s, b, delim, ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncReadStream, typename Allocator>
+std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, char delim,
+ boost::system::error_code& ec)
+{
+ std::size_t next_search_start = 0;
+ for (;;)
+ {
+ // Determine the range of the data to be searched.
+ typedef typename boost::asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = b.data();
+ iterator begin = iterator::begin(buffers);
+ iterator start = begin + next_search_start;
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ iterator iter = std::find(start, end, delim);
+ if (iter != end)
+ {
+ // Found a match. We're done.
+ ec = boost::system::error_code();
+ return iter - begin + 1;
+ }
+ else
+ {
+ // No match. Next search can start with the new data.
+ next_search_start = end - begin;
+ }
+
+ // Check if buffer is full.
+ if (b.size() == b.max_size())
+ {
+ ec = error::not_found;
+ return 0;
+ }
+
+ // Need more data.
+ std::size_t bytes_available =
+ std::min<std::size_t>(512, b.max_size() - b.size());
+ b.commit(s.read_some(b.prepare(bytes_available), ec));
+ if (ec)
+ return 0;
+ }
+}
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, const std::string& delim)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read_until(s, b, delim, ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+namespace detail
+{
+ // Algorithm that finds a subsequence of equal values in a sequence. Returns
+ // (iterator,true) if a full match was found, in which case the iterator
+ // points to the beginning of the match. Returns (iterator,false) if a
+ // partial match was found at the end of the first sequence, in which case
+ // the iterator points to the beginning of the partial match. Returns
+ // (last1,false) if no full or partial match was found.
+ template <typename Iterator1, typename Iterator2>
+ std::pair<Iterator1, bool> partial_search(
+ Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
+ {
+ for (Iterator1 iter1 = first1; iter1 != last1; ++iter1)
+ {
+ Iterator1 test_iter1 = iter1;
+ Iterator2 test_iter2 = first2;
+ for (;; ++test_iter1, ++test_iter2)
+ {
+ if (test_iter2 == last2)
+ return std::make_pair(iter1, true);
+ if (test_iter1 == last1)
+ {
+ if (test_iter2 != first2)
+ return std::make_pair(iter1, false);
+ else
+ break;
+ }
+ if (*test_iter1 != *test_iter2)
+ break;
+ }
+ }
+ return std::make_pair(last1, false);
+ }
+} // namespace detail
+
+template <typename SyncReadStream, typename Allocator>
+std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, const std::string& delim,
+ boost::system::error_code& ec)
+{
+ std::size_t next_search_start = 0;
+ for (;;)
+ {
+ // Determine the range of the data to be searched.
+ typedef typename boost::asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = b.data();
+ iterator begin = iterator::begin(buffers);
+ iterator start = begin + next_search_start;
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ std::pair<iterator, bool> result = boost::asio::detail::partial_search(
+ start, end, delim.begin(), delim.end());
+ if (result.first != end)
+ {
+ if (result.second)
+ {
+ // Full match. We're done.
+ ec = boost::system::error_code();
+ return result.first - begin + delim.length();
+ }
+ else
+ {
+ // Partial match. Next search needs to start from beginning of match.
+ next_search_start = result.first - begin;
+ }
+ }
+ else
+ {
+ // No match. Next search can start with the new data.
+ next_search_start = end - begin;
+ }
+
+ // Check if buffer is full.
+ if (b.size() == b.max_size())
+ {
+ ec = error::not_found;
+ return 0;
+ }
+
+ // Need more data.
+ std::size_t bytes_available =
+ std::min<std::size_t>(512, b.max_size() - b.size());
+ b.commit(s.read_some(b.prepare(bytes_available), ec));
+ if (ec)
+ return 0;
+ }
+}
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read_until(s, b, expr, ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncReadStream, typename Allocator>
+std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
+ boost::system::error_code& ec)
+{
+ std::size_t next_search_start = 0;
+ for (;;)
+ {
+ // Determine the range of the data to be searched.
+ typedef typename boost::asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = b.data();
+ iterator begin = iterator::begin(buffers);
+ iterator start = begin + next_search_start;
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ boost::match_results<iterator> match_results;
+ if (boost::regex_search(start, end, match_results, expr,
+ boost::match_default | boost::match_partial))
+ {
+ if (match_results[0].matched)
+ {
+ // Full match. We're done.
+ ec = boost::system::error_code();
+ return match_results[0].second - begin;
+ }
+ else
+ {
+ // Partial match. Next search needs to start from beginning of match.
+ next_search_start = match_results[0].first - begin;
+ }
+ }
+ else
+ {
+ // No match. Next search can start with the new data.
+ next_search_start = end - begin;
+ }
+
+ // Check if buffer is full.
+ if (b.size() == b.max_size())
+ {
+ ec = error::not_found;
+ return 0;
+ }
+
+ // Need more data.
+ std::size_t bytes_available =
+ std::min<std::size_t>(512, b.max_size() - b.size());
+ b.commit(s.read_some(b.prepare(bytes_available), ec));
+ if (ec)
+ return 0;
+ }
+}
+
+template <typename SyncReadStream, typename Allocator, typename MatchCondition>
+std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ MatchCondition match_condition, boost::system::error_code& ec,
+ typename boost::enable_if<is_match_condition<MatchCondition> >::type*)
+{
+ std::size_t next_search_start = 0;
+ for (;;)
+ {
+ // Determine the range of the data to be searched.
+ typedef typename boost::asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = b.data();
+ iterator begin = iterator::begin(buffers);
+ iterator start = begin + next_search_start;
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ std::pair<iterator, bool> result = match_condition(start, end);
+ if (result.first != end)
+ {
+ if (result.second)
+ {
+ // Full match. We're done.
+ ec = boost::system::error_code();
+ return result.first - begin;
+ }
+ else
+ {
+ // Partial match. Next search needs to start from beginning of match.
+ next_search_start = result.first - begin;
+ }
+ }
+ else
+ {
+ // No match. Next search can start with the new data.
+ next_search_start = end - begin;
+ }
+
+ // Check if buffer is full.
+ if (b.size() == b.max_size())
+ {
+ ec = error::not_found;
+ return 0;
+ }
+
+ // Need more data.
+ std::size_t bytes_available =
+ std::min<std::size_t>(512, b.max_size() - b.size());
+ b.commit(s.read_some(b.prepare(bytes_available), ec));
+ if (ec)
+ return 0;
+ }
+}
+
+template <typename SyncReadStream, typename Allocator, typename MatchCondition>
+inline std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, MatchCondition match_condition,
+ typename boost::enable_if<is_match_condition<MatchCondition> >::type*)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read_until(s, b, match_condition, ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+namespace detail
+{
+ template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ class read_until_delim_handler
+ {
+ public:
+ read_until_delim_handler(AsyncReadStream& stream,
+ boost::asio::basic_streambuf<Allocator>& streambuf, char delim,
+ std::size_t next_search_start, ReadHandler handler)
+ : stream_(stream),
+ streambuf_(streambuf),
+ delim_(delim),
+ next_search_start_(next_search_start),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ // Check for errors.
+ if (ec)
+ {
+ std::size_t bytes = 0;
+ handler_(ec, bytes);
+ return;
+ }
+
+ // Commit received data to streambuf's get area.
+ streambuf_.commit(bytes_transferred);
+
+ // Determine the range of the data to be searched.
+ typedef typename boost::asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = streambuf_.data();
+ iterator begin = iterator::begin(buffers);
+ iterator start = begin + next_search_start_;
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ iterator iter = std::find(start, end, delim_);
+ if (iter != end)
+ {
+ // Found a match. We're done.
+ std::size_t bytes = iter - begin + 1;
+ handler_(ec, bytes);
+ return;
+ }
+
+ // No match. Check if buffer is full.
+ if (streambuf_.size() == streambuf_.max_size())
+ {
+ std::size_t bytes = 0;
+ boost::system::error_code ec(error::not_found);
+ handler_(ec, bytes);
+ return;
+ }
+
+ // Next search can start with the new data.
+ next_search_start_ = end - begin;
+
+ // Start a new asynchronous read operation to obtain more data.
+ std::size_t bytes_available =
+ std::min<std::size_t>(512, streambuf_.max_size() - streambuf_.size());
+ stream_.async_read_some(streambuf_.prepare(bytes_available), *this);
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ boost::asio::basic_streambuf<Allocator>& streambuf_;
+ char delim_;
+ std::size_t next_search_start_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_until_delim_handler<AsyncReadStream,
+ Allocator, ReadHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_until_delim_handler<AsyncReadStream,
+ Allocator, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream, typename Allocator,
+ typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_until_delim_handler<AsyncReadStream,
+ Allocator, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+void async_read_until(AsyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, char delim, ReadHandler handler)
+{
+ // Determine the range of the data to be searched.
+ typedef typename boost::asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = b.data();
+ iterator begin = iterator::begin(buffers);
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ iterator iter = std::find(begin, end, delim);
+ if (iter != end)
+ {
+ // Found a match. We're done.
+ boost::system::error_code ec;
+ std::size_t bytes = iter - begin + 1;
+ s.io_service().post(detail::bind_handler(handler, ec, bytes));
+ return;
+ }
+
+ // No match. Check if buffer is full.
+ if (b.size() == b.max_size())
+ {
+ boost::system::error_code ec(error::not_found);
+ s.io_service().post(detail::bind_handler(handler, ec, 0));
+ return;
+ }
+
+ // Start a new asynchronous read operation to obtain more data.
+ std::size_t bytes_available =
+ std::min<std::size_t>(512, b.max_size() - b.size());
+ s.async_read_some(b.prepare(bytes_available),
+ detail::read_until_delim_handler<AsyncReadStream, Allocator, ReadHandler>(
+ s, b, delim, end - begin, handler));
+}
+
+namespace detail
+{
+ template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ class read_until_delim_string_handler
+ {
+ public:
+ read_until_delim_string_handler(AsyncReadStream& stream,
+ boost::asio::basic_streambuf<Allocator>& streambuf,
+ const std::string& delim, std::size_t next_search_start,
+ ReadHandler handler)
+ : stream_(stream),
+ streambuf_(streambuf),
+ delim_(delim),
+ next_search_start_(next_search_start),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ // Check for errors.
+ if (ec)
+ {
+ std::size_t bytes = 0;
+ handler_(ec, bytes);
+ return;
+ }
+
+ // Commit received data to streambuf's get area.
+ streambuf_.commit(bytes_transferred);
+
+ // Determine the range of the data to be searched.
+ typedef typename boost::asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = streambuf_.data();
+ iterator begin = iterator::begin(buffers);
+ iterator start = begin + next_search_start_;
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ std::pair<iterator, bool> result = boost::asio::detail::partial_search(
+ start, end, delim_.begin(), delim_.end());
+ if (result.first != end)
+ {
+ if (result.second)
+ {
+ // Full match. We're done.
+ std::size_t bytes = result.first - begin + delim_.length();
+ handler_(ec, bytes);
+ return;
+ }
+ else
+ {
+ // Partial match. Next search needs to start from beginning of match.
+ next_search_start_ = result.first - begin;
+ }
+ }
+ else
+ {
+ // No match. Next search can start with the new data.
+ next_search_start_ = end - begin;
+ }
+
+ // Check if buffer is full.
+ if (streambuf_.size() == streambuf_.max_size())
+ {
+ std::size_t bytes = 0;
+ boost::system::error_code ec(error::not_found);
+ handler_(ec, bytes);
+ return;
+ }
+
+ // Start a new asynchronous read operation to obtain more data.
+ std::size_t bytes_available =
+ std::min<std::size_t>(512, streambuf_.max_size() - streambuf_.size());
+ stream_.async_read_some(streambuf_.prepare(bytes_available), *this);
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ boost::asio::basic_streambuf<Allocator>& streambuf_;
+ std::string delim_;
+ std::size_t next_search_start_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_until_delim_string_handler<AsyncReadStream,
+ Allocator, ReadHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_until_delim_string_handler<AsyncReadStream,
+ Allocator, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream,
+ typename Allocator, typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_until_delim_string_handler<AsyncReadStream,
+ Allocator, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+void async_read_until(AsyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, const std::string& delim,
+ ReadHandler handler)
+{
+ // Determine the range of the data to be searched.
+ typedef typename boost::asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = b.data();
+ iterator begin = iterator::begin(buffers);
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ std::size_t next_search_start;
+ std::pair<iterator, bool> result = boost::asio::detail::partial_search(
+ begin, end, delim.begin(), delim.end());
+ if (result.first != end)
+ {
+ if (result.second)
+ {
+ // Full match. We're done.
+ boost::system::error_code ec;
+ std::size_t bytes = result.first - begin + delim.length();
+ s.io_service().post(detail::bind_handler(handler, ec, bytes));
+ return;
+ }
+ else
+ {
+ // Partial match. Next search needs to start from beginning of match.
+ next_search_start = result.first - begin;
+ }
+ }
+ else
+ {
+ // No match. Next search can start with the new data.
+ next_search_start = end - begin;
+ }
+
+ // Check if buffer is full.
+ if (b.size() == b.max_size())
+ {
+ boost::system::error_code ec(error::not_found);
+ s.io_service().post(detail::bind_handler(handler, ec, 0));
+ return;
+ }
+
+ // Start a new asynchronous read operation to obtain more data.
+ std::size_t bytes_available =
+ std::min<std::size_t>(512, b.max_size() - b.size());
+ s.async_read_some(b.prepare(bytes_available),
+ detail::read_until_delim_string_handler<
+ AsyncReadStream, Allocator, ReadHandler>(
+ s, b, delim, next_search_start, handler));
+}
+
+namespace detail
+{
+ template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ class read_until_expr_handler
+ {
+ public:
+ read_until_expr_handler(AsyncReadStream& stream,
+ boost::asio::basic_streambuf<Allocator>& streambuf,
+ const boost::regex& expr, std::size_t next_search_start,
+ ReadHandler handler)
+ : stream_(stream),
+ streambuf_(streambuf),
+ expr_(expr),
+ next_search_start_(next_search_start),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ // Check for errors.
+ if (ec)
+ {
+ std::size_t bytes = 0;
+ handler_(ec, bytes);
+ return;
+ }
+
+ // Commit received data to streambuf's get area.
+ streambuf_.commit(bytes_transferred);
+
+ // Determine the range of the data to be searched.
+ typedef typename boost::asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = streambuf_.data();
+ iterator begin = iterator::begin(buffers);
+ iterator start = begin + next_search_start_;
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ boost::match_results<iterator> match_results;
+ if (boost::regex_search(start, end, match_results, expr_,
+ boost::match_default | boost::match_partial))
+ {
+ if (match_results[0].matched)
+ {
+ // Full match. We're done.
+ std::size_t bytes = match_results[0].second - begin;
+ handler_(ec, bytes);
+ return;
+ }
+ else
+ {
+ // Partial match. Next search needs to start from beginning of match.
+ next_search_start_ = match_results[0].first - begin;
+ }
+ }
+ else
+ {
+ // No match. Next search can start with the new data.
+ next_search_start_ = end - begin;
+ }
+
+ // Check if buffer is full.
+ if (streambuf_.size() == streambuf_.max_size())
+ {
+ std::size_t bytes = 0;
+ boost::system::error_code ec(error::not_found);
+ handler_(ec, bytes);
+ return;
+ }
+
+ // Start a new asynchronous read operation to obtain more data.
+ std::size_t bytes_available =
+ std::min<std::size_t>(512, streambuf_.max_size() - streambuf_.size());
+ stream_.async_read_some(streambuf_.prepare(bytes_available), *this);
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ boost::asio::basic_streambuf<Allocator>& streambuf_;
+ boost::regex expr_;
+ std::size_t next_search_start_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_until_expr_handler<AsyncReadStream,
+ Allocator, ReadHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_until_expr_handler<AsyncReadStream,
+ Allocator, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream, typename Allocator,
+ typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_until_expr_handler<AsyncReadStream,
+ Allocator, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+void async_read_until(AsyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
+ ReadHandler handler)
+{
+ // Determine the range of the data to be searched.
+ typedef typename boost::asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = b.data();
+ iterator begin = iterator::begin(buffers);
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ std::size_t next_search_start;
+ boost::match_results<iterator> match_results;
+ if (boost::regex_search(begin, end, match_results, expr,
+ boost::match_default | boost::match_partial))
+ {
+ if (match_results[0].matched)
+ {
+ // Full match. We're done.
+ boost::system::error_code ec;
+ std::size_t bytes = match_results[0].second - begin;
+ s.io_service().post(detail::bind_handler(handler, ec, bytes));
+ return;
+ }
+ else
+ {
+ // Partial match. Next search needs to start from beginning of match.
+ next_search_start = match_results[0].first - begin;
+ }
+ }
+ else
+ {
+ // No match. Next search can start with the new data.
+ next_search_start = end - begin;
+ }
+
+ // Check if buffer is full.
+ if (b.size() == b.max_size())
+ {
+ boost::system::error_code ec(error::not_found);
+ s.io_service().post(detail::bind_handler(handler, ec, 0));
+ return;
+ }
+
+ // Start a new asynchronous read operation to obtain more data.
+ std::size_t bytes_available =
+ std::min<std::size_t>(512, b.max_size() - b.size());
+ s.async_read_some(b.prepare(bytes_available),
+ detail::read_until_expr_handler<AsyncReadStream, Allocator, ReadHandler>(
+ s, b, expr, next_search_start, handler));
+}
+
+namespace detail
+{
+ template <typename AsyncReadStream, typename Allocator,
+ typename MatchCondition, typename ReadHandler>
+ class read_until_match_handler
+ {
+ public:
+ read_until_match_handler(AsyncReadStream& stream,
+ boost::asio::basic_streambuf<Allocator>& streambuf,
+ MatchCondition match_condition, std::size_t next_search_start,
+ ReadHandler handler)
+ : stream_(stream),
+ streambuf_(streambuf),
+ match_condition_(match_condition),
+ next_search_start_(next_search_start),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ // Check for errors.
+ if (ec)
+ {
+ std::size_t bytes = 0;
+ handler_(ec, bytes);
+ return;
+ }
+
+ // Commit received data to streambuf's get area.
+ streambuf_.commit(bytes_transferred);
+
+ // Determine the range of the data to be searched.
+ typedef typename boost::asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = streambuf_.data();
+ iterator begin = iterator::begin(buffers);
+ iterator start = begin + next_search_start_;
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ std::pair<iterator, bool> result = match_condition_(start, end);
+ if (result.first != end)
+ {
+ if (result.second)
+ {
+ // Full match. We're done.
+ std::size_t bytes = result.first - begin;
+ handler_(ec, bytes);
+ return;
+ }
+ else
+ {
+ // Partial match. Next search needs to start from beginning of match.
+ next_search_start_ = result.first - begin;
+ }
+ }
+ else
+ {
+ // No match. Next search can start with the new data.
+ next_search_start_ = end - begin;
+ }
+
+ // Check if buffer is full.
+ if (streambuf_.size() == streambuf_.max_size())
+ {
+ std::size_t bytes = 0;
+ boost::system::error_code ec(error::not_found);
+ handler_(ec, bytes);
+ return;
+ }
+
+ // Start a new asynchronous read operation to obtain more data.
+ std::size_t bytes_available =
+ std::min<std::size_t>(512, streambuf_.max_size() - streambuf_.size());
+ stream_.async_read_some(streambuf_.prepare(bytes_available), *this);
+ }
+
+ //private:
+ AsyncReadStream& stream_;
+ boost::asio::basic_streambuf<Allocator>& streambuf_;
+ MatchCondition match_condition_;
+ std::size_t next_search_start_;
+ ReadHandler handler_;
+ };
+
+ template <typename AsyncReadStream, typename Allocator,
+ typename MatchCondition, typename ReadHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ read_until_match_handler<AsyncReadStream,
+ Allocator, MatchCondition, ReadHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+ }
+
+ template <typename AsyncReadStream, typename Allocator,
+ typename MatchCondition, typename ReadHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ read_until_match_handler<AsyncReadStream,
+ Allocator, MatchCondition, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncReadStream, typename Allocator,
+ typename MatchCondition, typename ReadHandler>
+ inline void asio_handler_invoke(const Function& function,
+ read_until_match_handler<AsyncReadStream,
+ Allocator, MatchCondition, ReadHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncReadStream, typename Allocator,
+ typename MatchCondition, typename ReadHandler>
+void async_read_until(AsyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ MatchCondition match_condition, ReadHandler handler,
+ typename boost::enable_if<is_match_condition<MatchCondition> >::type*)
+{
+ // Determine the range of the data to be searched.
+ typedef typename boost::asio::basic_streambuf<
+ Allocator>::const_buffers_type const_buffers_type;
+ typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
+ const_buffers_type buffers = b.data();
+ iterator begin = iterator::begin(buffers);
+ iterator end = iterator::end(buffers);
+
+ // Look for a match.
+ std::size_t next_search_start;
+ std::pair<iterator, bool> result = match_condition(begin, end);
+ if (result.first != end)
+ {
+ if (result.second)
+ {
+ // Full match. We're done.
+ boost::system::error_code ec;
+ std::size_t bytes = result.first - begin;
+ s.io_service().post(detail::bind_handler(handler, ec, bytes));
+ return;
+ }
+ else
+ {
+ // Partial match. Next search needs to start from beginning of match.
+ next_search_start = result.first - begin;
+ }
+ }
+ else
+ {
+ // No match. Next search can start with the new data.
+ next_search_start = end - begin;
+ }
+
+ // Check if buffer is full.
+ if (b.size() == b.max_size())
+ {
+ boost::system::error_code ec(error::not_found);
+ s.io_service().post(detail::bind_handler(handler, ec, 0));
+ return;
+ }
+
+ // Start a new asynchronous read operation to obtain more data.
+ std::size_t bytes_available =
+ std::min<std::size_t>(512, b.max_size() - b.size());
+ s.async_read_some(b.prepare(bytes_available),
+ detail::read_until_match_handler<
+ AsyncReadStream, Allocator, MatchCondition, ReadHandler>(
+ s, b, match_condition, next_search_start, handler));
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_READ_UNTIL_IPP
Added: branches/CMake/release/libs/asio/include/boost/asio/impl/serial_port_base.ipp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/impl/serial_port_base.ipp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,541 @@
+//
+// serial_port_base.ipp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info_at_[hidden])
+//
+// Distributed under the 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 BOOST_ASIO_SERIAL_PORT_BASE_IPP
+#define BOOST_ASIO_SERIAL_PORT_BASE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+inline serial_port_base::baud_rate::baud_rate(unsigned int rate)
+ : value_(rate)
+{
+}
+
+inline unsigned int serial_port_base::baud_rate::value() const
+{
+ return value_;
+}
+
+inline boost::system::error_code serial_port_base::baud_rate::store(
+ BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ storage.BaudRate = value_;
+#else
+ speed_t baud;
+ switch (value_)
+ {
+ // Do POSIX-specified rates first.
+ case 0: baud = B0; break;
+ case 50: baud = B50; break;
+ case 75: baud = B75; break;
+ case 110: baud = B110; break;
+ case 134: baud = B134; break;
+ case 150: baud = B150; break;
+ case 200: baud = B200; break;
+ case 300: baud = B300; break;
+ case 600: baud = B600; break;
+ case 1200: baud = B1200; break;
+ case 1800: baud = B1800; break;
+ case 2400: baud = B2400; break;
+ case 4800: baud = B4800; break;
+ case 9600: baud = B9600; break;
+ case 19200: baud = B19200; break;
+ case 38400: baud = B38400; break;
+ // And now the extended ones conditionally.
+# ifdef B7200
+ case 7200: baud = B7200; break;
+# endif
+# ifdef B14400
+ case 14400: baud = B14400; break;
+# endif
+# ifdef B57600
+ case 57600: baud = B57600; break;
+# endif
+# ifdef B115200
+ case 115200: baud = B115200; break;
+# endif
+# ifdef B230400
+ case 230400: baud = B230400; break;
+# endif
+# ifdef B460800
+ case 460800: baud = B460800; break;
+# endif
+# ifdef B500000
+ case 500000: baud = B500000; break;
+# endif
+# ifdef B576000
+ case 576000: baud = B576000; break;
+# endif
+# ifdef B921600
+ case 921600: baud = B921600; break;
+# endif
+# ifdef B1000000
+ case 1000000: baud = B1000000; break;
+# endif
+# ifdef B1152000
+ case 1152000: baud = B1152000; break;
+# endif
+# ifdef B2000000
+ case 2000000: baud = B2000000; break;
+# endif
+# ifdef B3000000
+ case 3000000: baud = B3000000; break;
+# endif
+# ifdef B3500000
+ case 3500000: baud = B3500000; break;
+# endif
+# ifdef B4000000
+ case 4000000: baud = B4000000; break;
+# endif
+ default:
+ baud = B0;
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+# if defined(_BSD_SOURCE)
+ ::cfsetspeed(&storage, baud);
+# else
+ ::cfsetispeed(&storage, baud);
+ ::cfsetospeed(&storage, baud);
+# endif
+#endif
+ ec = boost::system::error_code();
+ return ec;
+}
+
+inline boost::system::error_code serial_port_base::baud_rate::load(
+ const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ value_ = storage.BaudRate;
+#else
+ speed_t baud = ::cfgetospeed(&storage);
+ switch (baud)
+ {
+ // First do those specified by POSIX.
+ case B0: value_ = 0; break;
+ case B50: value_ = 50; break;
+ case B75: value_ = 75; break;
+ case B110: value_ = 110; break;
+ case B134: value_ = 134; break;
+ case B150: value_ = 150; break;
+ case B200: value_ = 200; break;
+ case B300: value_ = 300; break;
+ case B600: value_ = 600; break;
+ case B1200: value_ = 1200; break;
+ case B1800: value_ = 1800; break;
+ case B2400: value_ = 2400; break;
+ case B4800: value_ = 4800; break;
+ case B9600: value_ = 9600; break;
+ case B19200: value_ = 19200; break;
+ case B38400: value_ = 38400; break;
+ // Now conditionally handle a bunch of extended rates.
+# ifdef B7200
+ case B7200: value_ = 7200; break;
+# endif
+# ifdef B14400
+ case B14400: value_ = 14400; break;
+# endif
+# ifdef B57600
+ case B57600: value_ = 57600; break;
+# endif
+# ifdef B115200
+ case B115200: value_ = 115200; break;
+# endif
+# ifdef B230400
+ case B230400: value_ = 230400; break;
+# endif
+# ifdef B460800
+ case B460800: value_ = 460800; break;
+# endif
+# ifdef B500000
+ case B500000: value_ = 500000; break;
+# endif
+# ifdef B576000
+ case B576000: value_ = 576000; break;
+# endif
+# ifdef B921600
+ case B921600: value_ = 921600; break;
+# endif
+# ifdef B1000000
+ case B1000000: value_ = 1000000; break;
+# endif
+# ifdef B1152000
+ case B1152000: value_ = 1152000; break;
+# endif
+# ifdef B2000000
+ case B2000000: value_ = 2000000; break;
+# endif
+# ifdef B3000000
+ case B3000000: value_ = 3000000; break;
+# endif
+# ifdef B3500000
+ case B3500000: value_ = 3500000; break;
+# endif
+# ifdef B4000000
+ case B4000000: value_ = 4000000; break;
+# endif
+ default:
+ value_ = 0;
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+#endif
+ ec = boost::system::error_code();
+ return ec;
+}
+
+inline serial_port_base::flow_control::flow_control(
+ serial_port_base::flow_control::type t)
+ : value_(t)
+{
+ if (t != none && t != software && t != hardware)
+ throw std::out_of_range("invalid flow_control value");
+}
+
+inline serial_port_base::flow_control::type
+serial_port_base::flow_control::value() const
+{
+ return value_;
+}
+
+inline boost::system::error_code serial_port_base::flow_control::store(
+ BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ storage.fOutxCtsFlow = FALSE;
+ storage.fOutxDsrFlow = FALSE;
+ storage.fTXContinueOnXoff = TRUE;
+ storage.fDtrControl = DTR_CONTROL_ENABLE;
+ storage.fDsrSensitivity = FALSE;
+ storage.fOutX = FALSE;
+ storage.fInX = FALSE;
+ storage.fRtsControl = RTS_CONTROL_ENABLE;
+ switch (value_)
+ {
+ case none:
+ break;
+ case software:
+ storage.fOutX = TRUE;
+ storage.fInX = TRUE;
+ break;
+ case hardware:
+ storage.fOutxCtsFlow = TRUE;
+ storage.fRtsControl = RTS_CONTROL_HANDSHAKE;
+ break;
+ default:
+ break;
+ }
+#else
+ switch (value_)
+ {
+ case none:
+ storage.c_iflag &= ~(IXOFF | IXON);
+# if defined(_BSD_SOURCE)
+ storage.c_cflag &= ~CRTSCTS;
+# endif
+ break;
+ case software:
+ storage.c_iflag |= IXOFF | IXON;
+# if defined(_BSD_SOURCE)
+ storage.c_cflag &= ~CRTSCTS;
+# endif
+ break;
+ case hardware:
+# if defined(_BSD_SOURCE)
+ storage.c_iflag &= ~(IXOFF | IXON);
+ storage.c_cflag |= CRTSCTS;
+ break;
+# else
+ ec = boost::asio::error::operation_not_supported;
+ return ec;
+# endif
+ default:
+ break;
+ }
+#endif
+ ec = boost::system::error_code();
+ return ec;
+}
+
+inline boost::system::error_code serial_port_base::flow_control::load(
+ const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ if (storage.fOutX && storage.fInX)
+ {
+ value_ = software;
+ }
+ else if (storage.fOutxCtsFlow && storage.fRtsControl == RTS_CONTROL_HANDSHAKE)
+ {
+ value_ = hardware;
+ }
+ else
+ {
+ value_ = none;
+ }
+#else
+ if (storage.c_iflag & (IXOFF | IXON))
+ {
+ value_ = software;
+ }
+ else if (storage.c_cflag & CRTSCTS)
+ {
+ value_ = hardware;
+ }
+ else
+ {
+ value_ = none;
+ }
+#endif
+ ec = boost::system::error_code();
+ return ec;
+}
+
+inline serial_port_base::parity::parity(serial_port_base::parity::type t)
+ : value_(t)
+{
+ if (t != none && t != odd && t != even)
+ throw std::out_of_range("invalid parity value");
+}
+
+inline serial_port_base::parity::type serial_port_base::parity::value() const
+{
+ return value_;
+}
+
+inline boost::system::error_code serial_port_base::parity::store(
+ BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ switch (value_)
+ {
+ case none:
+ storage.fParity = FALSE;
+ storage.Parity = NOPARITY;
+ break;
+ case odd:
+ storage.fParity = TRUE;
+ storage.Parity = ODDPARITY;
+ break;
+ case even:
+ storage.fParity = TRUE;
+ storage.Parity = EVENPARITY;
+ break;
+ default:
+ break;
+ }
+#else
+ switch (value_)
+ {
+ case none:
+ storage.c_iflag |= IGNPAR;
+ storage.c_cflag &= ~(PARENB | PARODD);
+ break;
+ case even:
+ storage.c_iflag &= ~(IGNPAR | PARMRK);
+ storage.c_iflag |= INPCK;
+ storage.c_cflag |= PARENB;
+ storage.c_cflag &= ~PARODD;
+ break;
+ case odd:
+ storage.c_iflag &= ~(IGNPAR | PARMRK);
+ storage.c_iflag |= INPCK;
+ storage.c_cflag |= (PARENB | PARODD);
+ break;
+ default:
+ break;
+ }
+#endif
+ ec = boost::system::error_code();
+ return ec;
+}
+
+inline boost::system::error_code serial_port_base::parity::load(
+ const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ if (storage.Parity == EVENPARITY)
+ {
+ value_ = even;
+ }
+ else if (storage.Parity == ODDPARITY)
+ {
+ value_ = odd;
+ }
+ else
+ {
+ value_ = none;
+ }
+#else
+ if (storage.c_cflag & PARENB)
+ {
+ if (storage.c_cflag & PARODD)
+ {
+ value_ = odd;
+ }
+ else
+ {
+ value_ = even;
+ }
+ }
+ else
+ {
+ value_ = none;
+ }
+#endif
+ ec = boost::system::error_code();
+ return ec;
+}
+
+inline serial_port_base::stop_bits::stop_bits(
+ serial_port_base::stop_bits::type t)
+ : value_(t)
+{
+ if (t != one && t != onepointfive && t != two)
+ throw std::out_of_range("invalid stop_bits value");
+}
+
+inline serial_port_base::stop_bits::type
+serial_port_base::stop_bits::value() const
+{
+ return value_;
+}
+
+inline boost::system::error_code serial_port_base::stop_bits::store(
+ BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ switch (value_)
+ {
+ case one:
+ storage.StopBits = ONESTOPBIT;
+ break;
+ case onepointfive:
+ storage.StopBits = ONE5STOPBITS;
+ break;
+ case two:
+ storage.StopBits = TWOSTOPBITS;
+ break;
+ default:
+ break;
+ }
+#else
+ switch (value_)
+ {
+ case one:
+ storage.c_cflag &= ~CSTOPB;
+ break;
+ case two:
+ storage.c_cflag |= CSTOPB;
+ break;
+ default:
+ ec = boost::asio::error::operation_not_supported;
+ return ec;
+ }
+#endif
+ ec = boost::system::error_code();
+ return ec;
+}
+
+inline boost::system::error_code serial_port_base::stop_bits::load(
+ const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ if (storage.StopBits == ONESTOPBIT)
+ {
+ value_ = one;
+ }
+ else if (storage.StopBits == ONE5STOPBITS)
+ {
+ value_ = onepointfive;
+ }
+ else if (storage.StopBits == TWOSTOPBITS)
+ {
+ value_ = two;
+ }
+ else
+ {
+ value_ = one;
+ }
+#else
+ value_ = (storage.c_cflag & CSTOPB) ? two : one;
+#endif
+ ec = boost::system::error_code();
+ return ec;
+}
+
+inline serial_port_base::character_size::character_size(unsigned int t)
+ : value_(t)
+{
+ if (t < 5 || t > 8)
+ throw std::out_of_range("invalid character_size value");
+}
+
+inline unsigned int serial_port_base::character_size::value() const
+{
+ return value_;
+}
+
+inline boost::system::error_code serial_port_base::character_size::store(
+ BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ storage.ByteSize = value_;
+#else
+ storage.c_cflag &= ~CSIZE;
+ switch (value_)
+ {
+ case 5: storage.c_cflag |= CS5; break;
+ case 6: storage.c_cflag |= CS6; break;
+ case 7: storage.c_cflag |= CS7; break;
+ case 8: storage.c_cflag |= CS8; break;
+ default: break;
+ }
+#endif
+ ec = boost::system::error_code();
+ return ec;
+}
+
+inline boost::system::error_code serial_port_base::character_size::load(
+ const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
+{
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ value_ = storage.ByteSize;
+#else
+ if ((storage.c_cflag & CSIZE) == CS5) { value_ = 5; }
+ else if ((storage.c_cflag & CSIZE) == CS6) { value_ = 6; }
+ else if ((storage.c_cflag & CSIZE) == CS7) { value_ = 7; }
+ else if ((storage.c_cflag & CSIZE) == CS8) { value_ = 8; }
+ else
+ {
+ // Hmmm, use 8 for now.
+ value_ = 8;
+ }
+#endif
+ ec = boost::system::error_code();
+ return ec;
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SERIAL_PORT_BASE_IPP
Added: branches/CMake/release/libs/asio/include/boost/asio/impl/write.ipp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/impl/write.ipp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,281 @@
+//
+// write.ipp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_WRITE_IPP
+#define BOOST_ASIO_WRITE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/completion_condition.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/consuming_buffers.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+
+template <typename SyncWriteStream, typename ConstBufferSequence,
+ typename CompletionCondition>
+std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition, boost::system::error_code& ec)
+{
+ boost::asio::detail::consuming_buffers<
+ const_buffer, ConstBufferSequence> tmp(buffers);
+ std::size_t total_transferred = 0;
+ while (tmp.begin() != tmp.end())
+ {
+ std::size_t bytes_transferred = s.write_some(tmp, ec);
+ tmp.consume(bytes_transferred);
+ total_transferred += bytes_transferred;
+ if (completion_condition(ec, total_transferred))
+ return total_transferred;
+ }
+ ec = boost::system::error_code();
+ return total_transferred;
+}
+
+template <typename SyncWriteStream, typename ConstBufferSequence>
+inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncWriteStream, typename ConstBufferSequence,
+ typename CompletionCondition>
+inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = write(s, buffers, completion_condition, ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncWriteStream, typename Allocator,
+ typename CompletionCondition>
+std::size_t write(SyncWriteStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, boost::system::error_code& ec)
+{
+ std::size_t bytes_transferred = write(s, b.data(), completion_condition, ec);
+ b.consume(bytes_transferred);
+ return bytes_transferred;
+}
+
+template <typename SyncWriteStream, typename Allocator>
+inline std::size_t write(SyncWriteStream& s,
+ boost::asio::basic_streambuf<Allocator>& b)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = write(s, b, transfer_all(), ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncWriteStream, typename Allocator,
+ typename CompletionCondition>
+inline std::size_t write(SyncWriteStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = write(s, b, completion_condition, ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+namespace detail
+{
+ template <typename AsyncWriteStream, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+ class write_handler
+ {
+ public:
+ typedef boost::asio::detail::consuming_buffers<
+ const_buffer, ConstBufferSequence> buffers_type;
+
+ write_handler(AsyncWriteStream& stream, const buffers_type& buffers,
+ CompletionCondition completion_condition, WriteHandler handler)
+ : stream_(stream),
+ buffers_(buffers),
+ total_transferred_(0),
+ completion_condition_(completion_condition),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ total_transferred_ += bytes_transferred;
+ buffers_.consume(bytes_transferred);
+ if (completion_condition_(ec, total_transferred_)
+ || buffers_.begin() == buffers_.end())
+ {
+ handler_(ec, total_transferred_);
+ }
+ else
+ {
+ stream_.async_write_some(buffers_, *this);
+ }
+ }
+
+ //private:
+ AsyncWriteStream& stream_;
+ buffers_type buffers_;
+ std::size_t total_transferred_;
+ CompletionCondition completion_condition_;
+ WriteHandler handler_;
+ };
+
+ template <typename AsyncWriteStream, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ write_handler<AsyncWriteStream, ConstBufferSequence,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+ }
+
+ template <typename AsyncWriteStream, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ write_handler<AsyncWriteStream, ConstBufferSequence,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncWriteStream,
+ typename ConstBufferSequence, typename CompletionCondition,
+ typename WriteHandler>
+ inline void asio_handler_invoke(const Function& function,
+ write_handler<AsyncWriteStream, ConstBufferSequence,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncWriteStream, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition, WriteHandler handler)
+{
+ boost::asio::detail::consuming_buffers<
+ const_buffer, ConstBufferSequence> tmp(buffers);
+ s.async_write_some(tmp,
+ detail::write_handler<AsyncWriteStream, ConstBufferSequence,
+ CompletionCondition, WriteHandler>(
+ s, tmp, completion_condition, handler));
+}
+
+template <typename AsyncWriteStream, typename ConstBufferSequence,
+ typename WriteHandler>
+inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
+ WriteHandler handler)
+{
+ async_write(s, buffers, transfer_all(), handler);
+}
+
+namespace detail
+{
+ template <typename AsyncWriteStream, typename Allocator,
+ typename WriteHandler>
+ class write_streambuf_handler
+ {
+ public:
+ write_streambuf_handler(boost::asio::basic_streambuf<Allocator>& streambuf,
+ WriteHandler handler)
+ : streambuf_(streambuf),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ streambuf_.consume(bytes_transferred);
+ handler_(ec, bytes_transferred);
+ }
+
+ //private:
+ boost::asio::basic_streambuf<Allocator>& streambuf_;
+ WriteHandler handler_;
+ };
+
+ template <typename AsyncWriteStream, typename Allocator,
+ typename WriteHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ write_streambuf_handler<AsyncWriteStream,
+ Allocator, WriteHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+ }
+
+ template <typename AsyncWriteStream, typename Allocator,
+ typename WriteHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ write_streambuf_handler<AsyncWriteStream,
+ Allocator, WriteHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncWriteStream, typename Allocator,
+ typename WriteHandler>
+ inline void asio_handler_invoke(const Function& function,
+ write_streambuf_handler<AsyncWriteStream,
+ Allocator, WriteHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncWriteStream, typename Allocator,
+ typename CompletionCondition, typename WriteHandler>
+inline void async_write(AsyncWriteStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, WriteHandler handler)
+{
+ async_write(s, b.data(), completion_condition,
+ detail::write_streambuf_handler<
+ AsyncWriteStream, Allocator, WriteHandler>(b, handler));
+}
+
+template <typename AsyncWriteStream, typename Allocator, typename WriteHandler>
+inline void async_write(AsyncWriteStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, WriteHandler handler)
+{
+ async_write(s, b, transfer_all(), handler);
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_WRITE_IPP
Added: branches/CMake/release/libs/asio/include/boost/asio/impl/write_at.ipp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/impl/write_at.ipp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,298 @@
+//
+// write_at.ipp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_WRITE_AT_IPP
+#define BOOST_ASIO_WRITE_AT_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/completion_condition.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/consuming_buffers.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+
+template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename CompletionCondition>
+std::size_t write_at(SyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition, boost::system::error_code& ec)
+{
+ boost::asio::detail::consuming_buffers<
+ const_buffer, ConstBufferSequence> tmp(buffers);
+ std::size_t total_transferred = 0;
+ while (tmp.begin() != tmp.end())
+ {
+ std::size_t bytes_transferred = d.write_some_at(
+ offset + total_transferred, tmp, ec);
+ tmp.consume(bytes_transferred);
+ total_transferred += bytes_transferred;
+ if (completion_condition(ec, total_transferred))
+ return total_transferred;
+ }
+ ec = boost::system::error_code();
+ return total_transferred;
+}
+
+template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>
+inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, const ConstBufferSequence& buffers)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = write_at(
+ d, offset, buffers, transfer_all(), ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename CompletionCondition>
+inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = write_at(
+ d, offset, buffers, completion_condition, ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncRandomAccessWriteDevice, typename Allocator,
+ typename CompletionCondition>
+std::size_t write_at(SyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, boost::system::error_code& ec)
+{
+ std::size_t bytes_transferred = write_at(
+ d, offset, b.data(), completion_condition, ec);
+ b.consume(bytes_transferred);
+ return bytes_transferred;
+}
+
+template <typename SyncRandomAccessWriteDevice, typename Allocator>
+inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, boost::asio::basic_streambuf<Allocator>& b)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = write_at(d, offset, b, transfer_all(), ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+template <typename SyncRandomAccessWriteDevice, typename Allocator,
+ typename CompletionCondition>
+inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = write_at(
+ d, offset, b, completion_condition, ec);
+ boost::asio::detail::throw_error(ec);
+ return bytes_transferred;
+}
+
+namespace detail
+{
+ template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+ class write_at_handler
+ {
+ public:
+ typedef boost::asio::detail::consuming_buffers<
+ const_buffer, ConstBufferSequence> buffers_type;
+
+ write_at_handler(AsyncRandomAccessWriteDevice& stream,
+ boost::uint64_t offset, const buffers_type& buffers,
+ CompletionCondition completion_condition, WriteHandler handler)
+ : stream_(stream),
+ buffers_(buffers),
+ offset_(offset),
+ total_transferred_(0),
+ completion_condition_(completion_condition),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ total_transferred_ += bytes_transferred;
+ buffers_.consume(bytes_transferred);
+ if (completion_condition_(ec, total_transferred_)
+ || buffers_.begin() == buffers_.end())
+ {
+ handler_(ec, total_transferred_);
+ }
+ else
+ {
+ stream_.async_write_some_at(
+ offset_ + total_transferred_, buffers_, *this);
+ }
+ }
+
+ //private:
+ AsyncRandomAccessWriteDevice& stream_;
+ buffers_type buffers_;
+ boost::uint64_t offset_;
+ std::size_t total_transferred_;
+ CompletionCondition completion_condition_;
+ WriteHandler handler_;
+ };
+
+ template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ write_at_handler<AsyncRandomAccessWriteDevice, ConstBufferSequence,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+ }
+
+ template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ write_at_handler<AsyncRandomAccessWriteDevice, ConstBufferSequence,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncRandomAccessWriteDevice,
+ typename ConstBufferSequence, typename CompletionCondition,
+ typename WriteHandler>
+ inline void asio_handler_invoke(const Function& function,
+ write_at_handler<AsyncRandomAccessWriteDevice, ConstBufferSequence,
+ CompletionCondition, WriteHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+inline void async_write_at(AsyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition, WriteHandler handler)
+{
+ boost::asio::detail::consuming_buffers<
+ const_buffer, ConstBufferSequence> tmp(buffers);
+ d.async_write_some_at(offset, tmp,
+ detail::write_at_handler<AsyncRandomAccessWriteDevice,
+ ConstBufferSequence, CompletionCondition, WriteHandler>(
+ d, offset, tmp, completion_condition, handler));
+}
+
+template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename WriteHandler>
+inline void async_write_at(AsyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, const ConstBufferSequence& buffers,
+ WriteHandler handler)
+{
+ async_write_at(d, offset, buffers, transfer_all(), handler);
+}
+
+namespace detail
+{
+ template <typename AsyncRandomAccessWriteDevice, typename Allocator,
+ typename WriteHandler>
+ class write_at_streambuf_handler
+ {
+ public:
+ write_at_streambuf_handler(
+ boost::asio::basic_streambuf<Allocator>& streambuf,
+ WriteHandler handler)
+ : streambuf_(streambuf),
+ handler_(handler)
+ {
+ }
+
+ void operator()(const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
+ {
+ streambuf_.consume(bytes_transferred);
+ handler_(ec, bytes_transferred);
+ }
+
+ //private:
+ boost::asio::basic_streambuf<Allocator>& streambuf_;
+ WriteHandler handler_;
+ };
+
+ template <typename AsyncRandomAccessWriteDevice, typename Allocator,
+ typename WriteHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ write_at_streambuf_handler<AsyncRandomAccessWriteDevice,
+ Allocator, WriteHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, &this_handler->handler_);
+ }
+
+ template <typename AsyncRandomAccessWriteDevice, typename Allocator,
+ typename WriteHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ write_at_streambuf_handler<AsyncRandomAccessWriteDevice,
+ Allocator, WriteHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, &this_handler->handler_);
+ }
+
+ template <typename Function, typename AsyncRandomAccessWriteDevice,
+ typename Allocator, typename WriteHandler>
+ inline void asio_handler_invoke(const Function& function,
+ write_at_streambuf_handler<AsyncRandomAccessWriteDevice,
+ Allocator, WriteHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, &this_handler->handler_);
+ }
+} // namespace detail
+
+template <typename AsyncRandomAccessWriteDevice, typename Allocator,
+ typename CompletionCondition, typename WriteHandler>
+inline void async_write_at(AsyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, WriteHandler handler)
+{
+ async_write_at(d, offset, b.data(), completion_condition,
+ detail::write_at_streambuf_handler<
+ AsyncRandomAccessWriteDevice, Allocator, WriteHandler>(b, handler));
+}
+
+template <typename AsyncRandomAccessWriteDevice, typename Allocator,
+ typename WriteHandler>
+inline void async_write_at(AsyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, boost::asio::basic_streambuf<Allocator>& b,
+ WriteHandler handler)
+{
+ async_write_at(d, offset, b, transfer_all(), handler);
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_WRITE_AT_IPP
Added: branches/CMake/release/libs/asio/include/boost/asio/io_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/io_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,521 @@
+//
+// io_service.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IO_SERVICE_HPP
+#define BOOST_ASIO_IO_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <stdexcept>
+#include <typeinfo>
+#include <boost/config.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/dev_poll_reactor_fwd.hpp>
+#include <boost/asio/detail/epoll_reactor_fwd.hpp>
+#include <boost/asio/detail/kqueue_reactor_fwd.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/select_reactor_fwd.hpp>
+#include <boost/asio/detail/service_registry_fwd.hpp>
+#include <boost/asio/detail/signal_init.hpp>
+#include <boost/asio/detail/task_io_service_fwd.hpp>
+#include <boost/asio/detail/win_iocp_io_service_fwd.hpp>
+#include <boost/asio/detail/winsock_init.hpp>
+#include <boost/asio/detail/wrapped_handler.hpp>
+
+namespace boost {
+namespace asio {
+
+class io_service;
+template <typename Service> Service& use_service(io_service& ios);
+template <typename Service> void add_service(io_service& ios, Service* svc);
+template <typename Service> bool has_service(io_service& ios);
+
+/// Provides core I/O functionality.
+/**
+ * The io_service class provides the core I/O functionality for users of the
+ * asynchronous I/O objects, including:
+ *
+ * @li boost::asio::ip::tcp::socket
+ * @li boost::asio::ip::tcp::acceptor
+ * @li boost::asio::ip::udp::socket
+ * @li boost::asio::deadline_timer.
+ *
+ * The io_service class also includes facilities intended for developers of
+ * custom asynchronous services.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Safe, with the exception that calling reset()
+ * while there are unfinished run() calls results in undefined behaviour.
+ *
+ * @par Concepts:
+ * Dispatcher.
+ *
+ * @par Effect of exceptions thrown from handlers
+ *
+ * If an exception is thrown from a handler, the exception is allowed to
+ * propagate through the throwing thread's invocation of
+ * boost::asio::io_service::run(), boost::asio::io_service::run_one(),
+ * boost::asio::io_service::poll() or boost::asio::io_service::poll_one().
+ * No other threads that are calling any of these functions are affected. It is
+ * then the responsibility of the application to catch the exception.
+ *
+ * After the exception has been caught, the
+ * boost::asio::io_service::run(), boost::asio::io_service::run_one(),
+ * boost::asio::io_service::poll() or boost::asio::io_service::poll_one()
+ * call may be restarted @em without the need for an intervening call to
+ * boost::asio::io_service::reset(). This allows the thread to rejoin the
+ * io_service's thread pool without impacting any other threads in the pool.
+ *
+ * For example:
+ *
+ * @code
+ * boost::asio::io_service io_service;
+ * ...
+ * for (;;)
+ * {
+ * try
+ * {
+ * io_service.run();
+ * break; // run() exited normally
+ * }
+ * catch (my_exception& e)
+ * {
+ * // Deal with exception as appropriate.
+ * }
+ * }
+ * @endcode
+ */
+class io_service
+ : private noncopyable
+{
+private:
+ // The type of the platform-specific implementation.
+#if defined(BOOST_ASIO_HAS_IOCP)
+ typedef detail::win_iocp_io_service impl_type;
+#elif defined(BOOST_ASIO_HAS_EPOLL)
+ typedef detail::task_io_service<detail::epoll_reactor<false> > impl_type;
+#elif defined(BOOST_ASIO_HAS_KQUEUE)
+ typedef detail::task_io_service<detail::kqueue_reactor<false> > impl_type;
+#elif defined(BOOST_ASIO_HAS_DEV_POLL)
+ typedef detail::task_io_service<detail::dev_poll_reactor<false> > impl_type;
+#else
+ typedef detail::task_io_service<detail::select_reactor<false> > impl_type;
+#endif
+
+public:
+ class work;
+ friend class work;
+
+ class id;
+
+ class service;
+
+ class strand;
+
+ /// Constructor.
+ io_service();
+
+ /// Constructor.
+ /**
+ * Construct with a hint about the required level of concurrency.
+ *
+ * @param concurrency_hint A suggestion to the implementation on how many
+ * threads it should allow to run simultaneously.
+ */
+ explicit io_service(std::size_t concurrency_hint);
+
+ /// Destructor.
+ ~io_service();
+
+ /// Run the io_service's event processing loop.
+ /**
+ * The run() function blocks until all work has finished and there are no
+ * more handlers to be dispatched, or until the io_service has been stopped.
+ *
+ * Multiple threads may call the run() function to set up a pool of threads
+ * from which the io_service may execute handlers. All threads that are
+ * waiting in the pool are equivalent and the io_service may choose any one
+ * of them to invoke a handler.
+ *
+ * The run() function may be safely called again once it has completed only
+ * after a call to reset().
+ *
+ * @return The number of handlers that were executed.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ std::size_t run();
+
+ /// Run the io_service's event processing loop.
+ /**
+ * The run() function blocks until all work has finished and there are no
+ * more handlers to be dispatched, or until the io_service has been stopped.
+ *
+ * Multiple threads may call the run() function to set up a pool of threads
+ * from which the io_service may execute handlers. All threads that are
+ * waiting in the pool are equivalent and the io_service may choose any one
+ * of them to invoke a handler.
+ *
+ * The run() function may be safely called again once it has completed only
+ * after a call to reset().
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return The number of handlers that were executed.
+ */
+ std::size_t run(boost::system::error_code& ec);
+
+ /// Run the io_service's event processing loop to execute at most one handler.
+ /**
+ * The run_one() function blocks until one handler has been dispatched, or
+ * until the io_service has been stopped.
+ *
+ * @return The number of handlers that were executed.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ std::size_t run_one();
+
+ /// Run the io_service's event processing loop to execute at most one handler.
+ /**
+ * The run_one() function blocks until one handler has been dispatched, or
+ * until the io_service has been stopped.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return The number of handlers that were executed.
+ */
+ std::size_t run_one(boost::system::error_code& ec);
+
+ /// Run the io_service's event processing loop to execute ready handlers.
+ /**
+ * The poll() function runs handlers that are ready to run, without blocking,
+ * until the io_service has been stopped or there are no more ready handlers.
+ *
+ * @return The number of handlers that were executed.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ std::size_t poll();
+
+ /// Run the io_service's event processing loop to execute ready handlers.
+ /**
+ * The poll() function runs handlers that are ready to run, without blocking,
+ * until the io_service has been stopped or there are no more ready handlers.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return The number of handlers that were executed.
+ */
+ std::size_t poll(boost::system::error_code& ec);
+
+ /// Run the io_service's event processing loop to execute one ready handler.
+ /**
+ * The poll_one() function runs at most one handler that is ready to run,
+ * without blocking.
+ *
+ * @return The number of handlers that were executed.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ std::size_t poll_one();
+
+ /// Run the io_service's event processing loop to execute one ready handler.
+ /**
+ * The poll_one() function runs at most one handler that is ready to run,
+ * without blocking.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return The number of handlers that were executed.
+ */
+ std::size_t poll_one(boost::system::error_code& ec);
+
+ /// Stop the io_service's event processing loop.
+ /**
+ * This function does not block, but instead simply signals the io_service to
+ * stop. All invocations of its run() or run_one() member functions should
+ * return as soon as possible. Subsequent calls to run(), run_one(), poll()
+ * or poll_one() will return immediately until reset() is called.
+ */
+ void stop();
+
+ /// Reset the io_service in preparation for a subsequent run() invocation.
+ /**
+ * This function must be called prior to any second or later set of
+ * invocations of the run(), run_one(), poll() or poll_one() functions when a
+ * previous invocation of these functions returned due to the io_service
+ * being stopped or running out of work. This function allows the io_service
+ * to reset any internal state, such as a "stopped" flag.
+ *
+ * This function must not be called while there are any unfinished calls to
+ * the run(), run_one(), poll() or poll_one() functions.
+ */
+ void reset();
+
+ /// Request the io_service to invoke the given handler.
+ /**
+ * This function is used to ask the io_service to execute the given handler.
+ *
+ * The io_service guarantees that the handler will only be called in a thread
+ * in which the run(), run_one(), poll() or poll_one() member functions is
+ * currently being invoked. The handler may be executed inside this function
+ * if the guarantee can be met.
+ *
+ * @param handler The handler to be called. The io_service will make
+ * a copy of the handler object as required. The function signature of the
+ * handler must be: @code void handler(); @endcode
+ */
+ template <typename CompletionHandler>
+ void dispatch(CompletionHandler handler);
+
+ /// Request the io_service to invoke the given handler and return immediately.
+ /**
+ * This function is used to ask the io_service to execute the given handler,
+ * but without allowing the io_service to call the handler from inside this
+ * function.
+ *
+ * The io_service guarantees that the handler will only be called in a thread
+ * in which the run(), run_one(), poll() or poll_one() member functions is
+ * currently being invoked.
+ *
+ * @param handler The handler to be called. The io_service will make
+ * a copy of the handler object as required. The function signature of the
+ * handler must be: @code void handler(); @endcode
+ */
+ template <typename CompletionHandler>
+ void post(CompletionHandler handler);
+
+ /// Create a new handler that automatically dispatches the wrapped handler
+ /// on the io_service.
+ /**
+ * This function is used to create a new handler function object that, when
+ * invoked, will automatically pass the wrapped handler to the io_service's
+ * dispatch function.
+ *
+ * @param handler The handler to be wrapped. The io_service will make a copy
+ * of the handler object as required. The function signature of the handler
+ * must be: @code void handler(A1 a1, ... An an); @endcode
+ *
+ * @return A function object that, when invoked, passes the wrapped handler to
+ * the io_service's dispatch function. Given a function object with the
+ * signature:
+ * @code R f(A1 a1, ... An an); @endcode
+ * If this function object is passed to the wrap function like so:
+ * @code io_service.wrap(f); @endcode
+ * then the return value is a function object with the signature
+ * @code void g(A1 a1, ... An an); @endcode
+ * that, when invoked, executes code equivalent to:
+ * @code io_service.dispatch(boost::bind(f, a1, ... an)); @endcode
+ */
+ template <typename Handler>
+#if defined(GENERATING_DOCUMENTATION)
+ unspecified
+#else
+ detail::wrapped_handler<io_service&, Handler>
+#endif
+ wrap(Handler handler);
+
+ /// Obtain the service object corresponding to the given type.
+ /**
+ * This function is used to locate a service object that corresponds to
+ * the given service type. If there is no existing implementation of the
+ * service, then the io_service will create a new instance of the service.
+ *
+ * @param ios The io_service object that owns the service.
+ *
+ * @return The service interface implementing the specified service type.
+ * Ownership of the service interface is not transferred to the caller.
+ */
+ template <typename Service>
+ friend Service& use_service(io_service& ios);
+
+ /// Add a service object to the io_service.
+ /**
+ * This function is used to add a service to the io_service.
+ *
+ * @param ios The io_service object that owns the service.
+ *
+ * @param svc The service object. On success, ownership of the service object
+ * is transferred to the io_service. When the io_service object is destroyed,
+ * it will destroy the service object by performing:
+ * @code delete static_cast<io_service::service*>(svc) @endcode
+ *
+ * @throws boost::asio::service_already_exists Thrown if a service of the
+ * given type is already present in the io_service.
+ *
+ * @throws boost::asio::invalid_service_owner Thrown if the service's owning
+ * io_service is not the io_service object specified by the ios parameter.
+ */
+ template <typename Service>
+ friend void add_service(io_service& ios, Service* svc);
+
+ /// Determine if an io_service contains a specified service type.
+ /**
+ * This function is used to determine whether the io_service contains a
+ * service object corresponding to the given service type.
+ *
+ * @param ios The io_service object that owns the service.
+ *
+ * @return A boolean indicating whether the io_service contains the service.
+ */
+ template <typename Service>
+ friend bool has_service(io_service& ios);
+
+private:
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+ detail::winsock_init<> init_;
+#elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \
+ || defined(__osf__)
+ detail::signal_init<> init_;
+#endif
+
+ // The service registry.
+ boost::asio::detail::service_registry* service_registry_;
+
+ // The implementation.
+ impl_type& impl_;
+};
+
+/// Class to inform the io_service when it has work to do.
+/**
+ * The work class is used to inform the io_service when work starts and
+ * finishes. This ensures that the io_service's run() function will not exit
+ * while work is underway, and that it does exit when there is no unfinished
+ * work remaining.
+ *
+ * The work class is copy-constructible so that it may be used as a data member
+ * in a handler class. It is not assignable.
+ */
+class io_service::work
+{
+public:
+ /// Constructor notifies the io_service that work is starting.
+ /**
+ * The constructor is used to inform the io_service that some work has begun.
+ * This ensures that the io_service's run() function will not exit while the
+ * work is underway.
+ */
+ explicit work(boost::asio::io_service& io_service);
+
+ /// Copy constructor notifies the io_service that work is starting.
+ /**
+ * The constructor is used to inform the io_service that some work has begun.
+ * This ensures that the io_service's run() function will not exit while the
+ * work is underway.
+ */
+ work(const work& other);
+
+ /// Destructor notifies the io_service that the work is complete.
+ /**
+ * The destructor is used to inform the io_service that some work has
+ * finished. Once the count of unfinished work reaches zero, the io_service's
+ * run() function is permitted to exit.
+ */
+ ~work();
+
+ /// (Deprecated: use get_io_service().) Get the io_service associated with the
+ /// work.
+ boost::asio::io_service& io_service();
+
+ /// Get the io_service associated with the work.
+ boost::asio::io_service& get_io_service();
+
+private:
+ // Prevent assignment.
+ void operator=(const work& other);
+
+ // The io_service.
+ boost::asio::io_service& io_service_;
+};
+
+/// Class used to uniquely identify a service.
+class io_service::id
+ : private noncopyable
+{
+public:
+ /// Constructor.
+ id() {}
+};
+
+/// Base class for all io_service services.
+class io_service::service
+ : private noncopyable
+{
+public:
+ /// (Deprecated: use get_io_service().) Get the io_service object that owns
+ /// the service.
+ boost::asio::io_service& io_service();
+
+ /// Get the io_service object that owns the service.
+ boost::asio::io_service& get_io_service();
+
+protected:
+ /// Constructor.
+ /**
+ * @param owner The io_service object that owns the service.
+ */
+ service(boost::asio::io_service& owner);
+
+ /// Destructor.
+ virtual ~service();
+
+private:
+ /// Destroy all user-defined handler objects owned by the service.
+ virtual void shutdown_service() = 0;
+
+ friend class boost::asio::detail::service_registry;
+ boost::asio::io_service& owner_;
+ const std::type_info* type_info_;
+ const boost::asio::io_service::id* id_;
+ service* next_;
+};
+
+/// Exception thrown when trying to add a duplicate service to an io_service.
+class service_already_exists
+ : public std::logic_error
+{
+public:
+ service_already_exists()
+ : std::logic_error("Service already exists.")
+ {
+ }
+};
+
+/// Exception thrown when trying to add a service object to an io_service where
+/// the service has a different owner.
+class invalid_service_owner
+ : public std::logic_error
+{
+public:
+ invalid_service_owner()
+ : std::logic_error("Invalid service owner.")
+ {
+ }
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/impl/io_service.ipp>
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IO_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ip/address.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ip/address.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,279 @@
+//
+// address.hpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_ADDRESS_HPP
+#define BOOST_ASIO_IP_ADDRESS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <iosfwd>
+#include <string>
+#include <boost/throw_exception.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/ip/address_v4.hpp>
+#include <boost/asio/ip/address_v6.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// Implements version-independent IP addresses.
+/**
+ * The boost::asio::ip::address class provides the ability to use either IP
+ * version 4 or version 6 addresses.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ */
+class address
+{
+public:
+ /// Default constructor.
+ address()
+ : type_(ipv4),
+ ipv4_address_(),
+ ipv6_address_()
+ {
+ }
+
+ /// Construct an address from an IPv4 address.
+ address(const boost::asio::ip::address_v4& ipv4_address)
+ : type_(ipv4),
+ ipv4_address_(ipv4_address),
+ ipv6_address_()
+ {
+ }
+
+ /// Construct an address from an IPv6 address.
+ address(const boost::asio::ip::address_v6& ipv6_address)
+ : type_(ipv6),
+ ipv4_address_(),
+ ipv6_address_(ipv6_address)
+ {
+ }
+
+ /// Copy constructor.
+ address(const address& other)
+ : type_(other.type_),
+ ipv4_address_(other.ipv4_address_),
+ ipv6_address_(other.ipv6_address_)
+ {
+ }
+
+ /// Assign from another address.
+ address& operator=(const address& other)
+ {
+ type_ = other.type_;
+ ipv4_address_ = other.ipv4_address_;
+ ipv6_address_ = other.ipv6_address_;
+ return *this;
+ }
+
+ /// Assign from an IPv4 address.
+ address& operator=(const boost::asio::ip::address_v4& ipv4_address)
+ {
+ type_ = ipv4;
+ ipv4_address_ = ipv4_address;
+ ipv6_address_ = boost::asio::ip::address_v6();
+ return *this;
+ }
+
+ /// Assign from an IPv6 address.
+ address& operator=(const boost::asio::ip::address_v6& ipv6_address)
+ {
+ type_ = ipv6;
+ ipv4_address_ = boost::asio::ip::address_v4();
+ ipv6_address_ = ipv6_address;
+ return *this;
+ }
+
+ /// Get whether the address is an IP version 4 address.
+ bool is_v4() const
+ {
+ return type_ == ipv4;
+ }
+
+ /// Get whether the address is an IP version 6 address.
+ bool is_v6() const
+ {
+ return type_ == ipv6;
+ }
+
+ /// Get the address as an IP version 4 address.
+ boost::asio::ip::address_v4 to_v4() const
+ {
+ if (type_ != ipv4)
+ {
+ boost::system::system_error e(
+ boost::asio::error::address_family_not_supported);
+ boost::throw_exception(e);
+ }
+ return ipv4_address_;
+ }
+
+ /// Get the address as an IP version 6 address.
+ boost::asio::ip::address_v6 to_v6() const
+ {
+ if (type_ != ipv6)
+ {
+ boost::system::system_error e(
+ boost::asio::error::address_family_not_supported);
+ boost::throw_exception(e);
+ }
+ return ipv6_address_;
+ }
+
+ /// Get the address as a string in dotted decimal format.
+ std::string to_string() const
+ {
+ if (type_ == ipv6)
+ return ipv6_address_.to_string();
+ return ipv4_address_.to_string();
+ }
+
+ /// Get the address as a string in dotted decimal format.
+ std::string to_string(boost::system::error_code& ec) const
+ {
+ if (type_ == ipv6)
+ return ipv6_address_.to_string(ec);
+ return ipv4_address_.to_string(ec);
+ }
+
+ /// Create an address from an IPv4 address string in dotted decimal form,
+ /// or from an IPv6 address in hexadecimal notation.
+ static address from_string(const char* str)
+ {
+ boost::system::error_code ec;
+ address addr = from_string(str, ec);
+ boost::asio::detail::throw_error(ec);
+ return addr;
+ }
+
+ /// Create an address from an IPv4 address string in dotted decimal form,
+ /// or from an IPv6 address in hexadecimal notation.
+ static address from_string(const char* str, boost::system::error_code& ec)
+ {
+ boost::asio::ip::address_v6 ipv6_address =
+ boost::asio::ip::address_v6::from_string(str, ec);
+ if (!ec)
+ {
+ address tmp;
+ tmp.type_ = ipv6;
+ tmp.ipv6_address_ = ipv6_address;
+ return tmp;
+ }
+
+ boost::asio::ip::address_v4 ipv4_address =
+ boost::asio::ip::address_v4::from_string(str, ec);
+ if (!ec)
+ {
+ address tmp;
+ tmp.type_ = ipv4;
+ tmp.ipv4_address_ = ipv4_address;
+ return tmp;
+ }
+
+ return address();
+ }
+
+ /// Create an address from an IPv4 address string in dotted decimal form,
+ /// or from an IPv6 address in hexadecimal notation.
+ static address from_string(const std::string& str)
+ {
+ return from_string(str.c_str());
+ }
+
+ /// Create an address from an IPv4 address string in dotted decimal form,
+ /// or from an IPv6 address in hexadecimal notation.
+ static address from_string(const std::string& str,
+ boost::system::error_code& ec)
+ {
+ return from_string(str.c_str(), ec);
+ }
+
+ /// Compare two addresses for equality.
+ friend bool operator==(const address& a1, const address& a2)
+ {
+ if (a1.type_ != a2.type_)
+ return false;
+ if (a1.type_ == ipv6)
+ return a1.ipv6_address_ == a2.ipv6_address_;
+ return a1.ipv4_address_ == a2.ipv4_address_;
+ }
+
+ /// Compare two addresses for inequality.
+ friend bool operator!=(const address& a1, const address& a2)
+ {
+ if (a1.type_ != a2.type_)
+ return true;
+ if (a1.type_ == ipv6)
+ return a1.ipv6_address_ != a2.ipv6_address_;
+ return a1.ipv4_address_ != a2.ipv4_address_;
+ }
+
+ /// Compare addresses for ordering.
+ friend bool operator<(const address& a1, const address& a2)
+ {
+ if (a1.type_ < a2.type_)
+ return true;
+ if (a1.type_ > a2.type_)
+ return false;
+ if (a1.type_ == ipv6)
+ return a1.ipv6_address_ < a2.ipv6_address_;
+ return a1.ipv4_address_ < a2.ipv4_address_;
+ }
+
+private:
+ // The type of the address.
+ enum { ipv4, ipv6 } type_;
+
+ // The underlying IPv4 address.
+ boost::asio::ip::address_v4 ipv4_address_;
+
+ // The underlying IPv6 address.
+ boost::asio::ip::address_v6 ipv6_address_;
+};
+
+/// Output an address as a string.
+/**
+ * Used to output a human-readable string for a specified address.
+ *
+ * @param os The output stream to which the string will be written.
+ *
+ * @param addr The address to be written.
+ *
+ * @return The output stream.
+ *
+ * @relates boost::asio::ip::address
+ */
+template <typename Elem, typename Traits>
+std::basic_ostream<Elem, Traits>& operator<<(
+ std::basic_ostream<Elem, Traits>& os, const address& addr)
+{
+ os << addr.to_string();
+ return os;
+}
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_ADDRESS_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ip/address_v4.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ip/address_v4.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,290 @@
+//
+// address_v4.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_ADDRESS_V4_HPP
+#define BOOST_ASIO_IP_ADDRESS_V4_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <string>
+#include <boost/array.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// Implements IP version 4 style addresses.
+/**
+ * The boost::asio::ip::address_v4 class provides the ability to use and
+ * manipulate IP version 4 addresses.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ */
+class address_v4
+{
+public:
+ /// The type used to represent an address as an array of bytes.
+ typedef boost::array<unsigned char, 4> bytes_type;
+
+ /// Default constructor.
+ address_v4()
+ {
+ addr_.s_addr = 0;
+ }
+
+ /// Construct an address from raw bytes.
+ explicit address_v4(const bytes_type& bytes)
+ {
+ using namespace std; // For memcpy.
+ memcpy(&addr_.s_addr, bytes.elems, 4);
+ }
+
+ /// Construct an address from a unsigned long in host byte order.
+ explicit address_v4(unsigned long addr)
+ {
+ addr_.s_addr = boost::asio::detail::socket_ops::host_to_network_long(addr);
+ }
+
+ /// Copy constructor.
+ address_v4(const address_v4& other)
+ : addr_(other.addr_)
+ {
+ }
+
+ /// Assign from another address.
+ address_v4& operator=(const address_v4& other)
+ {
+ addr_ = other.addr_;
+ return *this;
+ }
+
+ /// Get the address in bytes.
+ bytes_type to_bytes() const
+ {
+ using namespace std; // For memcpy.
+ bytes_type bytes;
+ memcpy(bytes.elems, &addr_.s_addr, 4);
+ return bytes;
+ }
+
+ /// Get the address as an unsigned long in host byte order
+ unsigned long to_ulong() const
+ {
+ return boost::asio::detail::socket_ops::network_to_host_long(addr_.s_addr);
+ }
+
+ /// Get the address as a string in dotted decimal format.
+ std::string to_string() const
+ {
+ boost::system::error_code ec;
+ std::string addr = to_string(ec);
+ boost::asio::detail::throw_error(ec);
+ return addr;
+ }
+
+ /// Get the address as a string in dotted decimal format.
+ std::string to_string(boost::system::error_code& ec) const
+ {
+ char addr_str[boost::asio::detail::max_addr_v4_str_len];
+ const char* addr =
+ boost::asio::detail::socket_ops::inet_ntop(AF_INET, &addr_, addr_str,
+ boost::asio::detail::max_addr_v4_str_len, 0, ec);
+ if (addr == 0)
+ return std::string();
+ return addr;
+ }
+
+ /// Create an address from an IP address string in dotted decimal form.
+ static address_v4 from_string(const char* str)
+ {
+ boost::system::error_code ec;
+ address_v4 addr = from_string(str, ec);
+ boost::asio::detail::throw_error(ec);
+ return addr;
+ }
+
+ /// Create an address from an IP address string in dotted decimal form.
+ static address_v4 from_string(const char* str, boost::system::error_code& ec)
+ {
+ address_v4 tmp;
+ if (boost::asio::detail::socket_ops::inet_pton(
+ AF_INET, str, &tmp.addr_, 0, ec) <= 0)
+ return address_v4();
+ return tmp;
+ }
+
+ /// Create an address from an IP address string in dotted decimal form.
+ static address_v4 from_string(const std::string& str)
+ {
+ return from_string(str.c_str());
+ }
+
+ /// Create an address from an IP address string in dotted decimal form.
+ static address_v4 from_string(const std::string& str,
+ boost::system::error_code& ec)
+ {
+ return from_string(str.c_str(), ec);
+ }
+
+ /// Determine whether the address is a class A address.
+ bool is_class_a() const
+ {
+ return IN_CLASSA(to_ulong());
+ }
+
+ /// Determine whether the address is a class B address.
+ bool is_class_b() const
+ {
+ return IN_CLASSB(to_ulong());
+ }
+
+ /// Determine whether the address is a class C address.
+ bool is_class_c() const
+ {
+ return IN_CLASSC(to_ulong());
+ }
+
+ /// Determine whether the address is a multicast address.
+ bool is_multicast() const
+ {
+ return IN_MULTICAST(to_ulong());
+ }
+
+ /// Compare two addresses for equality.
+ friend bool operator==(const address_v4& a1, const address_v4& a2)
+ {
+ return a1.addr_.s_addr == a2.addr_.s_addr;
+ }
+
+ /// Compare two addresses for inequality.
+ friend bool operator!=(const address_v4& a1, const address_v4& a2)
+ {
+ return a1.addr_.s_addr != a2.addr_.s_addr;
+ }
+
+ /// Compare addresses for ordering.
+ friend bool operator<(const address_v4& a1, const address_v4& a2)
+ {
+ return a1.to_ulong() < a2.to_ulong();
+ }
+
+ /// Compare addresses for ordering.
+ friend bool operator>(const address_v4& a1, const address_v4& a2)
+ {
+ return a1.to_ulong() > a2.to_ulong();
+ }
+
+ /// Compare addresses for ordering.
+ friend bool operator<=(const address_v4& a1, const address_v4& a2)
+ {
+ return a1.to_ulong() <= a2.to_ulong();
+ }
+
+ /// Compare addresses for ordering.
+ friend bool operator>=(const address_v4& a1, const address_v4& a2)
+ {
+ return a1.to_ulong() >= a2.to_ulong();
+ }
+
+ /// Obtain an address object that represents any address.
+ static address_v4 any()
+ {
+ return address_v4(static_cast<unsigned long>(INADDR_ANY));
+ }
+
+ /// Obtain an address object that represents the loopback address.
+ static address_v4 loopback()
+ {
+ return address_v4(static_cast<unsigned long>(INADDR_LOOPBACK));
+ }
+
+ /// Obtain an address object that represents the broadcast address.
+ static address_v4 broadcast()
+ {
+ return address_v4(static_cast<unsigned long>(INADDR_BROADCAST));
+ }
+
+ /// Obtain an address object that represents the broadcast address that
+ /// corresponds to the specified address and netmask.
+ static address_v4 broadcast(const address_v4& addr, const address_v4& mask)
+ {
+ return address_v4(addr.to_ulong() | ~mask.to_ulong());
+ }
+
+ /// Obtain the netmask that corresponds to the address, based on its address
+ /// class.
+ static address_v4 netmask(const address_v4& addr)
+ {
+ if (addr.is_class_a())
+ return address_v4(0xFF000000);
+ if (addr.is_class_b())
+ return address_v4(0xFFFF0000);
+ if (addr.is_class_c())
+ return address_v4(0xFFFFFF00);
+ return address_v4(0xFFFFFFFF);
+ }
+
+private:
+ // The underlying IPv4 address.
+ boost::asio::detail::in4_addr_type addr_;
+};
+
+/// Output an address as a string.
+/**
+ * Used to output a human-readable string for a specified address.
+ *
+ * @param os The output stream to which the string will be written.
+ *
+ * @param addr The address to be written.
+ *
+ * @return The output stream.
+ *
+ * @relates boost::asio::ip::address_v4
+ */
+template <typename Elem, typename Traits>
+std::basic_ostream<Elem, Traits>& operator<<(
+ std::basic_ostream<Elem, Traits>& os, const address_v4& addr)
+{
+ boost::system::error_code ec;
+ std::string s = addr.to_string(ec);
+ if (ec)
+ {
+ if (os.exceptions() & std::ios::failbit)
+ boost::asio::detail::throw_error(ec);
+ else
+ os.setstate(std::ios_base::failbit);
+ }
+ else
+ for (std::string::iterator i = s.begin(); i != s.end(); ++i)
+ os << os.widen(*i);
+ return os;
+}
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_ADDRESS_V4_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ip/address_v6.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ip/address_v6.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,408 @@
+//
+// address_v6.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_ADDRESS_V6_HPP
+#define BOOST_ASIO_IP_ADDRESS_V6_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstring>
+#include <string>
+#include <stdexcept>
+#include <typeinfo>
+#include <boost/array.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/ip/address_v4.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// Implements IP version 6 style addresses.
+/**
+ * The boost::asio::ip::address_v6 class provides the ability to use and
+ * manipulate IP version 6 addresses.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ */
+class address_v6
+{
+public:
+ /// The type used to represent an address as an array of bytes.
+ typedef boost::array<unsigned char, 16> bytes_type;
+
+ /// Default constructor.
+ address_v6()
+ : scope_id_(0)
+ {
+ boost::asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
+ addr_ = tmp_addr;
+ }
+
+ /// Construct an address from raw bytes and scope ID.
+ explicit address_v6(const bytes_type& bytes, unsigned long scope_id = 0)
+ : scope_id_(scope_id)
+ {
+ using namespace std; // For memcpy.
+ memcpy(addr_.s6_addr, bytes.elems, 16);
+ }
+
+ /// Copy constructor.
+ address_v6(const address_v6& other)
+ : addr_(other.addr_),
+ scope_id_(other.scope_id_)
+ {
+ }
+
+ /// Assign from another address.
+ address_v6& operator=(const address_v6& other)
+ {
+ addr_ = other.addr_;
+ scope_id_ = other.scope_id_;
+ return *this;
+ }
+
+ /// The scope ID of the address.
+ /**
+ * Returns the scope ID associated with the IPv6 address.
+ */
+ unsigned long scope_id() const
+ {
+ return scope_id_;
+ }
+
+ /// The scope ID of the address.
+ /**
+ * Modifies the scope ID associated with the IPv6 address.
+ */
+ void scope_id(unsigned long id)
+ {
+ scope_id_ = id;
+ }
+
+ /// Get the address in bytes.
+ bytes_type to_bytes() const
+ {
+ using namespace std; // For memcpy.
+ bytes_type bytes;
+ memcpy(bytes.elems, addr_.s6_addr, 16);
+ return bytes;
+ }
+
+ /// Get the address as a string.
+ std::string to_string() const
+ {
+ boost::system::error_code ec;
+ std::string addr = to_string(ec);
+ boost::asio::detail::throw_error(ec);
+ return addr;
+ }
+
+ /// Get the address as a string.
+ std::string to_string(boost::system::error_code& ec) const
+ {
+ char addr_str[boost::asio::detail::max_addr_v6_str_len];
+ const char* addr =
+ boost::asio::detail::socket_ops::inet_ntop(AF_INET6, &addr_, addr_str,
+ boost::asio::detail::max_addr_v6_str_len, scope_id_, ec);
+ if (addr == 0)
+ return std::string();
+ return addr;
+ }
+
+ /// Create an address from an IP address string.
+ static address_v6 from_string(const char* str)
+ {
+ boost::system::error_code ec;
+ address_v6 addr = from_string(str, ec);
+ boost::asio::detail::throw_error(ec);
+ return addr;
+ }
+
+ /// Create an address from an IP address string.
+ static address_v6 from_string(const char* str, boost::system::error_code& ec)
+ {
+ address_v6 tmp;
+ if (boost::asio::detail::socket_ops::inet_pton(
+ AF_INET6, str, &tmp.addr_, &tmp.scope_id_, ec) <= 0)
+ return address_v6();
+ return tmp;
+ }
+
+ /// Create an address from an IP address string.
+ static address_v6 from_string(const std::string& str)
+ {
+ return from_string(str.c_str());
+ }
+
+ /// Create an address from an IP address string.
+ static address_v6 from_string(const std::string& str,
+ boost::system::error_code& ec)
+ {
+ return from_string(str.c_str(), ec);
+ }
+
+ /// Converts an IPv4-mapped or IPv4-compatible address to an IPv4 address.
+ address_v4 to_v4() const
+ {
+ if (!is_v4_mapped() && !is_v4_compatible())
+ throw std::bad_cast();
+ address_v4::bytes_type v4_bytes = { { addr_.s6_addr[12],
+ addr_.s6_addr[13], addr_.s6_addr[14], addr_.s6_addr[15] } };
+ return address_v4(v4_bytes);
+ }
+
+ /// Determine whether the address is a loopback address.
+ bool is_loopback() const
+ {
+#if defined(__BORLANDC__)
+ return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)
+ && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)
+ && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)
+ && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)
+ && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)
+ && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0)
+ && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0)
+ && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 1));
+#else
+ using namespace boost::asio::detail;
+ return IN6_IS_ADDR_LOOPBACK(&addr_) != 0;
+#endif
+ }
+
+ /// Determine whether the address is unspecified.
+ bool is_unspecified() const
+ {
+#if defined(__BORLANDC__)
+ return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)
+ && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)
+ && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)
+ && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)
+ && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)
+ && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0)
+ && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0)
+ && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 0));
+#else
+ using namespace boost::asio::detail;
+ return IN6_IS_ADDR_UNSPECIFIED(&addr_) != 0;
+#endif
+ }
+
+ /// Determine whether the address is link local.
+ bool is_link_local() const
+ {
+ using namespace boost::asio::detail;
+ return IN6_IS_ADDR_LINKLOCAL(&addr_) != 0;
+ }
+
+ /// Determine whether the address is site local.
+ bool is_site_local() const
+ {
+ using namespace boost::asio::detail;
+ return IN6_IS_ADDR_SITELOCAL(&addr_) != 0;
+ }
+
+ /// Determine whether the address is a mapped IPv4 address.
+ bool is_v4_mapped() const
+ {
+ using namespace boost::asio::detail;
+ return IN6_IS_ADDR_V4MAPPED(&addr_) != 0;
+ }
+
+ /// Determine whether the address is an IPv4-compatible address.
+ bool is_v4_compatible() const
+ {
+ using namespace boost::asio::detail;
+ return IN6_IS_ADDR_V4COMPAT(&addr_) != 0;
+ }
+
+ /// Determine whether the address is a multicast address.
+ bool is_multicast() const
+ {
+ using namespace boost::asio::detail;
+ return IN6_IS_ADDR_MULTICAST(&addr_) != 0;
+ }
+
+ /// Determine whether the address is a global multicast address.
+ bool is_multicast_global() const
+ {
+ using namespace boost::asio::detail;
+ return IN6_IS_ADDR_MC_GLOBAL(&addr_) != 0;
+ }
+
+ /// Determine whether the address is a link-local multicast address.
+ bool is_multicast_link_local() const
+ {
+ using namespace boost::asio::detail;
+ return IN6_IS_ADDR_MC_LINKLOCAL(&addr_) != 0;
+ }
+
+ /// Determine whether the address is a node-local multicast address.
+ bool is_multicast_node_local() const
+ {
+ using namespace boost::asio::detail;
+ return IN6_IS_ADDR_MC_NODELOCAL(&addr_) != 0;
+ }
+
+ /// Determine whether the address is a org-local multicast address.
+ bool is_multicast_org_local() const
+ {
+ using namespace boost::asio::detail;
+ return IN6_IS_ADDR_MC_ORGLOCAL(&addr_) != 0;
+ }
+
+ /// Determine whether the address is a site-local multicast address.
+ bool is_multicast_site_local() const
+ {
+ using namespace boost::asio::detail;
+ return IN6_IS_ADDR_MC_SITELOCAL(&addr_) != 0;
+ }
+
+ /// Compare two addresses for equality.
+ friend bool operator==(const address_v6& a1, const address_v6& a2)
+ {
+ using namespace std; // For memcmp.
+ return memcmp(&a1.addr_, &a2.addr_,
+ sizeof(boost::asio::detail::in6_addr_type)) == 0
+ && a1.scope_id_ == a2.scope_id_;
+ }
+
+ /// Compare two addresses for inequality.
+ friend bool operator!=(const address_v6& a1, const address_v6& a2)
+ {
+ using namespace std; // For memcmp.
+ return memcmp(&a1.addr_, &a2.addr_,
+ sizeof(boost::asio::detail::in6_addr_type)) != 0
+ || a1.scope_id_ != a2.scope_id_;
+ }
+
+ /// Compare addresses for ordering.
+ friend bool operator<(const address_v6& a1, const address_v6& a2)
+ {
+ using namespace std; // For memcmp.
+ int memcmp_result = memcmp(&a1.addr_, &a2.addr_,
+ sizeof(boost::asio::detail::in6_addr_type));
+ if (memcmp_result < 0)
+ return true;
+ if (memcmp_result > 0)
+ return false;
+ return a1.scope_id_ < a2.scope_id_;
+ }
+
+ /// Compare addresses for ordering.
+ friend bool operator>(const address_v6& a1, const address_v6& a2)
+ {
+ return a2 < a1;
+ }
+
+ /// Compare addresses for ordering.
+ friend bool operator<=(const address_v6& a1, const address_v6& a2)
+ {
+ return !(a2 < a1);
+ }
+
+ /// Compare addresses for ordering.
+ friend bool operator>=(const address_v6& a1, const address_v6& a2)
+ {
+ return !(a1 < a2);
+ }
+
+ /// Obtain an address object that represents any address.
+ static address_v6 any()
+ {
+ return address_v6();
+ }
+
+ /// Obtain an address object that represents the loopback address.
+ static address_v6 loopback()
+ {
+ address_v6 tmp;
+ boost::asio::detail::in6_addr_type tmp_addr = IN6ADDR_LOOPBACK_INIT;
+ tmp.addr_ = tmp_addr;
+ return tmp;
+ }
+
+ /// Create an IPv4-mapped IPv6 address.
+ static address_v6 v4_mapped(const address_v4& addr)
+ {
+ address_v4::bytes_type v4_bytes = addr.to_bytes();
+ bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF,
+ v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };
+ return address_v6(v6_bytes);
+ }
+
+ /// Create an IPv4-compatible IPv6 address.
+ static address_v6 v4_compatible(const address_v4& addr)
+ {
+ address_v4::bytes_type v4_bytes = addr.to_bytes();
+ bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };
+ return address_v6(v6_bytes);
+ }
+
+private:
+ // The underlying IPv6 address.
+ boost::asio::detail::in6_addr_type addr_;
+
+ // The scope ID associated with the address.
+ unsigned long scope_id_;
+};
+
+/// Output an address as a string.
+/**
+ * Used to output a human-readable string for a specified address.
+ *
+ * @param os The output stream to which the string will be written.
+ *
+ * @param addr The address to be written.
+ *
+ * @return The output stream.
+ *
+ * @relates boost::asio::ip::address_v6
+ */
+template <typename Elem, typename Traits>
+std::basic_ostream<Elem, Traits>& operator<<(
+ std::basic_ostream<Elem, Traits>& os, const address_v6& addr)
+{
+ boost::system::error_code ec;
+ std::string s = addr.to_string(ec);
+ if (ec)
+ {
+ if (os.exceptions() & std::ios::failbit)
+ boost::asio::detail::throw_error(ec);
+ else
+ os.setstate(std::ios_base::failbit);
+ }
+ else
+ for (std::string::iterator i = s.begin(); i != s.end(); ++i)
+ os << os.widen(*i);
+ return os;
+}
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_ADDRESS_V6_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ip/basic_endpoint.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ip/basic_endpoint.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,370 @@
+//
+// basic_endpoint.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_BASIC_ENDPOINT_HPP
+#define BOOST_ASIO_IP_BASIC_ENDPOINT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/throw_exception.hpp>
+#include <boost/detail/workaround.hpp>
+#include <cstring>
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+# include <ostream>
+#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/ip/address.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// Describes an endpoint for a version-independent IP socket.
+/**
+ * The boost::asio::ip::basic_endpoint class template describes an endpoint that
+ * may be associated with a particular socket.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Concepts:
+ * Endpoint.
+ */
+template <typename InternetProtocol>
+class basic_endpoint
+{
+public:
+ /// The protocol type associated with the endpoint.
+ typedef InternetProtocol protocol_type;
+
+ /// The type of the endpoint structure. This type is dependent on the
+ /// underlying implementation of the socket layer.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined data_type;
+#else
+ typedef boost::asio::detail::socket_addr_type data_type;
+#endif
+
+ /// Default constructor.
+ basic_endpoint()
+ : data_()
+ {
+ data_.v4.sin_family = AF_INET;
+ data_.v4.sin_port = 0;
+ data_.v4.sin_addr.s_addr = INADDR_ANY;
+ }
+
+ /// Construct an endpoint using a port number, specified in the host's byte
+ /// order. The IP address will be the any address (i.e. INADDR_ANY or
+ /// in6addr_any). This constructor would typically be used for accepting new
+ /// connections.
+ /**
+ * @par Examples
+ * To initialise an IPv4 TCP endpoint for port 1234, use:
+ * @code
+ * boost::asio::ip::tcp::endpoint ep(boost::asio::ip::tcp::v4(), 1234);
+ * @endcode
+ *
+ * To specify an IPv6 UDP endpoint for port 9876, use:
+ * @code
+ * boost::asio::ip::udp::endpoint ep(boost::asio::ip::udp::v6(), 9876);
+ * @endcode
+ */
+ basic_endpoint(const InternetProtocol& protocol, unsigned short port_num)
+ : data_()
+ {
+ using namespace std; // For memcpy.
+ if (protocol.family() == PF_INET)
+ {
+ data_.v4.sin_family = AF_INET;
+ data_.v4.sin_port =
+ boost::asio::detail::socket_ops::host_to_network_short(port_num);
+ data_.v4.sin_addr.s_addr = INADDR_ANY;
+ }
+ else
+ {
+ data_.v6.sin6_family = AF_INET6;
+ data_.v6.sin6_port =
+ boost::asio::detail::socket_ops::host_to_network_short(port_num);
+ data_.v6.sin6_flowinfo = 0;
+ boost::asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
+ data_.v6.sin6_addr = tmp_addr;
+ data_.v6.sin6_scope_id = 0;
+ }
+ }
+
+ /// Construct an endpoint using a port number and an IP address. This
+ /// constructor may be used for accepting connections on a specific interface
+ /// or for making a connection to a remote endpoint.
+ basic_endpoint(const boost::asio::ip::address& addr, unsigned short port_num)
+ : data_()
+ {
+ using namespace std; // For memcpy.
+ if (addr.is_v4())
+ {
+ data_.v4.sin_family = AF_INET;
+ data_.v4.sin_port =
+ boost::asio::detail::socket_ops::host_to_network_short(port_num);
+ data_.v4.sin_addr.s_addr =
+ boost::asio::detail::socket_ops::host_to_network_long(
+ addr.to_v4().to_ulong());
+ }
+ else
+ {
+ data_.v6.sin6_family = AF_INET6;
+ data_.v6.sin6_port =
+ boost::asio::detail::socket_ops::host_to_network_short(port_num);
+ data_.v6.sin6_flowinfo = 0;
+ boost::asio::ip::address_v6 v6_addr = addr.to_v6();
+ boost::asio::ip::address_v6::bytes_type bytes = v6_addr.to_bytes();
+ memcpy(data_.v6.sin6_addr.s6_addr, bytes.elems, 16);
+ data_.v6.sin6_scope_id = v6_addr.scope_id();
+ }
+ }
+
+ /// Copy constructor.
+ basic_endpoint(const basic_endpoint& other)
+ : data_(other.data_)
+ {
+ }
+
+ /// Assign from another endpoint.
+ basic_endpoint& operator=(const basic_endpoint& other)
+ {
+ data_ = other.data_;
+ return *this;
+ }
+
+ /// The protocol associated with the endpoint.
+ protocol_type protocol() const
+ {
+ if (is_v4())
+ return InternetProtocol::v4();
+ return InternetProtocol::v6();
+ }
+
+ /// Get the underlying endpoint in the native type.
+ data_type* data()
+ {
+ return &data_.base;
+ }
+
+ /// Get the underlying endpoint in the native type.
+ const data_type* data() const
+ {
+ return &data_.base;
+ }
+
+ /// Get the underlying size of the endpoint in the native type.
+ std::size_t size() const
+ {
+ if (is_v4())
+ return sizeof(boost::asio::detail::sockaddr_in4_type);
+ else
+ return sizeof(boost::asio::detail::sockaddr_in6_type);
+ }
+
+ /// Set the underlying size of the endpoint in the native type.
+ void resize(std::size_t size)
+ {
+ if (size > sizeof(boost::asio::detail::sockaddr_storage_type))
+ {
+ boost::system::system_error e(boost::asio::error::invalid_argument);
+ boost::throw_exception(e);
+ }
+ }
+
+ /// Get the capacity of the endpoint in the native type.
+ std::size_t capacity() const
+ {
+ return sizeof(boost::asio::detail::sockaddr_storage_type);
+ }
+
+ /// Get the port associated with the endpoint. The port number is always in
+ /// the host's byte order.
+ unsigned short port() const
+ {
+ if (is_v4())
+ {
+ return boost::asio::detail::socket_ops::network_to_host_short(
+ data_.v4.sin_port);
+ }
+ else
+ {
+ return boost::asio::detail::socket_ops::network_to_host_short(
+ data_.v6.sin6_port);
+ }
+ }
+
+ /// Set the port associated with the endpoint. The port number is always in
+ /// the host's byte order.
+ void port(unsigned short port_num)
+ {
+ if (is_v4())
+ {
+ data_.v4.sin_port
+ = boost::asio::detail::socket_ops::host_to_network_short(port_num);
+ }
+ else
+ {
+ data_.v6.sin6_port
+ = boost::asio::detail::socket_ops::host_to_network_short(port_num);
+ }
+ }
+
+ /// Get the IP address associated with the endpoint.
+ boost::asio::ip::address address() const
+ {
+ using namespace std; // For memcpy.
+ if (is_v4())
+ {
+ return boost::asio::ip::address_v4(
+ boost::asio::detail::socket_ops::network_to_host_long(
+ data_.v4.sin_addr.s_addr));
+ }
+ else
+ {
+ boost::asio::ip::address_v6::bytes_type bytes;
+ memcpy(bytes.elems, data_.v6.sin6_addr.s6_addr, 16);
+ return boost::asio::ip::address_v6(bytes, data_.v6.sin6_scope_id);
+ }
+ }
+
+ /// Set the IP address associated with the endpoint.
+ void address(const boost::asio::ip::address& addr)
+ {
+ basic_endpoint<InternetProtocol> tmp_endpoint(addr, port());
+ data_ = tmp_endpoint.data_;
+ }
+
+ /// Compare two endpoints for equality.
+ friend bool operator==(const basic_endpoint<InternetProtocol>& e1,
+ const basic_endpoint<InternetProtocol>& e2)
+ {
+ return e1.address() == e2.address() && e1.port() == e2.port();
+ }
+
+ /// Compare two endpoints for inequality.
+ friend bool operator!=(const basic_endpoint<InternetProtocol>& e1,
+ const basic_endpoint<InternetProtocol>& e2)
+ {
+ return e1.address() != e2.address() || e1.port() != e2.port();
+ }
+
+ /// Compare endpoints for ordering.
+ friend bool operator<(const basic_endpoint<InternetProtocol>& e1,
+ const basic_endpoint<InternetProtocol>& e2)
+ {
+ if (e1.address() < e2.address())
+ return true;
+ if (e1.address() != e2.address())
+ return false;
+ return e1.port() < e2.port();
+ }
+
+private:
+ // Helper function to determine whether the endpoint is IPv4.
+ bool is_v4() const
+ {
+ return data_.base.sa_family == AF_INET;
+ }
+
+ // The underlying IP socket address.
+ union data_union
+ {
+ boost::asio::detail::socket_addr_type base;
+ boost::asio::detail::sockaddr_storage_type storage;
+ boost::asio::detail::sockaddr_in4_type v4;
+ boost::asio::detail::sockaddr_in6_type v6;
+ } data_;
+};
+
+/// Output an endpoint as a string.
+/**
+ * Used to output a human-readable string for a specified endpoint.
+ *
+ * @param os The output stream to which the string will be written.
+ *
+ * @param endpoint The endpoint to be written.
+ *
+ * @return The output stream.
+ *
+ * @relates boost::asio::ip::basic_endpoint
+ */
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+template <typename InternetProtocol>
+std::ostream& operator<<(std::ostream& os,
+ const basic_endpoint<InternetProtocol>& endpoint)
+{
+ const address& addr = endpoint.address();
+ boost::system::error_code ec;
+ std::string a = addr.to_string(ec);
+ if (ec)
+ {
+ if (os.exceptions() & std::ios::failbit)
+ boost::asio::detail::throw_error(ec);
+ else
+ os.setstate(std::ios_base::failbit);
+ }
+ else
+ {
+ if (addr.is_v4())
+ os << a;
+ else
+ os << '[' << a << ']';
+ os << ':' << endpoint.port();
+ }
+ return os;
+}
+#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+template <typename Elem, typename Traits, typename InternetProtocol>
+std::basic_ostream<Elem, Traits>& operator<<(
+ std::basic_ostream<Elem, Traits>& os,
+ const basic_endpoint<InternetProtocol>& endpoint)
+{
+ const address& addr = endpoint.address();
+ boost::system::error_code ec;
+ std::string a = addr.to_string(ec);
+ if (ec)
+ {
+ if (os.exceptions() & std::ios::failbit)
+ boost::asio::detail::throw_error(ec);
+ else
+ os.setstate(std::ios_base::failbit);
+ }
+ else
+ {
+ if (addr.is_v4())
+ os << a;
+ else
+ os << '[' << a << ']';
+ os << ':' << endpoint.port();
+ }
+ return os;
+}
+#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_BASIC_ENDPOINT_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ip/basic_resolver.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ip/basic_resolver.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,247 @@
+//
+// basic_resolver.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_BASIC_RESOLVER_HPP
+#define BOOST_ASIO_IP_BASIC_RESOLVER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/ip/resolver_service.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// Provides endpoint resolution functionality.
+/**
+ * The basic_resolver class template provides the ability to resolve a query
+ * to a list of endpoints.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename InternetProtocol,
+ typename ResolverService = resolver_service<InternetProtocol> >
+class basic_resolver
+ : public basic_io_object<ResolverService>
+{
+public:
+ /// The protocol type.
+ typedef InternetProtocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename InternetProtocol::endpoint endpoint_type;
+
+ /// The query type.
+ typedef typename InternetProtocol::resolver_query query;
+
+ /// The iterator type.
+ typedef typename InternetProtocol::resolver_iterator iterator;
+
+ /// Constructor.
+ /**
+ * This constructor creates a basic_resolver.
+ *
+ * @param io_service The io_service object that the resolver will use to
+ * dispatch handlers for any asynchronous operations performed on the timer.
+ */
+ explicit basic_resolver(boost::asio::io_service& io_service)
+ : basic_io_object<ResolverService>(io_service)
+ {
+ }
+
+ /// Cancel any asynchronous operations that are waiting on the resolver.
+ /**
+ * This function forces the completion of any pending asynchronous
+ * operations on the host resolver. The handler for each cancelled operation
+ * will be invoked with the boost::asio::error::operation_aborted error code.
+ */
+ void cancel()
+ {
+ return this->service.cancel(this->implementation);
+ }
+
+ /// Resolve a query to a list of entries.
+ /**
+ * This function is used to resolve a query into a list of endpoint entries.
+ *
+ * @param q A query object that determines what endpoints will be returned.
+ *
+ * @returns A forward-only iterator that can be used to traverse the list
+ * of endpoint entries.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note A default constructed iterator represents the end of the list.
+ *
+ * A successful call to this function is guaranteed to return at least one
+ * entry.
+ */
+ iterator resolve(const query& q)
+ {
+ boost::system::error_code ec;
+ iterator i = this->service.resolve(this->implementation, q, ec);
+ boost::asio::detail::throw_error(ec);
+ return i;
+ }
+
+ /// Resolve a query to a list of entries.
+ /**
+ * This function is used to resolve a query into a list of endpoint entries.
+ *
+ * @param q A query object that determines what endpoints will be returned.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns A forward-only iterator that can be used to traverse the list
+ * of endpoint entries. Returns a default constructed iterator if an error
+ * occurs.
+ *
+ * @note A default constructed iterator represents the end of the list.
+ *
+ * A successful call to this function is guaranteed to return at least one
+ * entry.
+ */
+ iterator resolve(const query& q, boost::system::error_code& ec)
+ {
+ return this->service.resolve(this->implementation, q, ec);
+ }
+
+ /// Asynchronously resolve a query to a list of entries.
+ /**
+ * This function is used to asynchronously resolve a query into a list of
+ * endpoint entries.
+ *
+ * @param q A query object that determines what endpoints will be returned.
+ *
+ * @param handler The handler to be called when the resolve operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * resolver::iterator iterator // Forward-only iterator that can
+ * // be used to traverse the list
+ * // of endpoint entries.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note A default constructed iterator represents the end of the list.
+ *
+ * A successful resolve operation is guaranteed to pass at least one entry to
+ * the handler.
+ */
+ template <typename ResolveHandler>
+ void async_resolve(const query& q, ResolveHandler handler)
+ {
+ return this->service.async_resolve(this->implementation, q, handler);
+ }
+
+ /// Resolve an endpoint to a list of entries.
+ /**
+ * This function is used to resolve an endpoint into a list of endpoint
+ * entries.
+ *
+ * @param e An endpoint object that determines what endpoints will be
+ * returned.
+ *
+ * @returns A forward-only iterator that can be used to traverse the list
+ * of endpoint entries.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note A default constructed iterator represents the end of the list.
+ *
+ * A successful call to this function is guaranteed to return at least one
+ * entry.
+ */
+ iterator resolve(const endpoint_type& e)
+ {
+ boost::system::error_code ec;
+ iterator i = this->service.resolve(this->implementation, e, ec);
+ boost::asio::detail::throw_error(ec);
+ return i;
+ }
+
+ /// Resolve an endpoint to a list of entries.
+ /**
+ * This function is used to resolve an endpoint into a list of endpoint
+ * entries.
+ *
+ * @param e An endpoint object that determines what endpoints will be
+ * returned.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns A forward-only iterator that can be used to traverse the list
+ * of endpoint entries. Returns a default constructed iterator if an error
+ * occurs.
+ *
+ * @note A default constructed iterator represents the end of the list.
+ *
+ * A successful call to this function is guaranteed to return at least one
+ * entry.
+ */
+ iterator resolve(const endpoint_type& e, boost::system::error_code& ec)
+ {
+ return this->service.resolve(this->implementation, e, ec);
+ }
+
+ /// Asynchronously resolve an endpoint to a list of entries.
+ /**
+ * This function is used to asynchronously resolve an endpoint into a list of
+ * endpoint entries.
+ *
+ * @param e An endpoint object that determines what endpoints will be
+ * returned.
+ *
+ * @param handler The handler to be called when the resolve operation
+ * completes. Copies will be made of the handler as required. The function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * resolver::iterator iterator // Forward-only iterator that can
+ * // be used to traverse the list
+ * // of endpoint entries.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note A default constructed iterator represents the end of the list.
+ *
+ * A successful resolve operation is guaranteed to pass at least one entry to
+ * the handler.
+ */
+ template <typename ResolveHandler>
+ void async_resolve(const endpoint_type& e, ResolveHandler handler)
+ {
+ return this->service.async_resolve(this->implementation, e, handler);
+ }
+};
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_BASIC_RESOLVER_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ip/basic_resolver_entry.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ip/basic_resolver_entry.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,97 @@
+//
+// basic_resolver_entry.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_BASIC_RESOLVER_ENTRY_HPP
+#define BOOST_ASIO_IP_BASIC_RESOLVER_ENTRY_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <string>
+#include <boost/asio/detail/pop_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// An entry produced by a resolver.
+/**
+ * The boost::asio::ip::basic_resolver_entry class template describes an entry
+ * as returned by a resolver.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename InternetProtocol>
+class basic_resolver_entry
+{
+public:
+ /// The protocol type associated with the endpoint entry.
+ typedef InternetProtocol protocol_type;
+
+ /// The endpoint type associated with the endpoint entry.
+ typedef typename InternetProtocol::endpoint endpoint_type;
+
+ /// Default constructor.
+ basic_resolver_entry()
+ {
+ }
+
+ /// Construct with specified endpoint, host name and service name.
+ basic_resolver_entry(const endpoint_type& endpoint,
+ const std::string& host_name, const std::string& service_name)
+ : endpoint_(endpoint),
+ host_name_(host_name),
+ service_name_(service_name)
+ {
+ }
+
+ /// Get the endpoint associated with the entry.
+ endpoint_type endpoint() const
+ {
+ return endpoint_;
+ }
+
+ /// Convert to the endpoint associated with the entry.
+ operator endpoint_type() const
+ {
+ return endpoint_;
+ }
+
+ /// Get the host name associated with the entry.
+ std::string host_name() const
+ {
+ return host_name_;
+ }
+
+ /// Get the service name associated with the entry.
+ std::string service_name() const
+ {
+ return service_name_;
+ }
+
+private:
+ endpoint_type endpoint_;
+ std::string host_name_;
+ std::string service_name_;
+};
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_BASIC_RESOLVER_ENTRY_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ip/basic_resolver_iterator.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ip/basic_resolver_iterator.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,156 @@
+//
+// basic_resolver_iterator.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP
+#define BOOST_ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/optional.hpp>
+#include <boost/shared_ptr.hpp>
+#include <cstring>
+#include <string>
+#include <vector>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/ip/basic_resolver_entry.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// An iterator over the entries produced by a resolver.
+/**
+ * The boost::asio::ip::basic_resolver_iterator class template is used to define
+ * iterators over the results returned by a resolver.
+ *
+ * The iterator's value_type, obtained when the iterator is dereferenced, is:
+ * @code const basic_resolver_entry<InternetProtocol> @endcode
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename InternetProtocol>
+class basic_resolver_iterator
+ : public boost::iterator_facade<
+ basic_resolver_iterator<InternetProtocol>,
+ const basic_resolver_entry<InternetProtocol>,
+ boost::forward_traversal_tag>
+{
+public:
+ /// Default constructor creates an end iterator.
+ basic_resolver_iterator()
+ {
+ }
+
+ /// Create an iterator from an addrinfo list returned by getaddrinfo.
+ static basic_resolver_iterator create(
+ boost::asio::detail::addrinfo_type* address_info,
+ const std::string& host_name, const std::string& service_name)
+ {
+ basic_resolver_iterator iter;
+ if (!address_info)
+ return iter;
+
+ std::string actual_host_name = host_name;
+ if (address_info->ai_canonname)
+ actual_host_name = address_info->ai_canonname;
+
+ iter.values_.reset(new values_type);
+
+ while (address_info)
+ {
+ if (address_info->ai_family == PF_INET
+ || address_info->ai_family == PF_INET6)
+ {
+ using namespace std; // For memcpy.
+ typename InternetProtocol::endpoint endpoint;
+ endpoint.resize(static_cast<std::size_t>(address_info->ai_addrlen));
+ memcpy(endpoint.data(), address_info->ai_addr,
+ address_info->ai_addrlen);
+ iter.values_->push_back(
+ basic_resolver_entry<InternetProtocol>(endpoint,
+ actual_host_name, service_name));
+ }
+ address_info = address_info->ai_next;
+ }
+
+ if (iter.values_->size())
+ iter.iter_ = iter.values_->begin();
+ else
+ iter.values_.reset();
+
+ return iter;
+ }
+
+ /// Create an iterator from an endpoint, host name and service name.
+ static basic_resolver_iterator create(
+ const typename InternetProtocol::endpoint& endpoint,
+ const std::string& host_name, const std::string& service_name)
+ {
+ basic_resolver_iterator iter;
+ iter.values_.reset(new values_type);
+ iter.values_->push_back(
+ basic_resolver_entry<InternetProtocol>(
+ endpoint, host_name, service_name));
+ iter.iter_ = iter.values_->begin();
+ return iter;
+ }
+
+private:
+ friend class boost::iterator_core_access;
+
+ void increment()
+ {
+ if (++*iter_ == values_->end())
+ {
+ // Reset state to match a default constructed end iterator.
+ values_.reset();
+ typedef typename values_type::const_iterator values_iterator_type;
+ iter_.reset();
+ }
+ }
+
+ bool equal(const basic_resolver_iterator& other) const
+ {
+ if (!values_ && !other.values_)
+ return true;
+ if (values_ != other.values_)
+ return false;
+ return *iter_ == *other.iter_;
+ }
+
+ const basic_resolver_entry<InternetProtocol>& dereference() const
+ {
+ return **iter_;
+ }
+
+ typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type;
+ typedef typename values_type::const_iterator values_iter_type;
+ boost::shared_ptr<values_type> values_;
+ boost::optional<values_iter_type> iter_;
+};
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ip/basic_resolver_query.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ip/basic_resolver_query.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,151 @@
+//
+// basic_resolver_query.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_BASIC_RESOLVER_QUERY_HPP
+#define BOOST_ASIO_IP_BASIC_RESOLVER_QUERY_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <string>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/ip/resolver_query_base.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// An query to be passed to a resolver.
+/**
+ * The boost::asio::ip::basic_resolver_query class template describes a query
+ * that can be passed to a resolver.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename InternetProtocol>
+class basic_resolver_query
+ : public resolver_query_base
+{
+public:
+ /// The protocol type associated with the endpoint query.
+ typedef InternetProtocol protocol_type;
+
+ /// Construct with specified service name for any protocol.
+ basic_resolver_query(const std::string& service_name,
+ int flags = passive | address_configured)
+ : hints_(),
+ host_name_(),
+ service_name_(service_name)
+ {
+ typename InternetProtocol::endpoint endpoint;
+ hints_.ai_flags = flags;
+ hints_.ai_family = PF_UNSPEC;
+ hints_.ai_socktype = endpoint.protocol().type();
+ hints_.ai_protocol = endpoint.protocol().protocol();
+ hints_.ai_addrlen = 0;
+ hints_.ai_canonname = 0;
+ hints_.ai_addr = 0;
+ hints_.ai_next = 0;
+ }
+
+ /// Construct with specified service name for a given protocol.
+ basic_resolver_query(const protocol_type& protocol,
+ const std::string& service_name,
+ int flags = passive | address_configured)
+ : hints_(),
+ host_name_(),
+ service_name_(service_name)
+ {
+ hints_.ai_flags = flags;
+ hints_.ai_family = protocol.family();
+ hints_.ai_socktype = protocol.type();
+ hints_.ai_protocol = protocol.protocol();
+ hints_.ai_addrlen = 0;
+ hints_.ai_canonname = 0;
+ hints_.ai_addr = 0;
+ hints_.ai_next = 0;
+ }
+
+ /// Construct with specified host name and service name for any protocol.
+ basic_resolver_query(const std::string& host_name,
+ const std::string& service_name, int flags = address_configured)
+ : hints_(),
+ host_name_(host_name),
+ service_name_(service_name)
+ {
+ typename InternetProtocol::endpoint endpoint;
+ hints_.ai_flags = flags;
+ hints_.ai_family = PF_UNSPEC;
+ hints_.ai_socktype = endpoint.protocol().type();
+ hints_.ai_protocol = endpoint.protocol().protocol();
+ hints_.ai_addrlen = 0;
+ hints_.ai_canonname = 0;
+ hints_.ai_addr = 0;
+ hints_.ai_next = 0;
+ }
+
+ /// Construct with specified host name and service name for a given protocol.
+ basic_resolver_query(const protocol_type& protocol,
+ const std::string& host_name, const std::string& service_name,
+ int flags = address_configured)
+ : hints_(),
+ host_name_(host_name),
+ service_name_(service_name)
+ {
+ hints_.ai_flags = flags;
+ hints_.ai_family = protocol.family();
+ hints_.ai_socktype = protocol.type();
+ hints_.ai_protocol = protocol.protocol();
+ hints_.ai_addrlen = 0;
+ hints_.ai_canonname = 0;
+ hints_.ai_addr = 0;
+ hints_.ai_next = 0;
+ }
+
+ /// Get the hints associated with the query.
+ const boost::asio::detail::addrinfo_type& hints() const
+ {
+ return hints_;
+ }
+
+ /// Get the host name associated with the query.
+ std::string host_name() const
+ {
+ return host_name_;
+ }
+
+ /// Get the service name associated with the query.
+ std::string service_name() const
+ {
+ return service_name_;
+ }
+
+private:
+ boost::asio::detail::addrinfo_type hints_;
+ std::string host_name_;
+ std::string service_name_;
+};
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_BASIC_RESOLVER_QUERY_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ip/detail/socket_option.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ip/detail/socket_option.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,580 @@
+//
+// socket_option.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_DETAIL_SOCKET_OPTION_HPP
+#define BOOST_ASIO_IP_DETAIL_SOCKET_OPTION_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <cstring>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/ip/address.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+namespace detail {
+namespace socket_option {
+
+// Helper template for implementing multicast enable loopback options.
+template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
+class multicast_enable_loopback
+{
+public:
+#if defined(__sun) || defined(__osf__)
+ typedef unsigned char ipv4_value_type;
+ typedef unsigned char ipv6_value_type;
+#elif defined(_AIX) || defined(__hpux)
+ typedef unsigned char ipv4_value_type;
+ typedef unsigned int ipv6_value_type;
+#else
+ typedef int ipv4_value_type;
+ typedef int ipv6_value_type;
+#endif
+
+ // Default constructor.
+ multicast_enable_loopback()
+ : ipv4_value_(0),
+ ipv6_value_(0)
+ {
+ }
+
+ // Construct with a specific option value.
+ explicit multicast_enable_loopback(bool v)
+ : ipv4_value_(v ? 1 : 0),
+ ipv6_value_(v ? 1 : 0)
+ {
+ }
+
+ // Set the value of the boolean.
+ multicast_enable_loopback& operator=(bool v)
+ {
+ ipv4_value_ = v ? 1 : 0;
+ ipv6_value_ = v ? 1 : 0;
+ return *this;
+ }
+
+ // Get the current value of the boolean.
+ bool value() const
+ {
+ return !!ipv4_value_;
+ }
+
+ // Convert to bool.
+ operator bool() const
+ {
+ return !!ipv4_value_;
+ }
+
+ // Test for false.
+ bool operator!() const
+ {
+ return !ipv4_value_;
+ }
+
+ // Get the level of the socket option.
+ template <typename Protocol>
+ int level(const Protocol& protocol) const
+ {
+ if (protocol.family() == PF_INET6)
+ return IPv6_Level;
+ return IPv4_Level;
+ }
+
+ // Get the name of the socket option.
+ template <typename Protocol>
+ int name(const Protocol& protocol) const
+ {
+ if (protocol.family() == PF_INET6)
+ return IPv6_Name;
+ return IPv4_Name;
+ }
+
+ // Get the address of the boolean data.
+ template <typename Protocol>
+ void* data(const Protocol& protocol)
+ {
+ if (protocol.family() == PF_INET6)
+ return &ipv6_value_;
+ return &ipv4_value_;
+ }
+
+ // Get the address of the boolean data.
+ template <typename Protocol>
+ const void* data(const Protocol& protocol) const
+ {
+ if (protocol.family() == PF_INET6)
+ return &ipv6_value_;
+ return &ipv4_value_;
+ }
+
+ // Get the size of the boolean data.
+ template <typename Protocol>
+ std::size_t size(const Protocol& protocol) const
+ {
+ if (protocol.family() == PF_INET6)
+ return sizeof(ipv6_value_);
+ return sizeof(ipv4_value_);
+ }
+
+ // Set the size of the boolean data.
+ template <typename Protocol>
+ void resize(const Protocol& protocol, std::size_t s)
+ {
+ if (protocol.family() == PF_INET6)
+ {
+ if (s != sizeof(ipv6_value_))
+ {
+ throw std::length_error(
+ "multicast_enable_loopback socket option resize");
+ }
+ ipv4_value_ = ipv6_value_ ? 1 : 0;
+ }
+ else
+ {
+ if (s != sizeof(ipv4_value_))
+ {
+ throw std::length_error(
+ "multicast_enable_loopback socket option resize");
+ }
+ ipv6_value_ = ipv4_value_ ? 1 : 0;
+ }
+ }
+
+private:
+ ipv4_value_type ipv4_value_;
+ ipv6_value_type ipv6_value_;
+};
+
+// Helper template for implementing unicast hops options.
+template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
+class unicast_hops
+{
+public:
+ // Default constructor.
+ unicast_hops()
+ : value_(0)
+ {
+ }
+
+ // Construct with a specific option value.
+ explicit unicast_hops(int v)
+ : value_(v)
+ {
+ }
+
+ // Set the value of the option.
+ unicast_hops& operator=(int v)
+ {
+ value_ = v;
+ return *this;
+ }
+
+ // Get the current value of the option.
+ int value() const
+ {
+ return value_;
+ }
+
+ // Get the level of the socket option.
+ template <typename Protocol>
+ int level(const Protocol& protocol) const
+ {
+ if (protocol.family() == PF_INET6)
+ return IPv6_Level;
+ return IPv4_Level;
+ }
+
+ // Get the name of the socket option.
+ template <typename Protocol>
+ int name(const Protocol& protocol) const
+ {
+ if (protocol.family() == PF_INET6)
+ return IPv6_Name;
+ return IPv4_Name;
+ }
+
+ // Get the address of the data.
+ template <typename Protocol>
+ int* data(const Protocol&)
+ {
+ return &value_;
+ }
+
+ // Get the address of the data.
+ template <typename Protocol>
+ const int* data(const Protocol&) const
+ {
+ return &value_;
+ }
+
+ // Get the size of the data.
+ template <typename Protocol>
+ std::size_t size(const Protocol&) const
+ {
+ return sizeof(value_);
+ }
+
+ // Set the size of the data.
+ template <typename Protocol>
+ void resize(const Protocol&, std::size_t s)
+ {
+ if (s != sizeof(value_))
+ throw std::length_error("unicast hops socket option resize");
+#if defined(__hpux)
+ if (value_ < 0)
+ value_ = value_ & 0xFF;
+#endif
+ }
+
+private:
+ int value_;
+};
+
+// Helper template for implementing multicast hops options.
+template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
+class multicast_hops
+{
+public:
+#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
+ typedef int ipv4_value_type;
+#else
+ typedef unsigned char ipv4_value_type;
+#endif
+ typedef int ipv6_value_type;
+
+ // Default constructor.
+ multicast_hops()
+ : ipv4_value_(0),
+ ipv6_value_(0)
+ {
+ }
+
+ // Construct with a specific option value.
+ explicit multicast_hops(int v)
+ {
+ if (v < 0 || v > 255)
+ throw std::out_of_range("multicast hops value out of range");
+ ipv4_value_ = (ipv4_value_type)v;
+ ipv6_value_ = v;
+ }
+
+ // Set the value of the option.
+ multicast_hops& operator=(int v)
+ {
+ if (v < 0 || v > 255)
+ throw std::out_of_range("multicast hops value out of range");
+ ipv4_value_ = (ipv4_value_type)v;
+ ipv6_value_ = v;
+ return *this;
+ }
+
+ // Get the current value of the option.
+ int value() const
+ {
+ return ipv6_value_;
+ }
+
+ // Get the level of the socket option.
+ template <typename Protocol>
+ int level(const Protocol& protocol) const
+ {
+ if (protocol.family() == PF_INET6)
+ return IPv6_Level;
+ return IPv4_Level;
+ }
+
+ // Get the name of the socket option.
+ template <typename Protocol>
+ int name(const Protocol& protocol) const
+ {
+ if (protocol.family() == PF_INET6)
+ return IPv6_Name;
+ return IPv4_Name;
+ }
+
+ // Get the address of the data.
+ template <typename Protocol>
+ void* data(const Protocol& protocol)
+ {
+ if (protocol.family() == PF_INET6)
+ return &ipv6_value_;
+ return &ipv4_value_;
+ }
+
+ // Get the address of the data.
+ template <typename Protocol>
+ const void* data(const Protocol& protocol) const
+ {
+ if (protocol.family() == PF_INET6)
+ return &ipv6_value_;
+ return &ipv4_value_;
+ }
+
+ // Get the size of the data.
+ template <typename Protocol>
+ std::size_t size(const Protocol& protocol) const
+ {
+ if (protocol.family() == PF_INET6)
+ return sizeof(ipv6_value_);
+ return sizeof(ipv4_value_);
+ }
+
+ // Set the size of the data.
+ template <typename Protocol>
+ void resize(const Protocol& protocol, std::size_t s)
+ {
+ if (protocol.family() == PF_INET6)
+ {
+ if (s != sizeof(ipv6_value_))
+ throw std::length_error("multicast hops socket option resize");
+ if (ipv6_value_ < 0)
+ ipv4_value_ = 0;
+ else if (ipv6_value_ > 255)
+ ipv4_value_ = 255;
+ else
+ ipv4_value_ = (ipv4_value_type)ipv6_value_;
+ }
+ else
+ {
+ if (s != sizeof(ipv4_value_))
+ throw std::length_error("multicast hops socket option resize");
+ ipv6_value_ = ipv4_value_;
+ }
+ }
+
+private:
+ ipv4_value_type ipv4_value_;
+ ipv6_value_type ipv6_value_;
+};
+
+// Helper template for implementing ip_mreq-based options.
+template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
+class multicast_request
+{
+public:
+ // Default constructor.
+ multicast_request()
+ {
+ ipv4_value_.imr_multiaddr.s_addr =
+ boost::asio::detail::socket_ops::host_to_network_long(
+ boost::asio::ip::address_v4::any().to_ulong());
+ ipv4_value_.imr_interface.s_addr =
+ boost::asio::detail::socket_ops::host_to_network_long(
+ boost::asio::ip::address_v4::any().to_ulong());
+
+ boost::asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
+ ipv6_value_.ipv6mr_multiaddr = tmp_addr;
+ ipv6_value_.ipv6mr_interface = 0;
+ }
+
+ // Construct with multicast address only.
+ explicit multicast_request(const boost::asio::ip::address& multicast_address)
+ {
+ if (multicast_address.is_v6())
+ {
+ ipv4_value_.imr_multiaddr.s_addr =
+ boost::asio::detail::socket_ops::host_to_network_long(
+ boost::asio::ip::address_v4::any().to_ulong());
+ ipv4_value_.imr_interface.s_addr =
+ boost::asio::detail::socket_ops::host_to_network_long(
+ boost::asio::ip::address_v4::any().to_ulong());
+
+ using namespace std; // For memcpy.
+ boost::asio::ip::address_v6 ipv6_address = multicast_address.to_v6();
+ boost::asio::ip::address_v6::bytes_type bytes = ipv6_address.to_bytes();
+ memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.elems, 16);
+ ipv6_value_.ipv6mr_interface = 0;
+ }
+ else
+ {
+ ipv4_value_.imr_multiaddr.s_addr =
+ boost::asio::detail::socket_ops::host_to_network_long(
+ multicast_address.to_v4().to_ulong());
+ ipv4_value_.imr_interface.s_addr =
+ boost::asio::detail::socket_ops::host_to_network_long(
+ boost::asio::ip::address_v4::any().to_ulong());
+
+ boost::asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
+ ipv6_value_.ipv6mr_multiaddr = tmp_addr;
+ ipv6_value_.ipv6mr_interface = 0;
+ }
+ }
+
+ // Construct with multicast address and IPv4 address specifying an interface.
+ explicit multicast_request(
+ const boost::asio::ip::address_v4& multicast_address,
+ const boost::asio::ip::address_v4& network_interface
+ = boost::asio::ip::address_v4::any())
+ {
+ ipv4_value_.imr_multiaddr.s_addr =
+ boost::asio::detail::socket_ops::host_to_network_long(
+ multicast_address.to_ulong());
+ ipv4_value_.imr_interface.s_addr =
+ boost::asio::detail::socket_ops::host_to_network_long(
+ network_interface.to_ulong());
+
+ boost::asio::detail::in6_addr_type tmp_addr = IN6ADDR_ANY_INIT;
+ ipv6_value_.ipv6mr_multiaddr = tmp_addr;
+ ipv6_value_.ipv6mr_interface = 0;
+ }
+
+ // Construct with multicast address and IPv6 network interface index.
+ explicit multicast_request(
+ const boost::asio::ip::address_v6& multicast_address,
+ unsigned long network_interface = 0)
+ {
+ ipv4_value_.imr_multiaddr.s_addr =
+ boost::asio::detail::socket_ops::host_to_network_long(
+ boost::asio::ip::address_v4::any().to_ulong());
+ ipv4_value_.imr_interface.s_addr =
+ boost::asio::detail::socket_ops::host_to_network_long(
+ boost::asio::ip::address_v4::any().to_ulong());
+
+ using namespace std; // For memcpy.
+ boost::asio::ip::address_v6::bytes_type bytes =
+ multicast_address.to_bytes();
+ memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.elems, 16);
+ ipv6_value_.ipv6mr_interface = network_interface;
+ }
+
+ // Get the level of the socket option.
+ template <typename Protocol>
+ int level(const Protocol& protocol) const
+ {
+ if (protocol.family() == PF_INET6)
+ return IPv6_Level;
+ return IPv4_Level;
+ }
+
+ // Get the name of the socket option.
+ template <typename Protocol>
+ int name(const Protocol& protocol) const
+ {
+ if (protocol.family() == PF_INET6)
+ return IPv6_Name;
+ return IPv4_Name;
+ }
+
+ // Get the address of the option data.
+ template <typename Protocol>
+ const void* data(const Protocol& protocol) const
+ {
+ if (protocol.family() == PF_INET6)
+ return &ipv6_value_;
+ return &ipv4_value_;
+ }
+
+ // Get the size of the option data.
+ template <typename Protocol>
+ std::size_t size(const Protocol& protocol) const
+ {
+ if (protocol.family() == PF_INET6)
+ return sizeof(ipv6_value_);
+ return sizeof(ipv4_value_);
+ }
+
+private:
+ boost::asio::detail::in4_mreq_type ipv4_value_;
+ boost::asio::detail::in6_mreq_type ipv6_value_;
+};
+
+// Helper template for implementing options that specify a network interface.
+template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>
+class network_interface
+{
+public:
+ // Default constructor.
+ network_interface()
+ {
+ ipv4_value_.s_addr =
+ boost::asio::detail::socket_ops::host_to_network_long(
+ boost::asio::ip::address_v4::any().to_ulong());
+ ipv6_value_ = 0;
+ }
+
+ // Construct with IPv4 interface.
+ explicit network_interface(const boost::asio::ip::address_v4& ipv4_interface)
+ {
+ ipv4_value_.s_addr =
+ boost::asio::detail::socket_ops::host_to_network_long(
+ ipv4_interface.to_ulong());
+ ipv6_value_ = 0;
+ }
+
+ // Construct with IPv6 interface.
+ explicit network_interface(unsigned int ipv6_interface)
+ {
+ ipv4_value_.s_addr =
+ boost::asio::detail::socket_ops::host_to_network_long(
+ boost::asio::ip::address_v4::any().to_ulong());
+ ipv6_value_ = ipv6_interface;
+ }
+
+ // Get the level of the socket option.
+ template <typename Protocol>
+ int level(const Protocol& protocol) const
+ {
+ if (protocol.family() == PF_INET6)
+ return IPv6_Level;
+ return IPv4_Level;
+ }
+
+ // Get the name of the socket option.
+ template <typename Protocol>
+ int name(const Protocol& protocol) const
+ {
+ if (protocol.family() == PF_INET6)
+ return IPv6_Name;
+ return IPv4_Name;
+ }
+
+ // Get the address of the option data.
+ template <typename Protocol>
+ const void* data(const Protocol& protocol) const
+ {
+ if (protocol.family() == PF_INET6)
+ return &ipv6_value_;
+ return &ipv4_value_;
+ }
+
+ // Get the size of the option data.
+ template <typename Protocol>
+ std::size_t size(const Protocol& protocol) const
+ {
+ if (protocol.family() == PF_INET6)
+ return sizeof(ipv6_value_);
+ return sizeof(ipv4_value_);
+ }
+
+private:
+ boost::asio::detail::in4_addr_type ipv4_value_;
+ unsigned int ipv6_value_;
+};
+
+} // namespace socket_option
+} // namespace detail
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_DETAIL_SOCKET_OPTION_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ip/host_name.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ip/host_name.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,64 @@
+//
+// host_name.hpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_HOST_NAME_HPP
+#define BOOST_ASIO_IP_HOST_NAME_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <string>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// Get the current host name.
+std::string host_name();
+
+/// Get the current host name.
+std::string host_name(boost::system::error_code& ec);
+
+inline std::string host_name()
+{
+ char name[1024];
+ boost::system::error_code ec;
+ if (boost::asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0)
+ {
+ boost::asio::detail::throw_error(ec);
+ return std::string();
+ }
+ return std::string(name);
+}
+
+inline std::string host_name(boost::system::error_code& ec)
+{
+ char name[1024];
+ if (boost::asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0)
+ return std::string();
+ return std::string(name);
+}
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_HOST_NAME_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ip/icmp.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ip/icmp.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,120 @@
+//
+// icmp.hpp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_ICMP_HPP
+#define BOOST_ASIO_IP_ICMP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/basic_raw_socket.hpp>
+#include <boost/asio/ip/basic_endpoint.hpp>
+#include <boost/asio/ip/basic_resolver.hpp>
+#include <boost/asio/ip/basic_resolver_iterator.hpp>
+#include <boost/asio/ip/basic_resolver_query.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// Encapsulates the flags needed for ICMP.
+/**
+ * The boost::asio::ip::icmp class contains flags necessary for ICMP sockets.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Safe.
+ *
+ * @par Concepts:
+ * Protocol, InternetProtocol.
+ */
+class icmp
+{
+public:
+ /// The type of a ICMP endpoint.
+ typedef basic_endpoint<icmp> endpoint;
+
+ /// The type of a resolver query.
+ typedef basic_resolver_query<icmp> resolver_query;
+
+ /// The type of a resolver iterator.
+ typedef basic_resolver_iterator<icmp> resolver_iterator;
+
+ /// Construct to represent the IPv4 ICMP protocol.
+ static icmp v4()
+ {
+ return icmp(IPPROTO_ICMP, PF_INET);
+ }
+
+ /// Construct to represent the IPv6 ICMP protocol.
+ static icmp v6()
+ {
+ return icmp(IPPROTO_ICMPV6, PF_INET6);
+ }
+
+ /// Obtain an identifier for the type of the protocol.
+ int type() const
+ {
+ return SOCK_RAW;
+ }
+
+ /// Obtain an identifier for the protocol.
+ int protocol() const
+ {
+ return protocol_;
+ }
+
+ /// Obtain an identifier for the protocol family.
+ int family() const
+ {
+ return family_;
+ }
+
+ /// The ICMP socket type.
+ typedef basic_raw_socket<icmp> socket;
+
+ /// The ICMP resolver type.
+ typedef basic_resolver<icmp> resolver;
+
+ /// Compare two protocols for equality.
+ friend bool operator==(const icmp& p1, const icmp& p2)
+ {
+ return p1.protocol_ == p2.protocol_ && p1.family_ == p2.family_;
+ }
+
+ /// Compare two protocols for inequality.
+ friend bool operator!=(const icmp& p1, const icmp& p2)
+ {
+ return p1.protocol_ != p2.protocol_ || p1.family_ != p2.family_;
+ }
+
+private:
+ // Construct with a specific family.
+ explicit icmp(int protocol, int family)
+ : protocol_(protocol),
+ family_(family)
+ {
+ }
+
+ int protocol_;
+ int family_;
+};
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_ICMP_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ip/multicast.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ip/multicast.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,183 @@
+//
+// multicast.hpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_MULTICAST_HPP
+#define BOOST_ASIO_IP_MULTICAST_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/ip/detail/socket_option.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+namespace multicast {
+
+/// Socket option to join a multicast group on a specified interface.
+/**
+ * Implements the IPPROTO_IP/IP_ADD_MEMBERSHIP socket option.
+ *
+ * @par Examples
+ * Setting the option to join a multicast group:
+ * @code
+ * boost::asio::ip::udp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::address multicast_address =
+ * boost::asio::ip::address::from_string("225.0.0.1");
+ * boost::asio::ip::multicast::join_group option(multicast_address);
+ * socket.set_option(option);
+ * @endcode
+ *
+ * @par Concepts:
+ * SettableSocketOption.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+typedef implementation_defined join_group;
+#else
+typedef boost::asio::ip::detail::socket_option::multicast_request<
+ IPPROTO_IP, IP_ADD_MEMBERSHIP, IPPROTO_IPV6, IPV6_JOIN_GROUP> join_group;
+#endif
+
+/// Socket option to leave a multicast group on a specified interface.
+/**
+ * Implements the IPPROTO_IP/IP_DROP_MEMBERSHIP socket option.
+ *
+ * @par Examples
+ * Setting the option to leave a multicast group:
+ * @code
+ * boost::asio::ip::udp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::address multicast_address =
+ * boost::asio::ip::address::from_string("225.0.0.1");
+ * boost::asio::ip::multicast::leave_group option(multicast_address);
+ * socket.set_option(option);
+ * @endcode
+ *
+ * @par Concepts:
+ * SettableSocketOption.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+typedef implementation_defined leave_group;
+#else
+typedef boost::asio::ip::detail::socket_option::multicast_request<
+ IPPROTO_IP, IP_DROP_MEMBERSHIP, IPPROTO_IPV6, IPV6_LEAVE_GROUP> leave_group;
+#endif
+
+/// Socket option for local interface to use for outgoing multicast packets.
+/**
+ * Implements the IPPROTO_IP/IP_MULTICAST_IF socket option.
+ *
+ * @par Examples
+ * Setting the option:
+ * @code
+ * boost::asio::ip::udp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::address_v4 local_interface =
+ * boost::asio::ip::address_v4::from_string("1.2.3.4");
+ * boost::asio::ip::multicast::outbound_interface option(local_interface);
+ * socket.set_option(option);
+ * @endcode
+ *
+ * @par Concepts:
+ * SettableSocketOption.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+typedef implementation_defined outbound_interface;
+#else
+typedef boost::asio::ip::detail::socket_option::network_interface<
+ IPPROTO_IP, IP_MULTICAST_IF, IPPROTO_IPV6, IPV6_MULTICAST_IF>
+ outbound_interface;
+#endif
+
+/// Socket option for time-to-live associated with outgoing multicast packets.
+/**
+ * Implements the IPPROTO_IP/IP_MULTICAST_TTL socket option.
+ *
+ * @par Examples
+ * Setting the option:
+ * @code
+ * boost::asio::ip::udp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::multicast::hops option(4);
+ * socket.set_option(option);
+ * @endcode
+ *
+ * @par
+ * Getting the current option value:
+ * @code
+ * boost::asio::ip::udp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::multicast::hops option;
+ * socket.get_option(option);
+ * int ttl = option.value();
+ * @endcode
+ *
+ * @par Concepts:
+ * GettableSocketOption, SettableSocketOption.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+typedef implementation_defined hops;
+#else
+typedef boost::asio::ip::detail::socket_option::multicast_hops<
+ IPPROTO_IP, IP_MULTICAST_TTL, IPPROTO_IPV6, IPV6_MULTICAST_HOPS> hops;
+#endif
+
+/// Socket option determining whether outgoing multicast packets will be
+/// received on the same socket if it is a member of the multicast group.
+/**
+ * Implements the IPPROTO_IP/IP_MULTICAST_LOOP socket option.
+ *
+ * @par Examples
+ * Setting the option:
+ * @code
+ * boost::asio::ip::udp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::multicast::enable_loopback option(true);
+ * socket.set_option(option);
+ * @endcode
+ *
+ * @par
+ * Getting the current option value:
+ * @code
+ * boost::asio::ip::udp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::multicast::enable_loopback option;
+ * socket.get_option(option);
+ * bool is_set = option.value();
+ * @endcode
+ *
+ * @par Concepts:
+ * GettableSocketOption, SettableSocketOption.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+typedef implementation_defined enable_loopback;
+#else
+typedef boost::asio::ip::detail::socket_option::multicast_enable_loopback<
+ IPPROTO_IP, IP_MULTICAST_LOOP, IPPROTO_IPV6, IPV6_MULTICAST_LOOP>
+ enable_loopback;
+#endif
+
+} // namespace multicast
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_MULTICAST_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ip/resolver_query_base.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ip/resolver_query_base.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,109 @@
+//
+// resolver_query_base.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_RESOLVER_QUERY_BASE_HPP
+#define BOOST_ASIO_IP_RESOLVER_QUERY_BASE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/socket_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// The resolver_query_base class is used as a base for the
+/// basic_resolver_query class templates to provide a common place to define
+/// the flag constants.
+class resolver_query_base
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// Determine the canonical name of the host specified in the query.
+ static const int canonical_name = implementation_defined;
+
+ /// Indicate that returned endpoint is intended for use as a locally bound
+ /// socket endpoint.
+ static const int passive = implementation_defined;
+
+ /// Host name should be treated as a numeric string defining an IPv4 or IPv6
+ /// address and no name resolution should be attempted.
+ static const int numeric_host = implementation_defined;
+
+ /// Service name should be treated as a numeric string defining a port number
+ /// and no name resolution should be attempted.
+ static const int numeric_service = implementation_defined;
+
+ /// If the query protocol family is specified as IPv6, return IPv4-mapped
+ /// IPv6 addresses on finding no IPv6 addresses.
+ static const int v4_mapped = implementation_defined;
+
+ /// If used with v4_mapped, return all matching IPv6 and IPv4 addresses.
+ static const int all_matching = implementation_defined;
+
+ /// Only return IPv4 addresses if a non-loopback IPv4 address is configured
+ /// for the system. Only return IPv6 addresses if a non-loopback IPv6 address
+ /// is configured for the system.
+ static const int address_configured = implementation_defined;
+#else
+ BOOST_STATIC_CONSTANT(int, canonical_name = AI_CANONNAME);
+ BOOST_STATIC_CONSTANT(int, passive = AI_PASSIVE);
+ BOOST_STATIC_CONSTANT(int, numeric_host = AI_NUMERICHOST);
+# if defined(AI_NUMERICSERV)
+ BOOST_STATIC_CONSTANT(int, numeric_service = AI_NUMERICSERV);
+# else
+ BOOST_STATIC_CONSTANT(int, numeric_service = 0);
+# endif
+# if defined(AI_V4MAPPED)
+ BOOST_STATIC_CONSTANT(int, v4_mapped = AI_V4MAPPED);
+# else
+ BOOST_STATIC_CONSTANT(int, v4_mapped = 0);
+# endif
+# if defined(AI_ALL)
+ BOOST_STATIC_CONSTANT(int, all_matching = AI_ALL);
+# else
+ BOOST_STATIC_CONSTANT(int, all_matching = 0);
+# endif
+# if defined(AI_ADDRCONFIG)
+ BOOST_STATIC_CONSTANT(int, address_configured = AI_ADDRCONFIG);
+# else
+ BOOST_STATIC_CONSTANT(int, address_configured = 0);
+# endif
+#endif
+
+protected:
+ /// Protected destructor to prevent deletion through this type.
+ ~resolver_query_base()
+ {
+ }
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+private:
+ // Workaround to enable the empty base optimisation with Borland C++.
+ char dummy_;
+#endif
+};
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_RESOLVER_QUERY_BASE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ip/resolver_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ip/resolver_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,142 @@
+//
+// resolver_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_RESOLVER_SERVICE_HPP
+#define BOOST_ASIO_IP_RESOLVER_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/resolver_service.hpp>
+#include <boost/asio/detail/service_base.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// Default service implementation for a resolver.
+template <typename InternetProtocol>
+class resolver_service
+#if defined(GENERATING_DOCUMENTATION)
+ : public boost::asio::io_service::service
+#else
+ : public boost::asio::detail::service_base<
+ resolver_service<InternetProtocol> >
+#endif
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The unique service identifier.
+ static boost::asio::io_service::id id;
+#endif
+
+ /// The protocol type.
+ typedef InternetProtocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename InternetProtocol::endpoint endpoint_type;
+
+ /// The query type.
+ typedef typename InternetProtocol::resolver_query query_type;
+
+ /// The iterator type.
+ typedef typename InternetProtocol::resolver_iterator iterator_type;
+
+private:
+ // The type of the platform-specific implementation.
+ typedef boost::asio::detail::resolver_service<InternetProtocol>
+ service_impl_type;
+
+public:
+ /// The type of a resolver implementation.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined implementation_type;
+#else
+ typedef typename service_impl_type::implementation_type implementation_type;
+#endif
+
+ /// Construct a new resolver service for the specified io_service.
+ explicit resolver_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ resolver_service<InternetProtocol> >(io_service),
+ service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ {
+ }
+
+ /// Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ /// Construct a new resolver implementation.
+ void construct(implementation_type& impl)
+ {
+ service_impl_.construct(impl);
+ }
+
+ /// Destroy a resolver implementation.
+ void destroy(implementation_type& impl)
+ {
+ service_impl_.destroy(impl);
+ }
+
+ /// Cancel pending asynchronous operations.
+ void cancel(implementation_type& impl)
+ {
+ service_impl_.cancel(impl);
+ }
+
+ /// Resolve a query to a list of entries.
+ iterator_type resolve(implementation_type& impl, const query_type& query,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.resolve(impl, query, ec);
+ }
+
+ /// Asynchronously resolve a query to a list of entries.
+ template <typename Handler>
+ void async_resolve(implementation_type& impl, const query_type& query,
+ Handler handler)
+ {
+ service_impl_.async_resolve(impl, query, handler);
+ }
+
+ /// Resolve an endpoint to a list of entries.
+ iterator_type resolve(implementation_type& impl,
+ const endpoint_type& endpoint, boost::system::error_code& ec)
+ {
+ return service_impl_.resolve(impl, endpoint, ec);
+ }
+
+ /// Asynchronously resolve an endpoint to a list of entries.
+ template <typename ResolveHandler>
+ void async_resolve(implementation_type& impl, const endpoint_type& endpoint,
+ ResolveHandler handler)
+ {
+ return service_impl_.async_resolve(impl, endpoint, handler);
+ }
+
+private:
+ // The service that provides the platform-specific implementation.
+ service_impl_type& service_impl_;
+};
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_RESOLVER_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ip/tcp.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ip/tcp.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,160 @@
+//
+// tcp.hpp
+// ~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_TCP_HPP
+#define BOOST_ASIO_IP_TCP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/basic_socket_acceptor.hpp>
+#include <boost/asio/basic_socket_iostream.hpp>
+#include <boost/asio/basic_stream_socket.hpp>
+#include <boost/asio/ip/basic_endpoint.hpp>
+#include <boost/asio/ip/basic_resolver.hpp>
+#include <boost/asio/ip/basic_resolver_iterator.hpp>
+#include <boost/asio/ip/basic_resolver_query.hpp>
+#include <boost/asio/detail/socket_option.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// Encapsulates the flags needed for TCP.
+/**
+ * The boost::asio::ip::tcp class contains flags necessary for TCP sockets.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Safe.
+ *
+ * @par Concepts:
+ * Protocol, InternetProtocol.
+ */
+class tcp
+{
+public:
+ /// The type of a TCP endpoint.
+ typedef basic_endpoint<tcp> endpoint;
+
+ /// The type of a resolver query.
+ typedef basic_resolver_query<tcp> resolver_query;
+
+ /// The type of a resolver iterator.
+ typedef basic_resolver_iterator<tcp> resolver_iterator;
+
+ /// Construct to represent the IPv4 TCP protocol.
+ static tcp v4()
+ {
+ return tcp(PF_INET);
+ }
+
+ /// Construct to represent the IPv6 TCP protocol.
+ static tcp v6()
+ {
+ return tcp(PF_INET6);
+ }
+
+ /// Obtain an identifier for the type of the protocol.
+ int type() const
+ {
+ return SOCK_STREAM;
+ }
+
+ /// Obtain an identifier for the protocol.
+ int protocol() const
+ {
+ return IPPROTO_TCP;
+ }
+
+ /// Obtain an identifier for the protocol family.
+ int family() const
+ {
+ return family_;
+ }
+
+ /// The TCP socket type.
+ typedef basic_stream_socket<tcp> socket;
+
+ /// The TCP acceptor type.
+ typedef basic_socket_acceptor<tcp> acceptor;
+
+ /// The TCP resolver type.
+ typedef basic_resolver<tcp> resolver;
+
+ /// The TCP iostream type.
+ typedef basic_socket_iostream<tcp> iostream;
+
+ /// Socket option for disabling the Nagle algorithm.
+ /**
+ * Implements the IPPROTO_TCP/TCP_NODELAY socket option.
+ *
+ * @par Examples
+ * Setting the option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::tcp::no_delay option(true);
+ * socket.set_option(option);
+ * @endcode
+ *
+ * @par
+ * Getting the current option value:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::tcp::no_delay option;
+ * socket.get_option(option);
+ * bool is_set = option.value();
+ * @endcode
+ *
+ * @par Concepts:
+ * Socket_Option, Boolean_Socket_Option.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined no_delay;
+#else
+ typedef boost::asio::detail::socket_option::boolean<
+ IPPROTO_TCP, TCP_NODELAY> no_delay;
+#endif
+
+ /// Compare two protocols for equality.
+ friend bool operator==(const tcp& p1, const tcp& p2)
+ {
+ return p1.family_ == p2.family_;
+ }
+
+ /// Compare two protocols for inequality.
+ friend bool operator!=(const tcp& p1, const tcp& p2)
+ {
+ return p1.family_ != p2.family_;
+ }
+
+private:
+ // Construct with a specific family.
+ explicit tcp(int family)
+ : family_(family)
+ {
+ }
+
+ int family_;
+};
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_TCP_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ip/udp.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ip/udp.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,118 @@
+//
+// udp.hpp
+// ~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_UDP_HPP
+#define BOOST_ASIO_IP_UDP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/basic_datagram_socket.hpp>
+#include <boost/asio/ip/basic_endpoint.hpp>
+#include <boost/asio/ip/basic_resolver.hpp>
+#include <boost/asio/ip/basic_resolver_iterator.hpp>
+#include <boost/asio/ip/basic_resolver_query.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// Encapsulates the flags needed for UDP.
+/**
+ * The boost::asio::ip::udp class contains flags necessary for UDP sockets.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Safe.
+ *
+ * @par Concepts:
+ * Protocol, InternetProtocol.
+ */
+class udp
+{
+public:
+ /// The type of a UDP endpoint.
+ typedef basic_endpoint<udp> endpoint;
+
+ /// The type of a resolver query.
+ typedef basic_resolver_query<udp> resolver_query;
+
+ /// The type of a resolver iterator.
+ typedef basic_resolver_iterator<udp> resolver_iterator;
+
+ /// Construct to represent the IPv4 UDP protocol.
+ static udp v4()
+ {
+ return udp(PF_INET);
+ }
+
+ /// Construct to represent the IPv6 UDP protocol.
+ static udp v6()
+ {
+ return udp(PF_INET6);
+ }
+
+ /// Obtain an identifier for the type of the protocol.
+ int type() const
+ {
+ return SOCK_DGRAM;
+ }
+
+ /// Obtain an identifier for the protocol.
+ int protocol() const
+ {
+ return IPPROTO_UDP;
+ }
+
+ /// Obtain an identifier for the protocol family.
+ int family() const
+ {
+ return family_;
+ }
+
+ /// The UDP socket type.
+ typedef basic_datagram_socket<udp> socket;
+
+ /// The UDP resolver type.
+ typedef basic_resolver<udp> resolver;
+
+ /// Compare two protocols for equality.
+ friend bool operator==(const udp& p1, const udp& p2)
+ {
+ return p1.family_ == p2.family_;
+ }
+
+ /// Compare two protocols for inequality.
+ friend bool operator!=(const udp& p1, const udp& p2)
+ {
+ return p1.family_ != p2.family_;
+ }
+
+private:
+ // Construct with a specific family.
+ explicit udp(int family)
+ : family_(family)
+ {
+ }
+
+ int family_;
+};
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_UDP_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ip/unicast.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ip/unicast.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,72 @@
+//
+// unicast.hpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_UNICAST_HPP
+#define BOOST_ASIO_IP_UNICAST_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/ip/detail/socket_option.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+namespace unicast {
+
+/// Socket option for time-to-live associated with outgoing unicast packets.
+/**
+ * Implements the IPPROTO_IP/IP_UNICAST_TTL socket option.
+ *
+ * @par Examples
+ * Setting the option:
+ * @code
+ * boost::asio::ip::udp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::unicast::hops option(4);
+ * socket.set_option(option);
+ * @endcode
+ *
+ * @par
+ * Getting the current option value:
+ * @code
+ * boost::asio::ip::udp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::unicast::hops option;
+ * socket.get_option(option);
+ * int ttl = option.value();
+ * @endcode
+ *
+ * @par Concepts:
+ * GettableSocketOption, SettableSocketOption.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+typedef implementation_defined hops;
+#else
+typedef boost::asio::ip::detail::socket_option::unicast_hops<
+ IPPROTO_IP, IP_TTL, IPPROTO_IPV6, IPV6_UNICAST_HOPS> hops;
+#endif
+
+} // namespace unicast
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_UNICAST_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ip/v6_only.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ip/v6_only.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,70 @@
+//
+// v6_only.hpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_V6_ONLY_HPP
+#define BOOST_ASIO_IP_V6_ONLY_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/socket_option.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// Socket option for determining whether an IPv6 socket supports IPv6
+/// communication only.
+/**
+ * Implements the IPPROTO_IPV6/IP_V6ONLY socket option.
+ *
+ * @par Examples
+ * Setting the option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::v6_only option(true);
+ * socket.set_option(option);
+ * @endcode
+ *
+ * @par
+ * Getting the current option value:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::ip::v6_only option;
+ * socket.get_option(option);
+ * bool v6_only = option.value();
+ * @endcode
+ *
+ * @par Concepts:
+ * GettableSocketOption, SettableSocketOption.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+typedef implementation_defined v6_only;
+#elif defined(IPV6_V6ONLY)
+typedef boost::asio::detail::socket_option::boolean<
+ IPPROTO_IPV6, IPV6_V6ONLY> v6_only;
+#else
+typedef boost::asio::detail::socket_option::boolean<
+ boost::asio::detail::custom_socket_option_level,
+ boost::asio::detail::always_fail_option> v6_only;
+#endif
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_V6_ONLY_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/is_read_buffered.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/is_read_buffered.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,64 @@
+//
+// is_read_buffered.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IS_READ_BUFFERED_HPP
+#define BOOST_ASIO_IS_READ_BUFFERED_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/buffered_read_stream_fwd.hpp>
+#include <boost/asio/buffered_stream_fwd.hpp>
+
+namespace boost {
+namespace asio {
+
+namespace detail {
+
+template <typename Stream>
+char is_read_buffered_helper(buffered_stream<Stream>* s);
+
+template <typename Stream>
+char is_read_buffered_helper(buffered_read_stream<Stream>* s);
+
+struct is_read_buffered_big_type { char data[10]; };
+is_read_buffered_big_type is_read_buffered_helper(...);
+
+} // namespace detail
+
+/// The is_read_buffered class is a traits class that may be used to determine
+/// whether a stream type supports buffering of read data.
+template <typename Stream>
+class is_read_buffered
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The value member is true only if the Stream type supports buffering of
+ /// read data.
+ static const bool value;
+#else
+ BOOST_STATIC_CONSTANT(bool,
+ value = sizeof(detail::is_read_buffered_helper((Stream*)0)) == 1);
+#endif
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IS_READ_BUFFERED_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/is_write_buffered.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/is_write_buffered.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,64 @@
+//
+// is_write_buffered.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IS_WRITE_BUFFERED_HPP
+#define BOOST_ASIO_IS_WRITE_BUFFERED_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/buffered_stream_fwd.hpp>
+#include <boost/asio/buffered_write_stream_fwd.hpp>
+
+namespace boost {
+namespace asio {
+
+namespace detail {
+
+template <typename Stream>
+char is_write_buffered_helper(buffered_stream<Stream>* s);
+
+template <typename Stream>
+char is_write_buffered_helper(buffered_write_stream<Stream>* s);
+
+struct is_write_buffered_big_type { char data[10]; };
+is_write_buffered_big_type is_write_buffered_helper(...);
+
+} // namespace detail
+
+/// The is_write_buffered class is a traits class that may be used to determine
+/// whether a stream type supports buffering of written data.
+template <typename Stream>
+class is_write_buffered
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The value member is true only if the Stream type supports buffering of
+ /// written data.
+ static const bool value;
+#else
+ BOOST_STATIC_CONSTANT(bool,
+ value = sizeof(detail::is_write_buffered_helper((Stream*)0)) == 1);
+#endif
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IS_WRITE_BUFFERED_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/local/basic_endpoint.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/local/basic_endpoint.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,267 @@
+//
+// basic_endpoint.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Derived from a public domain implementation written by Daniel Casimiro.
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_LOCAL_BASIC_ENDPOINT_HPP
+#define BOOST_ASIO_LOCAL_BASIC_ENDPOINT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/throw_exception.hpp>
+#include <cstddef>
+#include <cstring>
+#include <ostream>
+#include <boost/system/system_error.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+#if !defined(BOOST_ASIO_DISABLE_LOCAL_SOCKETS)
+# if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+# define BOOST_ASIO_HAS_LOCAL_SOCKETS 1
+# endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#endif // !defined(BOOST_ASIO_DISABLE_LOCAL_SOCKETS)
+
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \
+ || defined(GENERATING_DOCUMENTATION)
+
+
+namespace boost {
+namespace asio {
+namespace local {
+
+/// Describes an endpoint for a UNIX socket.
+/**
+ * The boost::asio::local::basic_endpoint class template describes an endpoint
+ * that may be associated with a particular UNIX socket.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Concepts:
+ * Endpoint.
+ */
+template <typename Protocol>
+class basic_endpoint
+{
+public:
+ /// The protocol type associated with the endpoint.
+ typedef Protocol protocol_type;
+
+ /// The type of the endpoint structure. This type is dependent on the
+ /// underlying implementation of the socket layer.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined data_type;
+#else
+ typedef boost::asio::detail::socket_addr_type data_type;
+#endif
+
+ /// Default constructor.
+ basic_endpoint()
+ {
+ init("", 0);
+ }
+
+ /// Construct an endpoint using the specified path name.
+ basic_endpoint(const char* path)
+ {
+ using namespace std; // For strlen.
+ init(path, strlen(path));
+ }
+
+ /// Construct an endpoint using the specified path name.
+ basic_endpoint(const std::string& path)
+ {
+ init(path.data(), path.length());
+ }
+
+ /// Copy constructor.
+ basic_endpoint(const basic_endpoint& other)
+ : data_(other.data_),
+ path_length_(other.path_length_)
+ {
+ }
+
+ /// Assign from another endpoint.
+ basic_endpoint& operator=(const basic_endpoint& other)
+ {
+ data_ = other.data_;
+ path_length_ = other.path_length_;
+ return *this;
+ }
+
+ /// The protocol associated with the endpoint.
+ protocol_type protocol() const
+ {
+ return protocol_type();
+ }
+
+ /// Get the underlying endpoint in the native type.
+ data_type* data()
+ {
+ return &data_.base;
+ }
+
+ /// Get the underlying endpoint in the native type.
+ const data_type* data() const
+ {
+ return &data_.base;
+ }
+
+ /// Get the underlying size of the endpoint in the native type.
+ std::size_t size() const
+ {
+ return path_length_
+ + offsetof(boost::asio::detail::sockaddr_un_type, sun_path);
+ }
+
+ /// Set the underlying size of the endpoint in the native type.
+ void resize(std::size_t size)
+ {
+ if (size > sizeof(boost::asio::detail::sockaddr_un_type))
+ {
+ boost::system::system_error e(boost::asio::error::invalid_argument);
+ boost::throw_exception(e);
+ }
+ else if (size == 0)
+ {
+ path_length_ = 0;
+ }
+ else
+ {
+ path_length_ = size
+ - offsetof(boost::asio::detail::sockaddr_un_type, sun_path);
+
+ // The path returned by the operating system may be NUL-terminated.
+ if (path_length_ > 0 && data_.local.sun_path[path_length_] == 0)
+ --path_length_;
+ }
+ }
+
+ /// Get the capacity of the endpoint in the native type.
+ std::size_t capacity() const
+ {
+ return sizeof(boost::asio::detail::sockaddr_un_type);
+ }
+
+ /// Get the path associated with the endpoint.
+ std::string path() const
+ {
+ return std::string(data_.local.sun_path, path_length_);
+ }
+
+ /// Set the path associated with the endpoint.
+ void path(const char* p)
+ {
+ using namespace std; // For strlen.
+ init(p, strlen(p));
+ }
+
+ /// Set the path associated with the endpoint.
+ void path(const std::string& p)
+ {
+ init(p.data(), p.length());
+ }
+
+ /// Compare two endpoints for equality.
+ friend bool operator==(const basic_endpoint<Protocol>& e1,
+ const basic_endpoint<Protocol>& e2)
+ {
+ return e1.path() == e2.path();
+ }
+
+ /// Compare two endpoints for inequality.
+ friend bool operator!=(const basic_endpoint<Protocol>& e1,
+ const basic_endpoint<Protocol>& e2)
+ {
+ return e1.path() != e2.path();
+ }
+
+ /// Compare endpoints for ordering.
+ friend bool operator<(const basic_endpoint<Protocol>& e1,
+ const basic_endpoint<Protocol>& e2)
+ {
+ return e1.path() < e2.path();
+ }
+
+private:
+ // The underlying UNIX socket address.
+ union data_union
+ {
+ boost::asio::detail::socket_addr_type base;
+ boost::asio::detail::sockaddr_un_type local;
+ } data_;
+
+ // The length of the path associated with the endpoint.
+ std::size_t path_length_;
+
+ // Initialise with a specified path.
+ void init(const char* path, std::size_t path_length)
+ {
+ if (path_length > sizeof(data_.local.sun_path) - 1)
+ {
+ // The buffer is not large enough to store this address.
+ boost::system::error_code ec(boost::asio::error::name_too_long);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ using namespace std; // For memcpy.
+ data_.local = boost::asio::detail::sockaddr_un_type();
+ data_.local.sun_family = AF_UNIX;
+ memcpy(data_.local.sun_path, path, path_length);
+ path_length_ = path_length;
+
+ // NUL-terminate normal path names. Names that start with a NUL are in the
+ // UNIX domain protocol's "abstract namespace" and are not NUL-terminated.
+ if (path_length > 0 && data_.local.sun_path[0] == 0)
+ data_.local.sun_path[path_length] = 0;
+ }
+};
+
+/// Output an endpoint as a string.
+/**
+ * Used to output a human-readable string for a specified endpoint.
+ *
+ * @param os The output stream to which the string will be written.
+ *
+ * @param endpoint The endpoint to be written.
+ *
+ * @return The output stream.
+ *
+ * @relates boost::asio::local::basic_endpoint
+ */
+template <typename Elem, typename Traits, typename Protocol>
+std::basic_ostream<Elem, Traits>& operator<<(
+ std::basic_ostream<Elem, Traits>& os,
+ const basic_endpoint<Protocol>& endpoint)
+{
+ os << endpoint.path();
+ return os;
+}
+
+} // namespace local
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_LOCAL_BASIC_ENDPOINT_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/local/connect_pair.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/local/connect_pair.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,102 @@
+//
+// connect_pair.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_LOCAL_CONNECT_PAIR_HPP
+#define BOOST_ASIO_LOCAL_CONNECT_PAIR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/basic_socket.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/local/basic_endpoint.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \
+ || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+namespace local {
+
+/// Create a pair of connected sockets.
+template <typename Protocol, typename SocketService1, typename SocketService2>
+void connect_pair(
+ basic_socket<Protocol, SocketService1>& socket1,
+ basic_socket<Protocol, SocketService2>& socket2);
+
+/// Create a pair of connected sockets.
+template <typename Protocol, typename SocketService1, typename SocketService2>
+boost::system::error_code connect_pair(
+ basic_socket<Protocol, SocketService1>& socket1,
+ basic_socket<Protocol, SocketService2>& socket2,
+ boost::system::error_code& ec);
+
+template <typename Protocol, typename SocketService1, typename SocketService2>
+inline void connect_pair(
+ basic_socket<Protocol, SocketService1>& socket1,
+ basic_socket<Protocol, SocketService2>& socket2)
+{
+ boost::system::error_code ec;
+ connect_pair(socket1, socket2, ec);
+ boost::asio::detail::throw_error(ec);
+}
+
+template <typename Protocol, typename SocketService1, typename SocketService2>
+inline boost::system::error_code connect_pair(
+ basic_socket<Protocol, SocketService1>& socket1,
+ basic_socket<Protocol, SocketService2>& socket2,
+ boost::system::error_code& ec)
+{
+ // Check that this function is only being used with a UNIX domain socket.
+ boost::asio::local::basic_endpoint<Protocol>* tmp
+ = static_cast<typename Protocol::endpoint*>(0);
+ (void)tmp;
+
+ Protocol protocol;
+ boost::asio::detail::socket_type sv[2];
+ if (boost::asio::detail::socket_ops::socketpair(protocol.family(),
+ protocol.type(), protocol.protocol(), sv, ec)
+ == boost::asio::detail::socket_error_retval)
+ return ec;
+
+ if (socket1.assign(protocol, sv[0], ec))
+ {
+ boost::system::error_code temp_ec;
+ boost::asio::detail::socket_ops::close(sv[0], temp_ec);
+ boost::asio::detail::socket_ops::close(sv[1], temp_ec);
+ return ec;
+ }
+
+ if (socket2.assign(protocol, sv[1], ec))
+ {
+ boost::system::error_code temp_ec;
+ socket1.close(temp_ec);
+ boost::asio::detail::socket_ops::close(sv[1], temp_ec);
+ return ec;
+ }
+
+ return ec;
+}
+
+} // namespace local
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_LOCAL_CONNECT_PAIR_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/local/datagram_protocol.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/local/datagram_protocol.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,80 @@
+//
+// datagram_protocol.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_LOCAL_DATAGRAM_PROTOCOL_HPP
+#define BOOST_ASIO_LOCAL_DATAGRAM_PROTOCOL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/basic_datagram_socket.hpp>
+#include <boost/asio/local/basic_endpoint.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \
+ || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+namespace local {
+
+/// Encapsulates the flags needed for datagram-oriented UNIX sockets.
+/**
+ * The boost::asio::local::datagram_protocol class contains flags necessary for
+ * datagram-oriented UNIX domain sockets.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Safe.
+ *
+ * @par Concepts:
+ * Protocol.
+ */
+class datagram_protocol
+{
+public:
+ /// Obtain an identifier for the type of the protocol.
+ int type() const
+ {
+ return SOCK_DGRAM;
+ }
+
+ /// Obtain an identifier for the protocol.
+ int protocol() const
+ {
+ return 0;
+ }
+
+ /// Obtain an identifier for the protocol family.
+ int family() const
+ {
+ return AF_UNIX;
+ }
+
+ /// The type of a UNIX domain endpoint.
+ typedef basic_endpoint<datagram_protocol> endpoint;
+
+ /// The UNIX domain socket type.
+ typedef basic_datagram_socket<datagram_protocol> socket;
+};
+
+} // namespace local
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_LOCAL_DATAGRAM_PROTOCOL_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/local/stream_protocol.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/local/stream_protocol.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,88 @@
+//
+// stream_protocol.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_LOCAL_STREAM_PROTOCOL_HPP
+#define BOOST_ASIO_LOCAL_STREAM_PROTOCOL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/basic_socket_acceptor.hpp>
+#include <boost/asio/basic_socket_iostream.hpp>
+#include <boost/asio/basic_stream_socket.hpp>
+#include <boost/asio/local/basic_endpoint.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS) \
+ || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+namespace local {
+
+/// Encapsulates the flags needed for stream-oriented UNIX sockets.
+/**
+ * The boost::asio::local::stream_protocol class contains flags necessary for
+ * stream-oriented UNIX domain sockets.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Safe.
+ *
+ * @par Concepts:
+ * Protocol.
+ */
+class stream_protocol
+{
+public:
+ /// Obtain an identifier for the type of the protocol.
+ int type() const
+ {
+ return SOCK_STREAM;
+ }
+
+ /// Obtain an identifier for the protocol.
+ int protocol() const
+ {
+ return 0;
+ }
+
+ /// Obtain an identifier for the protocol family.
+ int family() const
+ {
+ return AF_UNIX;
+ }
+
+ /// The type of a UNIX domain endpoint.
+ typedef basic_endpoint<stream_protocol> endpoint;
+
+ /// The UNIX domain socket type.
+ typedef basic_stream_socket<stream_protocol> socket;
+
+ /// The UNIX domain acceptor type.
+ typedef basic_socket_acceptor<stream_protocol> acceptor;
+
+ /// The UNIX domain iostream type.
+ typedef basic_socket_iostream<stream_protocol> iostream;
+};
+
+} // namespace local
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_LOCAL_STREAM_PROTOCOL_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/placeholders.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/placeholders.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,109 @@
+//
+// placeholders.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_PLACEHOLDERS_HPP
+#define BOOST_ASIO_PLACEHOLDERS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/bind/arg.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace placeholders {
+
+#if defined(GENERATING_DOCUMENTATION)
+
+/// An argument placeholder, for use with boost::bind(), that corresponds to
+/// the error argument of a handler for any of the asynchronous functions.
+unspecified error;
+
+/// An argument placeholder, for use with boost::bind(), that corresponds to
+/// the bytes_transferred argument of a handler for asynchronous functions such
+/// as boost::asio::basic_stream_socket::async_write_some or
+/// boost::asio::async_write.
+unspecified bytes_transferred;
+
+/// An argument placeholder, for use with boost::bind(), that corresponds to
+/// the iterator argument of a handler for asynchronous functions such as
+/// boost::asio::basic_resolver::resolve.
+unspecified iterator;
+
+#elif defined(__BORLANDC__) || defined(__GNUC__)
+
+inline boost::arg<1> error()
+{
+ return boost::arg<1>();
+}
+
+inline boost::arg<2> bytes_transferred()
+{
+ return boost::arg<2>();
+}
+
+inline boost::arg<2> iterator()
+{
+ return boost::arg<2>();
+}
+
+#else
+
+namespace detail
+{
+ template <int Number>
+ struct placeholder
+ {
+ static boost::arg<Number>& get()
+ {
+ static boost::arg<Number> result;
+ return result;
+ }
+ };
+}
+
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1400)
+
+static boost::arg<1>& error
+ = boost::asio::placeholders::detail::placeholder<1>::get();
+static boost::arg<2>& bytes_transferred
+ = boost::asio::placeholders::detail::placeholder<2>::get();
+static boost::arg<2>& iterator
+ = boost::asio::placeholders::detail::placeholder<2>::get();
+
+#else
+
+namespace
+{
+ boost::arg<1>& error
+ = boost::asio::placeholders::detail::placeholder<1>::get();
+ boost::arg<2>& bytes_transferred
+ = boost::asio::placeholders::detail::placeholder<2>::get();
+ boost::arg<2>& iterator
+ = boost::asio::placeholders::detail::placeholder<2>::get();
+} // namespace
+
+#endif
+
+#endif
+
+} // namespace placeholders
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_PLACEHOLDERS_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/posix/basic_descriptor.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/posix/basic_descriptor.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,282 @@
+//
+// basic_descriptor.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP
+#define BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/posix/descriptor_base.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+namespace posix {
+
+/// Provides POSIX descriptor functionality.
+/**
+ * The posix::basic_descriptor class template provides the ability to wrap a
+ * POSIX descriptor.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename DescriptorService>
+class basic_descriptor
+ : public basic_io_object<DescriptorService>,
+ public descriptor_base
+{
+public:
+ /// The native representation of a descriptor.
+ typedef typename DescriptorService::native_type native_type;
+
+ /// A basic_descriptor is always the lowest layer.
+ typedef basic_descriptor<DescriptorService> lowest_layer_type;
+
+ /// Construct a basic_descriptor without opening it.
+ /**
+ * This constructor creates a descriptor without opening it.
+ *
+ * @param io_service The io_service object that the descriptor will use to
+ * dispatch handlers for any asynchronous operations performed on the
+ * descriptor.
+ */
+ explicit basic_descriptor(boost::asio::io_service& io_service)
+ : basic_io_object<DescriptorService>(io_service)
+ {
+ }
+
+ /// Construct a basic_descriptor on an existing native descriptor.
+ /**
+ * This constructor creates a descriptor object to hold an existing native
+ * descriptor.
+ *
+ * @param io_service The io_service object that the descriptor will use to
+ * dispatch handlers for any asynchronous operations performed on the
+ * descriptor.
+ *
+ * @param native_descriptor A native descriptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_descriptor(boost::asio::io_service& io_service,
+ const native_type& native_descriptor)
+ : basic_io_object<DescriptorService>(io_service)
+ {
+ boost::system::error_code ec;
+ this->service.assign(this->implementation, native_descriptor, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Get a reference to the lowest layer.
+ /**
+ * This function returns a reference to the lowest layer in a stack of
+ * layers. Since a basic_descriptor cannot contain any further layers, it
+ * simply returns a reference to itself.
+ *
+ * @return A reference to the lowest layer in the stack of layers. Ownership
+ * is not transferred to the caller.
+ */
+ lowest_layer_type& lowest_layer()
+ {
+ return *this;
+ }
+
+ /// Assign an existing native descriptor to the descriptor.
+ /*
+ * This function opens the descriptor to hold an existing native descriptor.
+ *
+ * @param native_descriptor A native descriptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void assign(const native_type& native_descriptor)
+ {
+ boost::system::error_code ec;
+ this->service.assign(this->implementation, native_descriptor, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Assign an existing native descriptor to the descriptor.
+ /*
+ * This function opens the descriptor to hold an existing native descriptor.
+ *
+ * @param native_descriptor A native descriptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code assign(const native_type& native_descriptor,
+ boost::system::error_code& ec)
+ {
+ return this->service.assign(this->implementation, native_descriptor, ec);
+ }
+
+ /// Determine whether the descriptor is open.
+ bool is_open() const
+ {
+ return this->service.is_open(this->implementation);
+ }
+
+ /// Close the descriptor.
+ /**
+ * This function is used to close the descriptor. Any asynchronous read or
+ * write operations will be cancelled immediately, and will complete with the
+ * boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void close()
+ {
+ boost::system::error_code ec;
+ this->service.close(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Close the descriptor.
+ /**
+ * This function is used to close the descriptor. Any asynchronous read or
+ * write operations will be cancelled immediately, and will complete with the
+ * boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code close(boost::system::error_code& ec)
+ {
+ return this->service.close(this->implementation, ec);
+ }
+
+ /// Get the native descriptor representation.
+ /**
+ * This function may be used to obtain the underlying representation of the
+ * descriptor. This is intended to allow access to native descriptor
+ * functionality that is not otherwise provided.
+ */
+ native_type native()
+ {
+ return this->service.native(this->implementation);
+ }
+
+ /// Cancel all asynchronous operations associated with the descriptor.
+ /**
+ * This function causes all outstanding asynchronous read or write operations
+ * to finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void cancel()
+ {
+ boost::system::error_code ec;
+ this->service.cancel(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Cancel all asynchronous operations associated with the descriptor.
+ /**
+ * This function causes all outstanding asynchronous read or write operations
+ * to finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code cancel(boost::system::error_code& ec)
+ {
+ return this->service.cancel(this->implementation, ec);
+ }
+
+ /// Perform an IO control command on the descriptor.
+ /**
+ * This function is used to execute an IO control command on the descriptor.
+ *
+ * @param command The IO control command to be performed on the descriptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::posix::descriptor_base::bytes_readable @n
+ * boost::asio::posix::descriptor_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::posix::stream_descriptor descriptor(io_service);
+ * ...
+ * boost::asio::posix::stream_descriptor::bytes_readable command;
+ * descriptor.io_control(command);
+ * std::size_t bytes_readable = command.get();
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ void io_control(IoControlCommand& command)
+ {
+ boost::system::error_code ec;
+ this->service.io_control(this->implementation, command, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Perform an IO control command on the descriptor.
+ /**
+ * This function is used to execute an IO control command on the descriptor.
+ *
+ * @param command The IO control command to be performed on the descriptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::posix::descriptor_base::bytes_readable @n
+ * boost::asio::posix::descriptor_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::posix::stream_descriptor descriptor(io_service);
+ * ...
+ * boost::asio::posix::stream_descriptor::bytes_readable command;
+ * boost::system::error_code ec;
+ * descriptor.io_control(command, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * std::size_t bytes_readable = command.get();
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ boost::system::error_code io_control(IoControlCommand& command,
+ boost::system::error_code& ec)
+ {
+ return this->service.io_control(this->implementation, command, ec);
+ }
+
+protected:
+ /// Protected destructor to prevent deletion through this type.
+ ~basic_descriptor()
+ {
+ }
+};
+
+} // namespace posix
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/posix/basic_stream_descriptor.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/posix/basic_stream_descriptor.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,306 @@
+//
+// basic_stream_descriptor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP
+#define BOOST_ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/posix/basic_descriptor.hpp>
+#include <boost/asio/posix/stream_descriptor_service.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
+ || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+namespace posix {
+
+/// Provides stream-oriented descriptor functionality.
+/**
+ * The posix::basic_stream_descriptor class template provides asynchronous and
+ * blocking stream-oriented descriptor functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Concepts:
+ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
+ */
+template <typename StreamDescriptorService = stream_descriptor_service>
+class basic_stream_descriptor
+ : public basic_descriptor<StreamDescriptorService>
+{
+public:
+ /// The native representation of a descriptor.
+ typedef typename StreamDescriptorService::native_type native_type;
+
+ /// Construct a basic_stream_descriptor without opening it.
+ /**
+ * This constructor creates a stream descriptor without opening it. The
+ * descriptor needs to be opened and then connected or accepted before data
+ * can be sent or received on it.
+ *
+ * @param io_service The io_service object that the stream descriptor will
+ * use to dispatch handlers for any asynchronous operations performed on the
+ * descriptor.
+ */
+ explicit basic_stream_descriptor(boost::asio::io_service& io_service)
+ : basic_descriptor<StreamDescriptorService>(io_service)
+ {
+ }
+
+ /// Construct a basic_stream_descriptor on an existing native descriptor.
+ /**
+ * This constructor creates a stream descriptor object to hold an existing
+ * native descriptor.
+ *
+ * @param io_service The io_service object that the stream descriptor will
+ * use to dispatch handlers for any asynchronous operations performed on the
+ * descriptor.
+ *
+ * @param native_descriptor The new underlying descriptor implementation.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_stream_descriptor(boost::asio::io_service& io_service,
+ const native_type& native_descriptor)
+ : basic_descriptor<StreamDescriptorService>(io_service, native_descriptor)
+ {
+ }
+
+ /// Write some data to the descriptor.
+ /**
+ * This function is used to write data to the stream descriptor. The function
+ * call will block until one or more bytes of the data has been written
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more data buffers to be written to the descriptor.
+ *
+ * @returns The number of bytes written.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The write_some operation may not transmit all of the data to the
+ * peer. Consider using the @ref write function if you need to ensure that
+ * all data is written before the blocking operation completes.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * descriptor.write_some(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.write_some(this->implementation, buffers, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Write some data to the descriptor.
+ /**
+ * This function is used to write data to the stream descriptor. The function
+ * call will block until one or more bytes of the data has been written
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more data buffers to be written to the descriptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes written. Returns 0 if an error occurred.
+ *
+ * @note The write_some operation may not transmit all of the data to the
+ * peer. Consider using the @ref write function if you need to ensure that
+ * all data is written before the blocking operation completes.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return this->service.write_some(this->implementation, buffers, ec);
+ }
+
+ /// Start an asynchronous write.
+ /**
+ * This function is used to asynchronously write data to the stream
+ * descriptor. The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be written to the descriptor.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes written.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The write operation may not transmit all of the data to the peer.
+ * Consider using the @ref async_write function if you need to ensure that all
+ * data is written before the asynchronous operation completes.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * descriptor.async_write_some(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_write_some(const ConstBufferSequence& buffers,
+ WriteHandler handler)
+ {
+ this->service.async_write_some(this->implementation, buffers, handler);
+ }
+
+ /// Read some data from the descriptor.
+ /**
+ * This function is used to read data from the stream descriptor. The function
+ * call will block until one or more bytes of data has been read successfully,
+ * or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ *
+ * @returns The number of bytes read.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The read_some operation may not read all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that
+ * the requested amount of data is read before the blocking operation
+ * completes.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code
+ * descriptor.read_some(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.read_some(this->implementation, buffers, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Read some data from the descriptor.
+ /**
+ * This function is used to read data from the stream descriptor. The function
+ * call will block until one or more bytes of data has been read successfully,
+ * or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes read. Returns 0 if an error occurred.
+ *
+ * @note The read_some operation may not read all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that
+ * the requested amount of data is read before the blocking operation
+ * completes.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return this->service.read_some(this->implementation, buffers, ec);
+ }
+
+ /// Start an asynchronous read.
+ /**
+ * This function is used to asynchronously read data from the stream
+ * descriptor. The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes read.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The read operation may not read all of the requested number of bytes.
+ * Consider using the @ref async_read function if you need to ensure that the
+ * requested amount of data is read before the asynchronous operation
+ * completes.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code
+ * descriptor.async_read_some(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_read_some(const MutableBufferSequence& buffers,
+ ReadHandler handler)
+ {
+ this->service.async_read_some(this->implementation, buffers, handler);
+ }
+};
+
+} // namespace posix
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/posix/descriptor_base.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/posix/descriptor_base.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,95 @@
+//
+// descriptor_base.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_POSIX_DESCRIPTOR_BASE_HPP
+#define BOOST_ASIO_POSIX_DESCRIPTOR_BASE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/io_control.hpp>
+#include <boost/asio/detail/socket_option.hpp>
+
+namespace boost {
+namespace asio {
+namespace posix {
+
+/// The descriptor_base class is used as a base for the basic_stream_descriptor
+/// class template so that we have a common place to define the associated
+/// IO control commands.
+class descriptor_base
+{
+public:
+ /// IO control command to set the blocking mode of the descriptor.
+ /**
+ * Implements the FIONBIO IO control command.
+ *
+ * @par Example
+ * @code
+ * boost::asio::posix::stream_descriptor descriptor(io_service);
+ * ...
+ * boost::asio::descriptor_base::non_blocking_io command(true);
+ * descriptor.io_control(command);
+ * @endcode
+ *
+ * @par Concepts:
+ * IoControlCommand.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined non_blocking_io;
+#else
+ typedef boost::asio::detail::io_control::non_blocking_io non_blocking_io;
+#endif
+
+ /// IO control command to get the amount of data that can be read without
+ /// blocking.
+ /**
+ * Implements the FIONREAD IO control command.
+ *
+ * @par Example
+ * @code
+ * boost::asio::posix::stream_descriptor descriptor(io_service);
+ * ...
+ * boost::asio::descriptor_base::bytes_readable command(true);
+ * descriptor.io_control(command);
+ * std::size_t bytes_readable = command.get();
+ * @endcode
+ *
+ * @par Concepts:
+ * IoControlCommand.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined bytes_readable;
+#else
+ typedef boost::asio::detail::io_control::bytes_readable bytes_readable;
+#endif
+
+protected:
+ /// Protected destructor to prevent deletion through this type.
+ ~descriptor_base()
+ {
+ }
+};
+
+} // namespace posix
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_POSIX_DESCRIPTOR_BASE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/posix/stream_descriptor.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/posix/stream_descriptor.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,41 @@
+//
+// stream_descriptor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_HPP
+#define BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/posix/basic_stream_descriptor.hpp>
+
+#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
+ || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+namespace posix {
+
+/// Typedef for the typical usage of a stream-oriented descriptor.
+typedef basic_stream_descriptor<> stream_descriptor;
+
+} // namespace posix
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/posix/stream_descriptor_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/posix/stream_descriptor_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,202 @@
+//
+// stream_descriptor_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP
+#define BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/epoll_reactor.hpp>
+#include <boost/asio/detail/kqueue_reactor.hpp>
+#include <boost/asio/detail/select_reactor.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/reactive_descriptor_service.hpp>
+
+#if !defined(BOOST_ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR)
+# if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+# define BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR 1
+# endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+#endif // !defined(BOOST_ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR)
+
+#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
+ || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+namespace posix {
+
+/// Default service implementation for a stream descriptor.
+class stream_descriptor_service
+#if defined(GENERATING_DOCUMENTATION)
+ : public boost::asio::io_service::service
+#else
+ : public boost::asio::detail::service_base<stream_descriptor_service>
+#endif
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The unique service identifier.
+ static boost::asio::io_service::id id;
+#endif
+
+private:
+ // The type of the platform-specific implementation.
+#if defined(BOOST_ASIO_HAS_EPOLL)
+ typedef detail::reactive_descriptor_service<
+ detail::epoll_reactor<false> > service_impl_type;
+#elif defined(BOOST_ASIO_HAS_KQUEUE)
+ typedef detail::reactive_descriptor_service<
+ detail::kqueue_reactor<false> > service_impl_type;
+#elif defined(BOOST_ASIO_HAS_DEV_POLL)
+ typedef detail::reactive_descriptor_service<
+ detail::dev_poll_reactor<false> > service_impl_type;
+#else
+ typedef detail::reactive_descriptor_service<
+ detail::select_reactor<false> > service_impl_type;
+#endif
+
+public:
+ /// The type of a stream descriptor implementation.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined implementation_type;
+#else
+ typedef service_impl_type::implementation_type implementation_type;
+#endif
+
+ /// The native descriptor type.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_type;
+#else
+ typedef service_impl_type::native_type native_type;
+#endif
+
+ /// Construct a new stream descriptor service for the specified io_service.
+ explicit stream_descriptor_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<stream_descriptor_service>(io_service),
+ service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ {
+ }
+
+ /// Destroy all user-defined descriptorr objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ /// Construct a new stream descriptor implementation.
+ void construct(implementation_type& impl)
+ {
+ service_impl_.construct(impl);
+ }
+
+ /// Destroy a stream descriptor implementation.
+ void destroy(implementation_type& impl)
+ {
+ service_impl_.destroy(impl);
+ }
+
+ /// Assign an existing native descriptor to a stream descriptor.
+ boost::system::error_code assign(implementation_type& impl,
+ const native_type& native_descriptor, boost::system::error_code& ec)
+ {
+ return service_impl_.assign(impl, native_descriptor, ec);
+ }
+
+ /// Determine whether the descriptor is open.
+ bool is_open(const implementation_type& impl) const
+ {
+ return service_impl_.is_open(impl);
+ }
+
+ /// Close a stream descriptor implementation.
+ boost::system::error_code close(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.close(impl, ec);
+ }
+
+ /// Get the native descriptor implementation.
+ native_type native(implementation_type& impl)
+ {
+ return service_impl_.native(impl);
+ }
+
+ /// Cancel all asynchronous operations associated with the descriptor.
+ boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.cancel(impl, ec);
+ }
+
+ /// Perform an IO control command on the descriptor.
+ template <typename IoControlCommand>
+ boost::system::error_code io_control(implementation_type& impl,
+ IoControlCommand& command, boost::system::error_code& ec)
+ {
+ return service_impl_.io_control(impl, command, ec);
+ }
+
+ /// Write the given data to the stream.
+ template <typename ConstBufferSequence>
+ std::size_t write_some(implementation_type& impl,
+ const ConstBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return service_impl_.write_some(impl, buffers, ec);
+ }
+
+ /// Start an asynchronous write.
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_write_some(implementation_type& impl,
+ const ConstBufferSequence& buffers, WriteHandler descriptorr)
+ {
+ service_impl_.async_write_some(impl, buffers, descriptorr);
+ }
+
+ /// Read some data from the stream.
+ template <typename MutableBufferSequence>
+ std::size_t read_some(implementation_type& impl,
+ const MutableBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return service_impl_.read_some(impl, buffers, ec);
+ }
+
+ /// Start an asynchronous read.
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_read_some(implementation_type& impl,
+ const MutableBufferSequence& buffers, ReadHandler descriptorr)
+ {
+ service_impl_.async_read_some(impl, buffers, descriptorr);
+ }
+
+private:
+ // The service that provides the platform-specific implementation.
+ service_impl_type& service_impl_;
+};
+
+} // namespace posix
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/raw_socket_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/raw_socket_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,325 @@
+//
+// raw_socket_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_RAW_SOCKET_SERVICE_HPP
+#define BOOST_ASIO_RAW_SOCKET_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/epoll_reactor.hpp>
+#include <boost/asio/detail/kqueue_reactor.hpp>
+#include <boost/asio/detail/select_reactor.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/reactive_socket_service.hpp>
+#include <boost/asio/detail/win_iocp_socket_service.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Default service implementation for a raw socket.
+template <typename Protocol>
+class raw_socket_service
+#if defined(GENERATING_DOCUMENTATION)
+ : public boost::asio::io_service::service
+#else
+ : public boost::asio::detail::service_base<raw_socket_service<Protocol> >
+#endif
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The unique service identifier.
+ static boost::asio::io_service::id id;
+#endif
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+private:
+ // The type of the platform-specific implementation.
+#if defined(BOOST_ASIO_HAS_IOCP)
+ typedef detail::win_iocp_socket_service<Protocol> service_impl_type;
+#elif defined(BOOST_ASIO_HAS_EPOLL)
+ typedef detail::reactive_socket_service<
+ Protocol, detail::epoll_reactor<false> > service_impl_type;
+#elif defined(BOOST_ASIO_HAS_KQUEUE)
+ typedef detail::reactive_socket_service<
+ Protocol, detail::kqueue_reactor<false> > service_impl_type;
+#elif defined(BOOST_ASIO_HAS_DEV_POLL)
+ typedef detail::reactive_socket_service<
+ Protocol, detail::dev_poll_reactor<false> > service_impl_type;
+#else
+ typedef detail::reactive_socket_service<
+ Protocol, detail::select_reactor<false> > service_impl_type;
+#endif
+
+public:
+ /// The type of a raw socket.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined implementation_type;
+#else
+ typedef typename service_impl_type::implementation_type implementation_type;
+#endif
+
+ /// The native socket type.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_type;
+#else
+ typedef typename service_impl_type::native_type native_type;
+#endif
+
+ /// Construct a new raw socket service for the specified io_service.
+ explicit raw_socket_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ raw_socket_service<Protocol> >(io_service),
+ service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ {
+ }
+
+ /// Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ /// Construct a new raw socket implementation.
+ void construct(implementation_type& impl)
+ {
+ service_impl_.construct(impl);
+ }
+
+ /// Destroy a raw socket implementation.
+ void destroy(implementation_type& impl)
+ {
+ service_impl_.destroy(impl);
+ }
+
+ // Open a new raw socket implementation.
+ boost::system::error_code open(implementation_type& impl,
+ const protocol_type& protocol, boost::system::error_code& ec)
+ {
+ if (protocol.type() == SOCK_RAW)
+ service_impl_.open(impl, protocol, ec);
+ else
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+
+ /// Assign an existing native socket to a raw socket.
+ boost::system::error_code assign(implementation_type& impl,
+ const protocol_type& protocol, const native_type& native_socket,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.assign(impl, protocol, native_socket, ec);
+ }
+
+ /// Determine whether the socket is open.
+ bool is_open(const implementation_type& impl) const
+ {
+ return service_impl_.is_open(impl);
+ }
+
+ /// Close a raw socket implementation.
+ boost::system::error_code close(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.close(impl, ec);
+ }
+
+ /// Get the native socket implementation.
+ native_type native(implementation_type& impl)
+ {
+ return service_impl_.native(impl);
+ }
+
+ /// Cancel all asynchronous operations associated with the socket.
+ boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.cancel(impl, ec);
+ }
+
+ /// Determine whether the socket is at the out-of-band data mark.
+ bool at_mark(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.at_mark(impl, ec);
+ }
+
+ /// Determine the number of bytes available for reading.
+ std::size_t available(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.available(impl, ec);
+ }
+
+ // Bind the raw socket to the specified local endpoint.
+ boost::system::error_code bind(implementation_type& impl,
+ const endpoint_type& endpoint, boost::system::error_code& ec)
+ {
+ return service_impl_.bind(impl, endpoint, ec);
+ }
+
+ /// Connect the raw socket to the specified endpoint.
+ boost::system::error_code connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ return service_impl_.connect(impl, peer_endpoint, ec);
+ }
+
+ /// Start an asynchronous connect.
+ template <typename ConnectHandler>
+ void async_connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, ConnectHandler handler)
+ {
+ service_impl_.async_connect(impl, peer_endpoint, handler);
+ }
+
+ /// Set a socket option.
+ template <typename SettableSocketOption>
+ boost::system::error_code set_option(implementation_type& impl,
+ const SettableSocketOption& option, boost::system::error_code& ec)
+ {
+ return service_impl_.set_option(impl, option, ec);
+ }
+
+ /// Get a socket option.
+ template <typename GettableSocketOption>
+ boost::system::error_code get_option(const implementation_type& impl,
+ GettableSocketOption& option, boost::system::error_code& ec) const
+ {
+ return service_impl_.get_option(impl, option, ec);
+ }
+
+ /// Perform an IO control command on the socket.
+ template <typename IoControlCommand>
+ boost::system::error_code io_control(implementation_type& impl,
+ IoControlCommand& command, boost::system::error_code& ec)
+ {
+ return service_impl_.io_control(impl, command, ec);
+ }
+
+ /// Get the local endpoint.
+ endpoint_type local_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.local_endpoint(impl, ec);
+ }
+
+ /// Get the remote endpoint.
+ endpoint_type remote_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.remote_endpoint(impl, ec);
+ }
+
+ /// Disable sends or receives on the socket.
+ boost::system::error_code shutdown(implementation_type& impl,
+ socket_base::shutdown_type what, boost::system::error_code& ec)
+ {
+ return service_impl_.shutdown(impl, what, ec);
+ }
+
+ /// Send the given data to the peer.
+ template <typename ConstBufferSequence>
+ std::size_t send(implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return service_impl_.send(impl, buffers, flags, ec);
+ }
+
+ /// Start an asynchronous send.
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_send(implementation_type& impl, const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, WriteHandler handler)
+ {
+ service_impl_.async_send(impl, buffers, flags, handler);
+ }
+
+ /// Send raw data to the specified endpoint.
+ template <typename ConstBufferSequence>
+ std::size_t send_to(implementation_type& impl,
+ const ConstBufferSequence& buffers, const endpoint_type& destination,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return service_impl_.send_to(impl, buffers, destination, flags, ec);
+ }
+
+ /// Start an asynchronous send.
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_send_to(implementation_type& impl,
+ const ConstBufferSequence& buffers, const endpoint_type& destination,
+ socket_base::message_flags flags, WriteHandler handler)
+ {
+ service_impl_.async_send_to(impl, buffers, destination, flags, handler);
+ }
+
+ /// Receive some data from the peer.
+ template <typename MutableBufferSequence>
+ std::size_t receive(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return service_impl_.receive(impl, buffers, flags, ec);
+ }
+
+ /// Start an asynchronous receive.
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_receive(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, ReadHandler handler)
+ {
+ service_impl_.async_receive(impl, buffers, flags, handler);
+ }
+
+ /// Receive raw data with the endpoint of the sender.
+ template <typename MutableBufferSequence>
+ std::size_t receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return service_impl_.receive_from(impl, buffers, sender_endpoint, flags,
+ ec);
+ }
+
+ /// Start an asynchronous receive that will get the endpoint of the sender.
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_receive_from(implementation_type& impl,
+ const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,
+ socket_base::message_flags flags, ReadHandler handler)
+ {
+ service_impl_.async_receive_from(impl, buffers, sender_endpoint, flags,
+ handler);
+ }
+
+private:
+ // The service that provides the platform-specific implementation.
+ service_impl_type& service_impl_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_RAW_SOCKET_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/read.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/read.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,518 @@
+//
+// read.hpp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_READ_HPP
+#define BOOST_ASIO_READ_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/basic_streambuf.hpp>
+#include <boost/asio/error.hpp>
+
+namespace boost {
+namespace asio {
+
+/**
+ * @defgroup read boost::asio::read
+ */
+/*@{*/
+
+/// Attempt to read a certain amount of data from a stream before returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * stream. The call will block until one of the following conditions is true:
+ *
+ * @li The supplied buffers are full. That is, the bytes transferred is equal to
+ * the sum of the buffer sizes.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * read_some function.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers One or more buffers into which the data will be read. The sum
+ * of the buffer sizes indicates the maximum number of bytes to read from the
+ * stream.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code boost::asio::read(s, boost::asio::buffer(data, size)); @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ *
+ * @note This overload is equivalent to calling:
+ * @code boost::asio::read(
+ * s, buffers,
+ * boost::asio::transfer_all()); @endcode
+ */
+template <typename SyncReadStream, typename MutableBufferSequence>
+std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers);
+
+/// Attempt to read a certain amount of data from a stream before returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * stream. The call will block until one of the following conditions is true:
+ *
+ * @li The supplied buffers are full. That is, the bytes transferred is equal to
+ * the sum of the buffer sizes.
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * read_some function.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers One or more buffers into which the data will be read. The sum
+ * of the buffer sizes indicates the maximum number of bytes to read from the
+ * stream.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the read operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * const boost::system::error_code& error, // Result of latest read_some
+ * // operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes transferred
+ * // so far.
+ * ); @endcode
+ * A return value of true indicates that the read operation is complete. False
+ * indicates that further calls to the stream's read_some function are required.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code boost::asio::read(s, boost::asio::buffer(data, size),
+ * boost::asio::transfer_at_least(32)); @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+template <typename SyncReadStream, typename MutableBufferSequence,
+ typename CompletionCondition>
+std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition);
+
+/// Attempt to read a certain amount of data from a stream before returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * stream. The call will block until one of the following conditions is true:
+ *
+ * @li The supplied buffers are full. That is, the bytes transferred is equal to
+ * the sum of the buffer sizes.
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * read_some function.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers One or more buffers into which the data will be read. The sum
+ * of the buffer sizes indicates the maximum number of bytes to read from the
+ * stream.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the read operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * const boost::system::error_code& error, // Result of latest read_some
+ * // operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes transferred
+ * // so far.
+ * ); @endcode
+ * A return value of true indicates that the read operation is complete. False
+ * indicates that further calls to the stream's read_some function are required.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes read. If an error occurs, returns the total
+ * number of bytes successfully transferred prior to the error.
+ */
+template <typename SyncReadStream, typename MutableBufferSequence,
+ typename CompletionCondition>
+std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition, boost::system::error_code& ec);
+
+/// Attempt to read a certain amount of data from a stream before returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * stream. The call will block until one of the following conditions is true:
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * read_some function.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param b The basic_streambuf object into which the data will be read.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This overload is equivalent to calling:
+ * @code boost::asio::read(
+ * s, b,
+ * boost::asio::transfer_all()); @endcode
+ */
+template <typename SyncReadStream, typename Allocator>
+std::size_t read(SyncReadStream& s, basic_streambuf<Allocator>& b);
+
+/// Attempt to read a certain amount of data from a stream before returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * stream. The call will block until one of the following conditions is true:
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * read_some function.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param b The basic_streambuf object into which the data will be read.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the read operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * const boost::system::error_code& error, // Result of latest read_some
+ * // operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes transferred
+ * // so far.
+ * ); @endcode
+ * A return value of true indicates that the read operation is complete. False
+ * indicates that further calls to the stream's read_some function are required.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+template <typename SyncReadStream, typename Allocator,
+ typename CompletionCondition>
+std::size_t read(SyncReadStream& s, basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition);
+
+/// Attempt to read a certain amount of data from a stream before returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * stream. The call will block until one of the following conditions is true:
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * read_some function.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param b The basic_streambuf object into which the data will be read.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the read operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * const boost::system::error_code& error, // Result of latest read_some
+ * // operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes transferred
+ * // so far.
+ * ); @endcode
+ * A return value of true indicates that the read operation is complete. False
+ * indicates that further calls to the stream's read_some function are required.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes read. If an error occurs, returns the total
+ * number of bytes successfully transferred prior to the error.
+ */
+template <typename SyncReadStream, typename Allocator,
+ typename CompletionCondition>
+std::size_t read(SyncReadStream& s, basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, boost::system::error_code& ec);
+
+/*@}*/
+/**
+ * @defgroup async_read boost::asio::async_read
+ */
+/*@{*/
+
+/// Start an asynchronous operation to read a certain amount of data from a
+/// stream.
+/**
+ * This function is used to asynchronously read a certain number of bytes of
+ * data from a stream. The function call always returns immediately. The
+ * asynchronous operation will continue until one of the following conditions is
+ * true:
+ *
+ * @li The supplied buffers are full. That is, the bytes transferred is equal to
+ * the sum of the buffer sizes.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * async_read_some function.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @param buffers One or more buffers into which the data will be read. The sum
+ * of the buffer sizes indicates the maximum number of bytes to read from the
+ * stream. Although the buffers object may be copied as necessary, ownership of
+ * the underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes copied into the
+ * // buffers. If an error occurred,
+ * // this will be the number of
+ * // bytes successfully transferred
+ * // prior to the error.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code
+ * boost::asio::async_read(s, boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ *
+ * @note This overload is equivalent to calling:
+ * @code boost::asio::async_read(
+ * s, buffers,
+ * boost::asio::transfer_all(),
+ * handler); @endcode
+ */
+template <typename AsyncReadStream, typename MutableBufferSequence,
+ typename ReadHandler>
+void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
+ ReadHandler handler);
+
+/// Start an asynchronous operation to read a certain amount of data from a
+/// stream.
+/**
+ * This function is used to asynchronously read a certain number of bytes of
+ * data from a stream. The function call always returns immediately. The
+ * asynchronous operation will continue until one of the following conditions is
+ * true:
+ *
+ * @li The supplied buffers are full. That is, the bytes transferred is equal to
+ * the sum of the buffer sizes.
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @param buffers One or more buffers into which the data will be read. The sum
+ * of the buffer sizes indicates the maximum number of bytes to read from the
+ * stream. Although the buffers object may be copied as necessary, ownership of
+ * the underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the read operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * const boost::system::error_code& error, // Result of latest read_some
+ * // operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes transferred
+ * // so far.
+ * ); @endcode
+ * A return value of true indicates that the read operation is complete. False
+ * indicates that further calls to the stream's async_read_some function are
+ * required.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes copied into the
+ * // buffers. If an error occurred,
+ * // this will be the number of
+ * // bytes successfully transferred
+ * // prior to the error.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code boost::asio::async_read(s,
+ * boost::asio::buffer(data, size),
+ * boost::asio::transfer_at_least(32),
+ * handler); @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+template <typename AsyncReadStream, typename MutableBufferSequence,
+ typename CompletionCondition, typename ReadHandler>
+void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition, ReadHandler handler);
+
+/// Start an asynchronous operation to read a certain amount of data from a
+/// stream.
+/**
+ * This function is used to asynchronously read a certain number of bytes of
+ * data from a stream. The function call always returns immediately. The
+ * asynchronous operation will continue until one of the following conditions is
+ * true:
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * async_read_some function.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @param b A basic_streambuf object into which the data will be read. Ownership
+ * of the streambuf is retained by the caller, which must guarantee that it
+ * remains valid until the handler is called.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes copied into the
+ * // buffers. If an error occurred,
+ * // this will be the number of
+ * // bytes successfully transferred
+ * // prior to the error.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note This overload is equivalent to calling:
+ * @code boost::asio::async_read(
+ * s, b,
+ * boost::asio::transfer_all(),
+ * handler); @endcode
+ */
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+void async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
+ ReadHandler handler);
+
+/// Start an asynchronous operation to read a certain amount of data from a
+/// stream.
+/**
+ * This function is used to asynchronously read a certain number of bytes of
+ * data from a stream. The function call always returns immediately. The
+ * asynchronous operation will continue until one of the following conditions is
+ * true:
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * async_read_some function.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @param b A basic_streambuf object into which the data will be read. Ownership
+ * of the streambuf is retained by the caller, which must guarantee that it
+ * remains valid until the handler is called.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the read operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * const boost::system::error_code& error, // Result of latest read_some
+ * // operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes transferred
+ * // so far.
+ * ); @endcode
+ * A return value of true indicates that the read operation is complete. False
+ * indicates that further calls to the stream's async_read_some function are
+ * required.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes copied into the
+ * // buffers. If an error occurred,
+ * // this will be the number of
+ * // bytes successfully transferred
+ * // prior to the error.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ */
+template <typename AsyncReadStream, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+void async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, ReadHandler handler);
+
+/*@}*/
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/impl/read.ipp>
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_READ_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/read_at.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/read_at.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,564 @@
+//
+// read_at.hpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_READ_AT_HPP
+#define BOOST_ASIO_READ_AT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/basic_streambuf.hpp>
+#include <boost/asio/error.hpp>
+
+namespace boost {
+namespace asio {
+
+/**
+ * @defgroup read_at boost::asio::read_at
+ */
+/*@{*/
+
+/// Attempt to read a certain amount of data at the specified offset before
+/// returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * random access device at the specified offset. The call will block until one
+ * of the following conditions is true:
+ *
+ * @li The supplied buffers are full. That is, the bytes transferred is equal to
+ * the sum of the buffer sizes.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * read_some_at function.
+ *
+ * @param d The device from which the data is to be read. The type must support
+ * the SyncRandomAccessReadDevice concept.
+ *
+ * @param offset The offset at which the data will be read.
+ *
+ * @param buffers One or more buffers into which the data will be read. The sum
+ * of the buffer sizes indicates the maximum number of bytes to read from the
+ * device.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code boost::asio::read_at(d, 42, boost::asio::buffer(data, size)); @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ *
+ * @note This overload is equivalent to calling:
+ * @code boost::asio::read_at(
+ * d, 42, buffers,
+ * boost::asio::transfer_all()); @endcode
+ */
+template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
+std::size_t read_at(SyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, const MutableBufferSequence& buffers);
+
+/// Attempt to read a certain amount of data at the specified offset before
+/// returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * random access device at the specified offset. The call will block until one
+ * of the following conditions is true:
+ *
+ * @li The supplied buffers are full. That is, the bytes transferred is equal to
+ * the sum of the buffer sizes.
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * read_some_at function.
+ *
+ * @param d The device from which the data is to be read. The type must support
+ * the SyncRandomAccessReadDevice concept.
+ *
+ * @param offset The offset at which the data will be read.
+ *
+ * @param buffers One or more buffers into which the data will be read. The sum
+ * of the buffer sizes indicates the maximum number of bytes to read from the
+ * device.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the read operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * // Result of latest read_some_at operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes transferred so far.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of true indicates that the read operation is complete. False
+ * indicates that further calls to the device's read_some_at function are
+ * required.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code boost::asio::read_at(d, 42, boost::asio::buffer(data, size),
+ * boost::asio::transfer_at_least(32)); @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
+ typename CompletionCondition>
+std::size_t read_at(SyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition);
+
+/// Attempt to read a certain amount of data at the specified offset before
+/// returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * random access device at the specified offset. The call will block until one
+ * of the following conditions is true:
+ *
+ * @li The supplied buffers are full. That is, the bytes transferred is equal to
+ * the sum of the buffer sizes.
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * read_some_at function.
+ *
+ * @param d The device from which the data is to be read. The type must support
+ * the SyncRandomAccessReadDevice concept.
+ *
+ * @param offset The offset at which the data will be read.
+ *
+ * @param buffers One or more buffers into which the data will be read. The sum
+ * of the buffer sizes indicates the maximum number of bytes to read from the
+ * device.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the read operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * const boost::system::error_code& error, // Result of latest read_some_at
+ * // operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes transferred
+ * // so far.
+ * ); @endcode
+ * A return value of true indicates that the read operation is complete. False
+ * indicates that further calls to the device's read_some_at function are
+ * required.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes read. If an error occurs, returns the total
+ * number of bytes successfully transferred prior to the error.
+ */
+template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
+ typename CompletionCondition>
+std::size_t read_at(SyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition, boost::system::error_code& ec);
+
+/// Attempt to read a certain amount of data at the specified offset before
+/// returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * random access device at the specified offset. The call will block until one
+ * of the following conditions is true:
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * read_some_at function.
+ *
+ * @param d The device from which the data is to be read. The type must support
+ * the SyncRandomAccessReadDevice concept.
+ *
+ * @param offset The offset at which the data will be read.
+ *
+ * @param b The basic_streambuf object into which the data will be read.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This overload is equivalent to calling:
+ * @code boost::asio::read_at(
+ * d, 42, b,
+ * boost::asio::transfer_all()); @endcode
+ */
+template <typename SyncRandomAccessReadDevice, typename Allocator>
+std::size_t read_at(SyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, basic_streambuf<Allocator>& b);
+
+/// Attempt to read a certain amount of data at the specified offset before
+/// returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * random access device at the specified offset. The call will block until one
+ * of the following conditions is true:
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * read_some_at function.
+ *
+ * @param d The device from which the data is to be read. The type must support
+ * the SyncRandomAccessReadDevice concept.
+ *
+ * @param offset The offset at which the data will be read.
+ *
+ * @param b The basic_streambuf object into which the data will be read.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the read operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * // Result of latest read_some_at operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes transferred so far.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of true indicates that the read operation is complete. False
+ * indicates that further calls to the device's read_some_at function are
+ * required.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+template <typename SyncRandomAccessReadDevice, typename Allocator,
+ typename CompletionCondition>
+std::size_t read_at(SyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition);
+
+/// Attempt to read a certain amount of data at the specified offset before
+/// returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * random access device at the specified offset. The call will block until one
+ * of the following conditions is true:
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * read_some_at function.
+ *
+ * @param d The device from which the data is to be read. The type must support
+ * the SyncRandomAccessReadDevice concept.
+ *
+ * @param offset The offset at which the data will be read.
+ *
+ * @param b The basic_streambuf object into which the data will be read.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the read operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * // Result of latest read_some_at operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes transferred so far.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of true indicates that the read operation is complete. False
+ * indicates that further calls to the device's read_some_at function are
+ * required.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes read. If an error occurs, returns the total
+ * number of bytes successfully transferred prior to the error.
+ */
+template <typename SyncRandomAccessReadDevice, typename Allocator,
+ typename CompletionCondition>
+std::size_t read_at(SyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, boost::system::error_code& ec);
+
+/*@}*/
+/**
+ * @defgroup async_read_at boost::asio::async_read_at
+ */
+/*@{*/
+
+/// Start an asynchronous operation to read a certain amount of data at the
+/// specified offset.
+/**
+ * This function is used to asynchronously read a certain number of bytes of
+ * data from a random access device at the specified offset. The function call
+ * always returns immediately. The asynchronous operation will continue until
+ * one of the following conditions is true:
+ *
+ * @li The supplied buffers are full. That is, the bytes transferred is equal to
+ * the sum of the buffer sizes.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * async_read_some_at function.
+ *
+ * @param d The device from which the data is to be read. The type must support
+ * the AsyncRandomAccessReadDevice concept.
+ *
+ * @param offset The offset at which the data will be read.
+ *
+ * @param buffers One or more buffers into which the data will be read. The sum
+ * of the buffer sizes indicates the maximum number of bytes to read from the
+ * device. Although the buffers object may be copied as necessary, ownership of
+ * the underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * // Result of operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes copied into the buffers. If an error
+ * // occurred, this will be the number of bytes successfully
+ * // transferred prior to the error.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code
+ * boost::asio::async_read_at(d, 42, boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ *
+ * @note This overload is equivalent to calling:
+ * @code boost::asio::async_read_at(
+ * d, 42, buffers,
+ * boost::asio::transfer_all(),
+ * handler); @endcode
+ */
+template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
+ typename ReadHandler>
+void async_read_at(AsyncRandomAccessReadDevice& d, boost::uint64_t offset,
+ const MutableBufferSequence& buffers, ReadHandler handler);
+
+/// Start an asynchronous operation to read a certain amount of data at the
+/// specified offset.
+/**
+ * This function is used to asynchronously read a certain number of bytes of
+ * data from a random access device at the specified offset. The function call
+ * always returns immediately. The asynchronous operation will continue until
+ * one of the following conditions is true:
+ *
+ * @li The supplied buffers are full. That is, the bytes transferred is equal to
+ * the sum of the buffer sizes.
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * @param d The device from which the data is to be read. The type must support
+ * the AsyncRandomAccessReadDevice concept.
+ *
+ * @param offset The offset at which the data will be read.
+ *
+ * @param buffers One or more buffers into which the data will be read. The sum
+ * of the buffer sizes indicates the maximum number of bytes to read from the
+ * device. Although the buffers object may be copied as necessary, ownership of
+ * the underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the read operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * // Result of latest read_some_at operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes transferred so far.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of true indicates that the read operation is complete. False
+ * indicates that further calls to the device's async_read_some_at function are
+ * required.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * // Result of operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes copied into the buffers. If an error
+ * // occurred, this will be the number of bytes successfully
+ * // transferred prior to the error.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code boost::asio::async_read_at(d, 42,
+ * boost::asio::buffer(data, size),
+ * boost::asio::transfer_at_least(32),
+ * handler); @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
+ typename CompletionCondition, typename ReadHandler>
+void async_read_at(AsyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, const MutableBufferSequence& buffers,
+ CompletionCondition completion_condition, ReadHandler handler);
+
+/// Start an asynchronous operation to read a certain amount of data at the
+/// specified offset.
+/**
+ * This function is used to asynchronously read a certain number of bytes of
+ * data from a random access device at the specified offset. The function call
+ * always returns immediately. The asynchronous operation will continue until
+ * one of the following conditions is true:
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * async_read_some_at function.
+ *
+ * @param d The device from which the data is to be read. The type must support
+ * the AsyncRandomAccessReadDevice concept.
+ *
+ * @param offset The offset at which the data will be read.
+ *
+ * @param b A basic_streambuf object into which the data will be read. Ownership
+ * of the streambuf is retained by the caller, which must guarantee that it
+ * remains valid until the handler is called.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * // Result of operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes copied into the buffers. If an error
+ * // occurred, this will be the number of bytes successfully
+ * // transferred prior to the error.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note This overload is equivalent to calling:
+ * @code boost::asio::async_read_at(
+ * d, 42, b,
+ * boost::asio::transfer_all(),
+ * handler); @endcode
+ */
+template <typename AsyncRandomAccessReadDevice, typename Allocator,
+ typename ReadHandler>
+void async_read_at(AsyncRandomAccessReadDevice& d, boost::uint64_t offset,
+ basic_streambuf<Allocator>& b, ReadHandler handler);
+
+/// Start an asynchronous operation to read a certain amount of data at the
+/// specified offset.
+/**
+ * This function is used to asynchronously read a certain number of bytes of
+ * data from a random access device at the specified offset. The function call
+ * always returns immediately. The asynchronous operation will continue until
+ * one of the following conditions is true:
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * async_read_some_at function.
+ *
+ * @param d The device from which the data is to be read. The type must support
+ * the AsyncRandomAccessReadDevice concept.
+ *
+ * @param offset The offset at which the data will be read.
+ *
+ * @param b A basic_streambuf object into which the data will be read. Ownership
+ * of the streambuf is retained by the caller, which must guarantee that it
+ * remains valid until the handler is called.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the read operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * // Result of latest read_some_at operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes transferred so far.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of true indicates that the read operation is complete. False
+ * indicates that further calls to the device's async_read_some_at function are
+ * required.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * // Result of operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes copied into the buffers. If an error
+ * // occurred, this will be the number of bytes successfully
+ * // transferred prior to the error.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ */
+template <typename AsyncRandomAccessReadDevice, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+void async_read_at(AsyncRandomAccessReadDevice& d,
+ boost::uint64_t offset, basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, ReadHandler handler);
+
+/*@}*/
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/impl/read_at.ipp>
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_READ_AT_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/read_until.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/read_until.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,760 @@
+//
+// read_until.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_READ_UNTIL_HPP
+#define BOOST_ASIO_READ_UNTIL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/regex.hpp>
+#include <boost/type_traits/is_function.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
+#include <boost/utility/enable_if.hpp>
+#include <string>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/basic_streambuf.hpp>
+#include <boost/asio/error.hpp>
+
+namespace boost {
+namespace asio {
+
+namespace detail
+{
+ template <typename T>
+ struct has_result_type
+ {
+ struct big { char a[100]; };
+ template <typename U> static big helper(U, ...);
+ template <typename U> static char helper(U, typename U::result_type* = 0);
+ static const T& ref();
+ enum { value = (sizeof((helper)((ref)())) == 1) };
+ };
+} // namespace detail
+
+/// Type trait used to determine whether a type can be used as a match condition
+/// function with read_until and async_read_until.
+template <typename T>
+struct is_match_condition
+{
+#if defined(GENERATING_DOCUMENTATION)
+ /// The value member is true if the type may be used as a match condition.
+ static const bool value;
+#else
+ enum
+ {
+ value = boost::is_function<typename boost::remove_pointer<T>::type>::value
+ || detail::has_result_type<T>::value
+ };
+#endif
+};
+
+/**
+ * @defgroup read_until boost::asio::read_until
+ */
+/*@{*/
+
+/// Read data into a streambuf until a delimiter is encountered.
+/**
+ * This function is used to read data into the specified streambuf until the
+ * streambuf's get area contains the specified delimiter. The call will block
+ * until one of the following conditions is true:
+ *
+ * @li The get area of the streambuf contains the specified delimiter.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the streambuf's get area already contains the
+ * delimiter, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param b A streambuf object into which the data will be read.
+ *
+ * @param delim The delimiter character.
+ *
+ * @returns The number of bytes in the streambuf's get area up to and including
+ * the delimiter.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To read data into a streambuf until a newline is encountered:
+ * @code boost::asio::streambuf b;
+ * boost::asio::read_until(s, b, '\n');
+ * std::istream is(&b);
+ * std::string line;
+ * std::getline(is, line); @endcode
+ */
+template <typename SyncReadStream, typename Allocator>
+std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, char delim);
+
+/// Read data into a streambuf until a delimiter is encountered.
+/**
+ * This function is used to read data into the specified streambuf until the
+ * streambuf's get area contains the specified delimiter. The call will block
+ * until one of the following conditions is true:
+ *
+ * @li The get area of the streambuf contains the specified delimiter.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the streambuf's get area already contains the
+ * delimiter, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param b A streambuf object into which the data will be read.
+ *
+ * @param delim The delimiter character.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes in the streambuf's get area up to and including
+ * the delimiter. Returns 0 if an error occurred.
+ */
+template <typename SyncReadStream, typename Allocator>
+std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, char delim,
+ boost::system::error_code& ec);
+
+/// Read data into a streambuf until a delimiter is encountered.
+/**
+ * This function is used to read data into the specified streambuf until the
+ * streambuf's get area contains the specified delimiter. The call will block
+ * until one of the following conditions is true:
+ *
+ * @li The get area of the streambuf contains the specified delimiter.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the streambuf's get area already contains the
+ * delimiter, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param b A streambuf object into which the data will be read.
+ *
+ * @param delim The delimiter string.
+ *
+ * @returns The number of bytes in the streambuf's get area up to and including
+ * the delimiter.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To read data into a streambuf until a newline is encountered:
+ * @code boost::asio::streambuf b;
+ * boost::asio::read_until(s, b, "\r\n");
+ * std::istream is(&b);
+ * std::string line;
+ * std::getline(is, line); @endcode
+ */
+template <typename SyncReadStream, typename Allocator>
+std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, const std::string& delim);
+
+/// Read data into a streambuf until a delimiter is encountered.
+/**
+ * This function is used to read data into the specified streambuf until the
+ * streambuf's get area contains the specified delimiter. The call will block
+ * until one of the following conditions is true:
+ *
+ * @li The get area of the streambuf contains the specified delimiter.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the streambuf's get area already contains the
+ * delimiter, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param b A streambuf object into which the data will be read.
+ *
+ * @param delim The delimiter string.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes in the streambuf's get area up to and including
+ * the delimiter. Returns 0 if an error occurred.
+ */
+template <typename SyncReadStream, typename Allocator>
+std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, const std::string& delim,
+ boost::system::error_code& ec);
+
+/// Read data into a streambuf until a regular expression is located.
+/**
+ * This function is used to read data into the specified streambuf until the
+ * streambuf's get area contains some data that matches a regular expression.
+ * The call will block until one of the following conditions is true:
+ *
+ * @li A substring of the streambuf's get area matches the regular expression.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the streambuf's get area already contains data that
+ * matches the regular expression, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param b A streambuf object into which the data will be read.
+ *
+ * @param expr The regular expression.
+ *
+ * @returns The number of bytes in the streambuf's get area up to and including
+ * the substring that matches the regular expression.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To read data into a streambuf until a CR-LF sequence is encountered:
+ * @code boost::asio::streambuf b;
+ * boost::asio::read_until(s, b, boost::regex("\r\n"));
+ * std::istream is(&b);
+ * std::string line;
+ * std::getline(is, line); @endcode
+ */
+template <typename SyncReadStream, typename Allocator>
+std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr);
+
+/// Read data into a streambuf until a regular expression is located.
+/**
+ * This function is used to read data into the specified streambuf until the
+ * streambuf's get area contains some data that matches a regular expression.
+ * The call will block until one of the following conditions is true:
+ *
+ * @li A substring of the streambuf's get area matches the regular expression.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the streambuf's get area already contains data that
+ * matches the regular expression, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param b A streambuf object into which the data will be read.
+ *
+ * @param expr The regular expression.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes in the streambuf's get area up to and including
+ * the substring that matches the regular expression. Returns 0 if an error
+ * occurred.
+ */
+template <typename SyncReadStream, typename Allocator>
+std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
+ boost::system::error_code& ec);
+
+/// Read data into a streambuf until a function object indicates a match.
+/**
+ * This function is used to read data into the specified streambuf until a
+ * user-defined match condition function object, when applied to the data
+ * contained in the streambuf, indicates a successful match. The call will
+ * block until one of the following conditions is true:
+ *
+ * @li The match condition function object returns a std::pair where the second
+ * element evaluates to true.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the match condition function object already indicates
+ * a match, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param b A streambuf object into which the data will be read.
+ *
+ * @param match_condition The function object to be called to determine whether
+ * a match exists. The signature of the function object must be:
+ * @code pair<iterator, bool> match_condition(iterator begin, iterator end);
+ * @endcode
+ * where @c iterator represents the type:
+ * @code buffers_iterator<basic_streambuf<Allocator>::const_buffers_type>
+ * @endcode
+ * The iterator parameters @c begin and @c end define the range of bytes to be
+ * scanned to determine whether there is a match. The @c first member of the
+ * return value is an iterator marking one-past-the-end of the bytes that have
+ * been consumed by the match function. This iterator is used to calculate the
+ * @c begin parameter for any subsequent invocation of the match condition. The
+ * @c second member of the return value is true if a match has been found, false
+ * otherwise.
+ *
+ * @returns The number of bytes in the streambuf's get area that have been fully
+ * consumed by the match function.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The default implementation of the @c is_match_condition type trait
+ * evaluates to true for function pointers and function objects with a
+ * @c result_type typedef. It must be specialised for other user-defined
+ * function objects.
+ *
+ * @par Examples
+ * To read data into a streambuf until whitespace is encountered:
+ * @code typedef boost::asio::buffers_iterator<
+ * boost::asio::streambuf::const_buffers_type> iterator;
+ *
+ * std::pair<iterator, bool>
+ * match_whitespace(iterator begin, iterator end)
+ * {
+ * iterator i = begin;
+ * while (i != end)
+ * if (std::isspace(*i++))
+ * return std::make_pair(i, true);
+ * return std::make_pair(i, false);
+ * }
+ * ...
+ * boost::asio::streambuf b;
+ * boost::asio::read_until(s, b, match_whitespace);
+ * @endcode
+ *
+ * To read data into a streambuf until a matching character is found:
+ * @code class match_char
+ * {
+ * public:
+ * explicit match_char(char c) : c_(c) {}
+ *
+ * template <typename Iterator>
+ * std::pair<Iterator, bool> operator()(
+ * Iterator begin, Iterator end) const
+ * {
+ * Iterator i = begin;
+ * while (i != end)
+ * if (c_ == *i++)
+ * return std::make_pair(i, true);
+ * return std::make_pair(i, false);
+ * }
+ *
+ * private:
+ * char c_;
+ * };
+ *
+ * namespace asio {
+ * template <> struct is_match_condition<match_char>
+ * : public boost::true_type {};
+ * } // namespace asio
+ * ...
+ * boost::asio::streambuf b;
+ * boost::asio::read_until(s, b, match_char('a'));
+ * @endcode
+ */
+template <typename SyncReadStream, typename Allocator, typename MatchCondition>
+std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, MatchCondition match_condition,
+ typename boost::enable_if<is_match_condition<MatchCondition> >::type* = 0);
+
+/// Read data into a streambuf until a function object indicates a match.
+/**
+ * This function is used to read data into the specified streambuf until a
+ * user-defined match condition function object, when applied to the data
+ * contained in the streambuf, indicates a successful match. The call will
+ * block until one of the following conditions is true:
+ *
+ * @li The match condition function object returns a std::pair where the second
+ * element evaluates to true.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the match condition function object already indicates
+ * a match, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param b A streambuf object into which the data will be read.
+ *
+ * @param match_condition The function object to be called to determine whether
+ * a match exists. The signature of the function object must be:
+ * @code pair<iterator, bool> match_condition(iterator begin, iterator end);
+ * @endcode
+ * where @c iterator represents the type:
+ * @code buffers_iterator<basic_streambuf<Allocator>::const_buffers_type>
+ * @endcode
+ * The iterator parameters @c begin and @c end define the range of bytes to be
+ * scanned to determine whether there is a match. The @c first member of the
+ * return value is an iterator marking one-past-the-end of the bytes that have
+ * been consumed by the match function. This iterator is used to calculate the
+ * @c begin parameter for any subsequent invocation of the match condition. The
+ * @c second member of the return value is true if a match has been found, false
+ * otherwise.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes in the streambuf's get area that have been fully
+ * consumed by the match function. Returns 0 if an error occurred.
+ *
+ * @note The default implementation of the @c is_match_condition type trait
+ * evaluates to true for function pointers and function objects with a
+ * @c result_type typedef. It must be specialised for other user-defined
+ * function objects.
+ */
+template <typename SyncReadStream, typename Allocator, typename MatchCondition>
+std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ MatchCondition match_condition, boost::system::error_code& ec,
+ typename boost::enable_if<is_match_condition<MatchCondition> >::type* = 0);
+
+/*@}*/
+/**
+* @defgroup async_read_until boost::asio::async_read_until
+*/
+/*@{*/
+
+/// Start an asynchronous operation to read data into a streambuf until a
+/// delimiter is encountered.
+/**
+ * This function is used to asynchronously read data into the specified
+ * streambuf until the streambuf's get area contains the specified delimiter.
+ * The function call always returns immediately. The asynchronous operation
+ * will continue until one of the following conditions is true:
+ *
+ * @li The get area of the streambuf contains the specified delimiter.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_read_some function. If the streambuf's get area already contains the
+ * delimiter, the asynchronous operation completes immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @param b A streambuf object into which the data will be read. Ownership of
+ * the streambuf is retained by the caller, which must guarantee that it remains
+ * valid until the handler is called.
+ *
+ * @param delim The delimiter character.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ *
+ * std::size_t bytes_transferred // The number of bytes in the
+ * // streambuf's get area up to
+ * // and including the delimiter.
+ * // 0 if an error occurred.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * To asynchronously read data into a streambuf until a newline is encountered:
+ * @code boost::asio::streambuf b;
+ * ...
+ * void handler(const boost::system::error_code& e, std::size_t size)
+ * {
+ * if (!e)
+ * {
+ * std::istream is(&b);
+ * std::string line;
+ * std::getline(is, line);
+ * ...
+ * }
+ * }
+ * ...
+ * boost::asio::async_read_until(s, b, '\n', handler); @endcode
+ */
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+void async_read_until(AsyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ char delim, ReadHandler handler);
+
+/// Start an asynchronous operation to read data into a streambuf until a
+/// delimiter is encountered.
+/**
+ * This function is used to asynchronously read data into the specified
+ * streambuf until the streambuf's get area contains the specified delimiter.
+ * The function call always returns immediately. The asynchronous operation
+ * will continue until one of the following conditions is true:
+ *
+ * @li The get area of the streambuf contains the specified delimiter.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_read_some function. If the streambuf's get area already contains the
+ * delimiter, the asynchronous operation completes immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @param b A streambuf object into which the data will be read. Ownership of
+ * the streambuf is retained by the caller, which must guarantee that it remains
+ * valid until the handler is called.
+ *
+ * @param delim The delimiter string.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ *
+ * std::size_t bytes_transferred // The number of bytes in the
+ * // streambuf's get area up to
+ * // and including the delimiter.
+ * // 0 if an error occurred.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * To asynchronously read data into a streambuf until a newline is encountered:
+ * @code boost::asio::streambuf b;
+ * ...
+ * void handler(const boost::system::error_code& e, std::size_t size)
+ * {
+ * if (!e)
+ * {
+ * std::istream is(&b);
+ * std::string line;
+ * std::getline(is, line);
+ * ...
+ * }
+ * }
+ * ...
+ * boost::asio::async_read_until(s, b, "\r\n", handler); @endcode
+ */
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+void async_read_until(AsyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, const std::string& delim,
+ ReadHandler handler);
+
+/// Start an asynchronous operation to read data into a streambuf until a
+/// regular expression is located.
+/**
+ * This function is used to asynchronously read data into the specified
+ * streambuf until the streambuf's get area contains some data that matches a
+ * regular expression. The function call always returns immediately. The
+ * asynchronous operation will continue until one of the following conditions
+ * is true:
+ *
+ * @li A substring of the streambuf's get area matches the regular expression.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_read_some function. If the streambuf's get area already contains data
+ * that matches the regular expression, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @param b A streambuf object into which the data will be read. Ownership of
+ * the streambuf is retained by the caller, which must guarantee that it remains
+ * valid until the handler is called.
+ *
+ * @param expr The regular expression.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ *
+ * std::size_t bytes_transferred // The number of bytes in the
+ * // streambuf's get area up to
+ * // and including the substring
+ * // that matches the regular.
+ * // expression. 0 if an error
+ * // occurred.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * To asynchronously read data into a streambuf until a CR-LF sequence is
+ * encountered:
+ * @code boost::asio::streambuf b;
+ * ...
+ * void handler(const boost::system::error_code& e, std::size_t size)
+ * {
+ * if (!e)
+ * {
+ * std::istream is(&b);
+ * std::string line;
+ * std::getline(is, line);
+ * ...
+ * }
+ * }
+ * ...
+ * boost::asio::async_read_until(s, b, boost::regex("\r\n"), handler); @endcode
+ */
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+void async_read_until(AsyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
+ ReadHandler handler);
+
+/// Start an asynchronous operation to read data into a streambuf until a
+/// function object indicates a match.
+/**
+ * This function is used to asynchronously read data into the specified
+ * streambuf until a user-defined match condition function object, when applied
+ * to the data contained in the streambuf, indicates a successful match. The
+ * function call always returns immediately. The asynchronous operation will
+ * continue until one of the following conditions is true:
+ *
+ * @li The match condition function object returns a std::pair where the second
+ * element evaluates to true.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_read_some function. If the match condition function object already
+ * indicates a match, the operation completes immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @param b A streambuf object into which the data will be read.
+ *
+ * @param match_condition The function object to be called to determine whether
+ * a match exists. The signature of the function object must be:
+ * @code pair<iterator, bool> match_condition(iterator begin, iterator end);
+ * @endcode
+ * where @c iterator represents the type:
+ * @code buffers_iterator<basic_streambuf<Allocator>::const_buffers_type>
+ * @endcode
+ * The iterator parameters @c begin and @c end define the range of bytes to be
+ * scanned to determine whether there is a match. The @c first member of the
+ * return value is an iterator marking one-past-the-end of the bytes that have
+ * been consumed by the match function. This iterator is used to calculate the
+ * @c begin parameter for any subsequent invocation of the match condition. The
+ * @c second member of the return value is true if a match has been found, false
+ * otherwise.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * // Result of operation.
+ * const boost::system::error_code& error,
+ *
+ * // The number of bytes in the streambuf's get
+ * // area that have been fully consumed by the
+ * // match function. O if an error occurred.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The default implementation of the @c is_match_condition type trait
+ * evaluates to true for function pointers and function objects with a
+ * @c result_type typedef. It must be specialised for other user-defined
+ * function objects.
+ *
+ * @par Examples
+ * To asynchronously read data into a streambuf until whitespace is encountered:
+ * @code typedef boost::asio::buffers_iterator<
+ * boost::asio::streambuf::const_buffers_type> iterator;
+ *
+ * std::pair<iterator, bool>
+ * match_whitespace(iterator begin, iterator end)
+ * {
+ * iterator i = begin;
+ * while (i != end)
+ * if (std::isspace(*i++))
+ * return std::make_pair(i, true);
+ * return std::make_pair(i, false);
+ * }
+ * ...
+ * void handler(const boost::system::error_code& e, std::size_t size);
+ * ...
+ * boost::asio::streambuf b;
+ * boost::asio::async_read_until(s, b, match_whitespace, handler);
+ * @endcode
+ *
+ * To asynchronously read data into a streambuf until a matching character is
+ * found:
+ * @code class match_char
+ * {
+ * public:
+ * explicit match_char(char c) : c_(c) {}
+ *
+ * template <typename Iterator>
+ * std::pair<Iterator, bool> operator()(
+ * Iterator begin, Iterator end) const
+ * {
+ * Iterator i = begin;
+ * while (i != end)
+ * if (c_ == *i++)
+ * return std::make_pair(i, true);
+ * return std::make_pair(i, false);
+ * }
+ *
+ * private:
+ * char c_;
+ * };
+ *
+ * namespace asio {
+ * template <> struct is_match_condition<match_char>
+ * : public boost::true_type {};
+ * } // namespace asio
+ * ...
+ * void handler(const boost::system::error_code& e, std::size_t size);
+ * ...
+ * boost::asio::streambuf b;
+ * boost::asio::async_read_until(s, b, match_char('a'), handler);
+ * @endcode
+ */
+template <typename AsyncReadStream, typename Allocator,
+ typename MatchCondition, typename ReadHandler>
+void async_read_until(AsyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ MatchCondition match_condition, ReadHandler handler,
+ typename boost::enable_if<is_match_condition<MatchCondition> >::type* = 0);
+
+/*@}*/
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/impl/read_until.ipp>
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_READ_UNTIL_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/serial_port.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/serial_port.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,40 @@
+//
+// serial_port.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info_at_[hidden])
+//
+// Distributed under the 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 BOOST_ASIO_SERIAL_PORT_HPP
+#define BOOST_ASIO_SERIAL_PORT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/basic_serial_port.hpp>
+
+#if defined(BOOST_ASIO_HAS_SERIAL_PORT) \
+ || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+
+/// Typedef for the typical usage of a serial port.
+typedef basic_serial_port<> serial_port;
+
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SERIAL_PORT_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/serial_port_base.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/serial_port_base.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,159 @@
+//
+// serial_port_base.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info_at_[hidden])
+//
+// Distributed under the 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 BOOST_ASIO_SERIAL_PORT_BASE_HPP
+#define BOOST_ASIO_SERIAL_PORT_BASE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <stdexcept>
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+# include <termios.h>
+#endif
+#include <boost/system/error_code.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/socket_types.hpp>
+
+#if defined(GENERATING_DOCUMENTATION)
+# define BOOST_ASIO_OPTION_STORAGE implementation_defined
+#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+# define BOOST_ASIO_OPTION_STORAGE DCB
+#else
+# define BOOST_ASIO_OPTION_STORAGE termios
+#endif
+
+namespace boost {
+namespace asio {
+
+/// The serial_port_base class is used as a base for the basic_serial_port class
+/// template so that we have a common place to define the serial port options.
+class serial_port_base
+{
+public:
+ /// Serial port option to permit changing the baud rate.
+ /**
+ * Implements changing the baud rate for a given serial port.
+ */
+ class baud_rate
+ {
+ public:
+ explicit baud_rate(unsigned int rate = 0);
+ unsigned int value() const;
+ boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage,
+ boost::system::error_code& ec) const;
+ boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage,
+ boost::system::error_code& ec);
+ private:
+ unsigned int value_;
+ };
+
+ /// Serial port option to permit changing the flow control.
+ /**
+ * Implements changing the flow control for a given serial port.
+ */
+ class flow_control
+ {
+ public:
+ enum type { none, software, hardware };
+ explicit flow_control(type t = none);
+ type value() const;
+ boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage,
+ boost::system::error_code& ec) const;
+ boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage,
+ boost::system::error_code& ec);
+ private:
+ type value_;
+ };
+
+ /// Serial port option to permit changing the parity.
+ /**
+ * Implements changing the parity for a given serial port.
+ */
+ class parity
+ {
+ public:
+ enum type { none, odd, even };
+ explicit parity(type t = none);
+ type value() const;
+ boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage,
+ boost::system::error_code& ec) const;
+ boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage,
+ boost::system::error_code& ec);
+ private:
+ type value_;
+ };
+
+ /// Serial port option to permit changing the number of stop bits.
+ /**
+ * Implements changing the number of stop bits for a given serial port.
+ */
+ class stop_bits
+ {
+ public:
+ enum type { one, onepointfive, two };
+ explicit stop_bits(type t = one);
+ type value() const;
+ boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage,
+ boost::system::error_code& ec) const;
+ boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage,
+ boost::system::error_code& ec);
+ private:
+ type value_;
+ };
+
+ /// Serial port option to permit changing the character size.
+ /**
+ * Implements changing the character size for a given serial port.
+ */
+ class character_size
+ {
+ public:
+ explicit character_size(unsigned int t = 8);
+ unsigned int value() const;
+ boost::system::error_code store(BOOST_ASIO_OPTION_STORAGE& storage,
+ boost::system::error_code& ec) const;
+ boost::system::error_code load(const BOOST_ASIO_OPTION_STORAGE& storage,
+ boost::system::error_code& ec);
+ private:
+ unsigned int value_;
+ };
+
+protected:
+ /// Protected destructor to prevent deletion through this type.
+ ~serial_port_base()
+ {
+ }
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+private:
+ // Workaround to enable the empty base optimisation with Borland C++.
+ char dummy_;
+#endif
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/impl/serial_port_base.ipp>
+
+#undef BOOST_ASIO_OPTION_STORAGE
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SERIAL_PORT_BASE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/serial_port_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/serial_port_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,224 @@
+//
+// serial_port_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_SERIAL_PORT_SERVICE_HPP
+#define BOOST_ASIO_SERIAL_PORT_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <string>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/reactive_serial_port_service.hpp>
+#include <boost/asio/detail/win_iocp_serial_port_service.hpp>
+
+#if !defined(BOOST_ASIO_DISABLE_SERIAL_PORT)
+# if defined(BOOST_ASIO_HAS_IOCP) \
+ || !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
+# define BOOST_ASIO_HAS_SERIAL_PORT 1
+# endif // defined(BOOST_ASIO_HAS_IOCP)
+#endif // !defined(BOOST_ASIO_DISABLE_STREAM_HANDLE)
+
+#if defined(BOOST_ASIO_HAS_SERIAL_PORT) \
+ || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+
+/// Default service implementation for a serial port.
+class serial_port_service
+#if defined(GENERATING_DOCUMENTATION)
+ : public boost::asio::io_service::service
+#else
+ : public boost::asio::detail::service_base<serial_port_service>
+#endif
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The unique service identifier.
+ static boost::asio::io_service::id id;
+#endif
+
+private:
+ // The type of the platform-specific implementation.
+#if defined(BOOST_ASIO_HAS_IOCP)
+ typedef detail::win_iocp_serial_port_service service_impl_type;
+#elif defined(BOOST_ASIO_HAS_EPOLL)
+ typedef detail::reactive_serial_port_service<
+ detail::epoll_reactor<false> > service_impl_type;
+#elif defined(BOOST_ASIO_HAS_KQUEUE)
+ typedef detail::reactive_serial_port_service<
+ detail::kqueue_reactor<false> > service_impl_type;
+#elif defined(BOOST_ASIO_HAS_DEV_POLL)
+ typedef detail::reactive_serial_port_service<
+ detail::dev_poll_reactor<false> > service_impl_type;
+#else
+ typedef detail::reactive_serial_port_service<
+ detail::select_reactor<false> > service_impl_type;
+#endif
+
+public:
+ /// The type of a serial port implementation.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined implementation_type;
+#else
+ typedef service_impl_type::implementation_type implementation_type;
+#endif
+
+ /// The native handle type.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_type;
+#else
+ typedef service_impl_type::native_type native_type;
+#endif
+
+ /// Construct a new serial port service for the specified io_service.
+ explicit serial_port_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<serial_port_service>(io_service),
+ service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ {
+ }
+
+ /// Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ /// Construct a new serial port implementation.
+ void construct(implementation_type& impl)
+ {
+ service_impl_.construct(impl);
+ }
+
+ /// Destroy a serial port implementation.
+ void destroy(implementation_type& impl)
+ {
+ service_impl_.destroy(impl);
+ }
+
+ /// Open a serial port.
+ boost::system::error_code open(implementation_type& impl,
+ const std::string& device, boost::system::error_code& ec)
+ {
+ return service_impl_.open(impl, device, ec);
+ }
+
+ /// Assign an existing native handle to a serial port.
+ boost::system::error_code assign(implementation_type& impl,
+ const native_type& native_handle, boost::system::error_code& ec)
+ {
+ return service_impl_.assign(impl, native_handle, ec);
+ }
+
+ /// Determine whether the handle is open.
+ bool is_open(const implementation_type& impl) const
+ {
+ return service_impl_.is_open(impl);
+ }
+
+ /// Close a serial port implementation.
+ boost::system::error_code close(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.close(impl, ec);
+ }
+
+ /// Get the native handle implementation.
+ native_type native(implementation_type& impl)
+ {
+ return service_impl_.native(impl);
+ }
+
+ /// Cancel all asynchronous operations associated with the handle.
+ boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.cancel(impl, ec);
+ }
+
+ /// Set a serial port option.
+ template <typename SettableSerialPortOption>
+ boost::system::error_code set_option(implementation_type& impl,
+ const SettableSerialPortOption& option, boost::system::error_code& ec)
+ {
+ return service_impl_.set_option(impl, option, ec);
+ }
+
+ /// Get a serial port option.
+ template <typename GettableSerialPortOption>
+ boost::system::error_code get_option(const implementation_type& impl,
+ GettableSerialPortOption& option, boost::system::error_code& ec) const
+ {
+ return service_impl_.get_option(impl, option, ec);
+ }
+
+ /// Send a break sequence to the serial port.
+ boost::system::error_code send_break(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.send_break(impl, ec);
+ }
+
+ /// Write the given data to the stream.
+ template <typename ConstBufferSequence>
+ std::size_t write_some(implementation_type& impl,
+ const ConstBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return service_impl_.write_some(impl, buffers, ec);
+ }
+
+ /// Start an asynchronous write.
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_write_some(implementation_type& impl,
+ const ConstBufferSequence& buffers, WriteHandler handler)
+ {
+ service_impl_.async_write_some(impl, buffers, handler);
+ }
+
+ /// Read some data from the stream.
+ template <typename MutableBufferSequence>
+ std::size_t read_some(implementation_type& impl,
+ const MutableBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return service_impl_.read_some(impl, buffers, ec);
+ }
+
+ /// Start an asynchronous read.
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_read_some(implementation_type& impl,
+ const MutableBufferSequence& buffers, ReadHandler handler)
+ {
+ service_impl_.async_read_some(impl, buffers, handler);
+ }
+
+private:
+ // The service that provides the platform-specific implementation.
+ service_impl_type& service_impl_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SERIAL_PORT_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/socket_acceptor_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/socket_acceptor_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,227 @@
+//
+// socket_acceptor_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_SOCKET_ACCEPTOR_SERVICE_HPP
+#define BOOST_ASIO_SOCKET_ACCEPTOR_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/basic_socket.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/epoll_reactor.hpp>
+#include <boost/asio/detail/kqueue_reactor.hpp>
+#include <boost/asio/detail/select_reactor.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/reactive_socket_service.hpp>
+#include <boost/asio/detail/win_iocp_socket_service.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Default service implementation for a socket acceptor.
+template <typename Protocol>
+class socket_acceptor_service
+#if defined(GENERATING_DOCUMENTATION)
+ : public boost::asio::io_service::service
+#else
+ : public boost::asio::detail::service_base<socket_acceptor_service<Protocol> >
+#endif
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The unique service identifier.
+ static boost::asio::io_service::id id;
+#endif
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename protocol_type::endpoint endpoint_type;
+
+private:
+ // The type of the platform-specific implementation.
+#if defined(BOOST_ASIO_HAS_IOCP)
+ typedef detail::win_iocp_socket_service<Protocol> service_impl_type;
+#elif defined(BOOST_ASIO_HAS_EPOLL)
+ typedef detail::reactive_socket_service<
+ Protocol, detail::epoll_reactor<false> > service_impl_type;
+#elif defined(BOOST_ASIO_HAS_KQUEUE)
+ typedef detail::reactive_socket_service<
+ Protocol, detail::kqueue_reactor<false> > service_impl_type;
+#elif defined(BOOST_ASIO_HAS_DEV_POLL)
+ typedef detail::reactive_socket_service<
+ Protocol, detail::dev_poll_reactor<false> > service_impl_type;
+#else
+ typedef detail::reactive_socket_service<
+ Protocol, detail::select_reactor<false> > service_impl_type;
+#endif
+
+public:
+ /// The native type of the socket acceptor.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined implementation_type;
+#else
+ typedef typename service_impl_type::implementation_type implementation_type;
+#endif
+
+ /// The native acceptor type.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_type;
+#else
+ typedef typename service_impl_type::native_type native_type;
+#endif
+
+ /// Construct a new socket acceptor service for the specified io_service.
+ explicit socket_acceptor_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ socket_acceptor_service<Protocol> >(io_service),
+ service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ {
+ }
+
+ /// Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ /// Construct a new socket acceptor implementation.
+ void construct(implementation_type& impl)
+ {
+ service_impl_.construct(impl);
+ }
+
+ /// Destroy a socket acceptor implementation.
+ void destroy(implementation_type& impl)
+ {
+ service_impl_.destroy(impl);
+ }
+
+ /// Open a new socket acceptor implementation.
+ boost::system::error_code open(implementation_type& impl,
+ const protocol_type& protocol, boost::system::error_code& ec)
+ {
+ return service_impl_.open(impl, protocol, ec);
+ }
+
+ /// Assign an existing native acceptor to a socket acceptor.
+ boost::system::error_code assign(implementation_type& impl,
+ const protocol_type& protocol, const native_type& native_acceptor,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.assign(impl, protocol, native_acceptor, ec);
+ }
+
+ /// Determine whether the acceptor is open.
+ bool is_open(const implementation_type& impl) const
+ {
+ return service_impl_.is_open(impl);
+ }
+
+ /// Cancel all asynchronous operations associated with the acceptor.
+ boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.cancel(impl, ec);
+ }
+
+ /// Bind the socket acceptor to the specified local endpoint.
+ boost::system::error_code bind(implementation_type& impl,
+ const endpoint_type& endpoint, boost::system::error_code& ec)
+ {
+ return service_impl_.bind(impl, endpoint, ec);
+ }
+
+ /// Place the socket acceptor into the state where it will listen for new
+ /// connections.
+ boost::system::error_code listen(implementation_type& impl, int backlog,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.listen(impl, backlog, ec);
+ }
+
+ /// Close a socket acceptor implementation.
+ boost::system::error_code close(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.close(impl, ec);
+ }
+
+ /// Get the native acceptor implementation.
+ native_type native(implementation_type& impl)
+ {
+ return service_impl_.native(impl);
+ }
+
+ /// Set a socket option.
+ template <typename SettableSocketOption>
+ boost::system::error_code set_option(implementation_type& impl,
+ const SettableSocketOption& option, boost::system::error_code& ec)
+ {
+ return service_impl_.set_option(impl, option, ec);
+ }
+
+ /// Get a socket option.
+ template <typename GettableSocketOption>
+ boost::system::error_code get_option(const implementation_type& impl,
+ GettableSocketOption& option, boost::system::error_code& ec) const
+ {
+ return service_impl_.get_option(impl, option, ec);
+ }
+
+ /// Perform an IO control command on the socket.
+ template <typename IoControlCommand>
+ boost::system::error_code io_control(implementation_type& impl,
+ IoControlCommand& command, boost::system::error_code& ec)
+ {
+ return service_impl_.io_control(impl, command, ec);
+ }
+
+ /// Get the local endpoint.
+ endpoint_type local_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.local_endpoint(impl, ec);
+ }
+
+ /// Accept a new connection.
+ template <typename SocketService>
+ boost::system::error_code accept(implementation_type& impl,
+ basic_socket<protocol_type, SocketService>& peer,
+ endpoint_type* peer_endpoint, boost::system::error_code& ec)
+ {
+ return service_impl_.accept(impl, peer, peer_endpoint, ec);
+ }
+
+ /// Start an asynchronous accept.
+ template <typename SocketService, typename AcceptHandler>
+ void async_accept(implementation_type& impl,
+ basic_socket<protocol_type, SocketService>& peer,
+ endpoint_type* peer_endpoint, AcceptHandler handler)
+ {
+ service_impl_.async_accept(impl, peer, peer_endpoint, handler);
+ }
+
+private:
+ // The service that provides the platform-specific implementation.
+ service_impl_type& service_impl_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SOCKET_ACCEPTOR_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/socket_base.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/socket_base.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,517 @@
+//
+// socket_base.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_SOCKET_BASE_HPP
+#define BOOST_ASIO_SOCKET_BASE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/io_control.hpp>
+#include <boost/asio/detail/socket_option.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+namespace boost {
+namespace asio {
+
+/// The socket_base class is used as a base for the basic_stream_socket and
+/// basic_datagram_socket class templates so that we have a common place to
+/// define the shutdown_type and enum.
+class socket_base
+{
+public:
+ /// Different ways a socket may be shutdown.
+ enum shutdown_type
+ {
+#if defined(GENERATING_DOCUMENTATION)
+ /// Shutdown the receive side of the socket.
+ shutdown_receive = implementation_defined,
+
+ /// Shutdown the send side of the socket.
+ shutdown_send = implementation_defined,
+
+ /// Shutdown both send and receive on the socket.
+ shutdown_both = implementation_defined
+#else
+ shutdown_receive = boost::asio::detail::shutdown_receive,
+ shutdown_send = boost::asio::detail::shutdown_send,
+ shutdown_both = boost::asio::detail::shutdown_both
+#endif
+ };
+
+ /// Bitmask type for flags that can be passed to send and receive operations.
+ typedef int message_flags;
+
+#if defined(GENERATING_DOCUMENTATION)
+ /// Peek at incoming data without removing it from the input queue.
+ static const int message_peek = implementation_defined;
+
+ /// Process out-of-band data.
+ static const int message_out_of_band = implementation_defined;
+
+ /// Specify that the data should not be subject to routing.
+ static const int message_do_not_route = implementation_defined;
+#else
+ BOOST_STATIC_CONSTANT(int,
+ message_peek = boost::asio::detail::message_peek);
+ BOOST_STATIC_CONSTANT(int,
+ message_out_of_band = boost::asio::detail::message_out_of_band);
+ BOOST_STATIC_CONSTANT(int,
+ message_do_not_route = boost::asio::detail::message_do_not_route);
+#endif
+
+ /// Socket option to permit sending of broadcast messages.
+ /**
+ * Implements the SOL_SOCKET/SO_BROADCAST socket option.
+ *
+ * @par Examples
+ * Setting the option:
+ * @code
+ * boost::asio::ip::udp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::broadcast option(true);
+ * socket.set_option(option);
+ * @endcode
+ *
+ * @par
+ * Getting the current option value:
+ * @code
+ * boost::asio::ip::udp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::broadcast option;
+ * socket.get_option(option);
+ * bool is_set = option.value();
+ * @endcode
+ *
+ * @par Concepts:
+ * Socket_Option, Boolean_Socket_Option.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined broadcast;
+#else
+ typedef boost::asio::detail::socket_option::boolean<
+ SOL_SOCKET, SO_BROADCAST> broadcast;
+#endif
+
+ /// Socket option to enable socket-level debugging.
+ /**
+ * Implements the SOL_SOCKET/SO_DEBUG socket option.
+ *
+ * @par Examples
+ * Setting the option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::debug option(true);
+ * socket.set_option(option);
+ * @endcode
+ *
+ * @par
+ * Getting the current option value:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::debug option;
+ * socket.get_option(option);
+ * bool is_set = option.value();
+ * @endcode
+ *
+ * @par Concepts:
+ * Socket_Option, Boolean_Socket_Option.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined debug;
+#else
+ typedef boost::asio::detail::socket_option::boolean<
+ SOL_SOCKET, SO_DEBUG> debug;
+#endif
+
+ /// Socket option to prevent routing, use local interfaces only.
+ /**
+ * Implements the SOL_SOCKET/SO_DONTROUTE socket option.
+ *
+ * @par Examples
+ * Setting the option:
+ * @code
+ * boost::asio::ip::udp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::do_not_route option(true);
+ * socket.set_option(option);
+ * @endcode
+ *
+ * @par
+ * Getting the current option value:
+ * @code
+ * boost::asio::ip::udp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::do_not_route option;
+ * socket.get_option(option);
+ * bool is_set = option.value();
+ * @endcode
+ *
+ * @par Concepts:
+ * Socket_Option, Boolean_Socket_Option.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined do_not_route;
+#else
+ typedef boost::asio::detail::socket_option::boolean<
+ SOL_SOCKET, SO_DONTROUTE> do_not_route;
+#endif
+
+ /// Socket option to send keep-alives.
+ /**
+ * Implements the SOL_SOCKET/SO_KEEPALIVE socket option.
+ *
+ * @par Examples
+ * Setting the option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::keep_alive option(true);
+ * socket.set_option(option);
+ * @endcode
+ *
+ * @par
+ * Getting the current option value:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::keep_alive option;
+ * socket.get_option(option);
+ * bool is_set = option.value();
+ * @endcode
+ *
+ * @par Concepts:
+ * Socket_Option, Boolean_Socket_Option.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined keep_alive;
+#else
+ typedef boost::asio::detail::socket_option::boolean<
+ SOL_SOCKET, SO_KEEPALIVE> keep_alive;
+#endif
+
+ /// Socket option for the send buffer size of a socket.
+ /**
+ * Implements the SOL_SOCKET/SO_SNDBUF socket option.
+ *
+ * @par Examples
+ * Setting the option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::send_buffer_size option(8192);
+ * socket.set_option(option);
+ * @endcode
+ *
+ * @par
+ * Getting the current option value:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::send_buffer_size option;
+ * socket.get_option(option);
+ * int size = option.value();
+ * @endcode
+ *
+ * @par Concepts:
+ * Socket_Option, Integer_Socket_Option.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined send_buffer_size;
+#else
+ typedef boost::asio::detail::socket_option::integer<
+ SOL_SOCKET, SO_SNDBUF> send_buffer_size;
+#endif
+
+ /// Socket option for the send low watermark.
+ /**
+ * Implements the SOL_SOCKET/SO_SNDLOWAT socket option.
+ *
+ * @par Examples
+ * Setting the option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::send_low_watermark option(1024);
+ * socket.set_option(option);
+ * @endcode
+ *
+ * @par
+ * Getting the current option value:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::send_low_watermark option;
+ * socket.get_option(option);
+ * int size = option.value();
+ * @endcode
+ *
+ * @par Concepts:
+ * Socket_Option, Integer_Socket_Option.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined send_low_watermark;
+#else
+ typedef boost::asio::detail::socket_option::integer<
+ SOL_SOCKET, SO_SNDLOWAT> send_low_watermark;
+#endif
+
+ /// Socket option for the receive buffer size of a socket.
+ /**
+ * Implements the SOL_SOCKET/SO_RCVBUF socket option.
+ *
+ * @par Examples
+ * Setting the option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::receive_buffer_size option(8192);
+ * socket.set_option(option);
+ * @endcode
+ *
+ * @par
+ * Getting the current option value:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::receive_buffer_size option;
+ * socket.get_option(option);
+ * int size = option.value();
+ * @endcode
+ *
+ * @par Concepts:
+ * Socket_Option, Integer_Socket_Option.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined receive_buffer_size;
+#else
+ typedef boost::asio::detail::socket_option::integer<
+ SOL_SOCKET, SO_RCVBUF> receive_buffer_size;
+#endif
+
+ /// Socket option for the receive low watermark.
+ /**
+ * Implements the SOL_SOCKET/SO_RCVLOWAT socket option.
+ *
+ * @par Examples
+ * Setting the option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::receive_low_watermark option(1024);
+ * socket.set_option(option);
+ * @endcode
+ *
+ * @par
+ * Getting the current option value:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::receive_low_watermark option;
+ * socket.get_option(option);
+ * int size = option.value();
+ * @endcode
+ *
+ * @par Concepts:
+ * Socket_Option, Integer_Socket_Option.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined receive_low_watermark;
+#else
+ typedef boost::asio::detail::socket_option::integer<
+ SOL_SOCKET, SO_RCVLOWAT> receive_low_watermark;
+#endif
+
+ /// Socket option to allow the socket to be bound to an address that is
+ /// already in use.
+ /**
+ * Implements the SOL_SOCKET/SO_REUSEADDR socket option.
+ *
+ * @par Examples
+ * Setting the option:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::socket_base::reuse_address option(true);
+ * acceptor.set_option(option);
+ * @endcode
+ *
+ * @par
+ * Getting the current option value:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::socket_base::reuse_address option;
+ * acceptor.get_option(option);
+ * bool is_set = option.value();
+ * @endcode
+ *
+ * @par Concepts:
+ * Socket_Option, Boolean_Socket_Option.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined reuse_address;
+#else
+ typedef boost::asio::detail::socket_option::boolean<
+ SOL_SOCKET, SO_REUSEADDR> reuse_address;
+#endif
+
+ /// Socket option to specify whether the socket lingers on close if unsent
+ /// data is present.
+ /**
+ * Implements the SOL_SOCKET/SO_LINGER socket option.
+ *
+ * @par Examples
+ * Setting the option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::linger option(true, 30);
+ * socket.set_option(option);
+ * @endcode
+ *
+ * @par
+ * Getting the current option value:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::linger option;
+ * socket.get_option(option);
+ * bool is_set = option.enabled();
+ * unsigned short timeout = option.timeout();
+ * @endcode
+ *
+ * @par Concepts:
+ * Socket_Option, Linger_Socket_Option.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined linger;
+#else
+ typedef boost::asio::detail::socket_option::linger<
+ SOL_SOCKET, SO_LINGER> linger;
+#endif
+
+ /// Socket option to report aborted connections on accept.
+ /**
+ * Implements a custom socket option that determines whether or not an accept
+ * operation is permitted to fail with boost::asio::error::connection_aborted.
+ * By default the option is false.
+ *
+ * @par Examples
+ * Setting the option:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::socket_base::enable_connection_aborted option(true);
+ * acceptor.set_option(option);
+ * @endcode
+ *
+ * @par
+ * Getting the current option value:
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * ...
+ * boost::asio::socket_base::enable_connection_aborted option;
+ * acceptor.get_option(option);
+ * bool is_set = option.value();
+ * @endcode
+ *
+ * @par Concepts:
+ * Socket_Option, Boolean_Socket_Option.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined enable_connection_aborted;
+#else
+ typedef boost::asio::detail::socket_option::boolean<
+ boost::asio::detail::custom_socket_option_level,
+ boost::asio::detail::enable_connection_aborted_option>
+ enable_connection_aborted;
+#endif
+
+ /// IO control command to set the blocking mode of the socket.
+ /**
+ * Implements the FIONBIO IO control command.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::non_blocking_io command(true);
+ * socket.io_control(command);
+ * @endcode
+ *
+ * @par Concepts:
+ * IO_Control_Command, Boolean_IO_Control_Command.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined non_blocking_io;
+#else
+ typedef boost::asio::detail::io_control::non_blocking_io non_blocking_io;
+#endif
+
+ /// IO control command to get the amount of data that can be read without
+ /// blocking.
+ /**
+ * Implements the FIONREAD IO control command.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_service);
+ * ...
+ * boost::asio::socket_base::bytes_readable command(true);
+ * socket.io_control(command);
+ * std::size_t bytes_readable = command.get();
+ * @endcode
+ *
+ * @par Concepts:
+ * IO_Control_Command, Size_IO_Control_Command.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined bytes_readable;
+#else
+ typedef boost::asio::detail::io_control::bytes_readable bytes_readable;
+#endif
+
+ /// The maximum length of the queue of pending incoming connections.
+#if defined(GENERATING_DOCUMENTATION)
+ static const int max_connections = implementation_defined;
+#else
+ BOOST_STATIC_CONSTANT(int, max_connections = SOMAXCONN);
+#endif
+
+protected:
+ /// Protected destructor to prevent deletion through this type.
+ ~socket_base()
+ {
+ }
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+private:
+ // Workaround to enable the empty base optimisation with Borland C++.
+ char dummy_;
+#endif
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SOCKET_BASE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ssl.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ssl.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,26 @@
+//
+// ssl.hpp
+// ~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_SSL_HPP
+#define BOOST_ASIO_SSL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/ssl/basic_context.hpp>
+#include <boost/asio/ssl/context.hpp>
+#include <boost/asio/ssl/context_base.hpp>
+#include <boost/asio/ssl/context_service.hpp>
+#include <boost/asio/ssl/stream.hpp>
+#include <boost/asio/ssl/stream_base.hpp>
+#include <boost/asio/ssl/stream_service.hpp>
+
+#endif // BOOST_ASIO_SSL_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ssl/basic_context.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ssl/basic_context.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,436 @@
+//
+// basic_context.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
+// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_SSL_BASIC_CONTEXT_HPP
+#define BOOST_ASIO_SSL_BASIC_CONTEXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <string>
+#include <boost/noncopyable.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/ssl/context_base.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+namespace ssl {
+
+/// SSL context.
+template <typename Service>
+class basic_context
+ : public context_base,
+ private boost::noncopyable
+{
+public:
+ /// The type of the service that will be used to provide context operations.
+ typedef Service service_type;
+
+ /// The native implementation type of the locking dispatcher.
+ typedef typename service_type::impl_type impl_type;
+
+ /// Constructor.
+ basic_context(boost::asio::io_service& io_service, method m)
+ : service_(boost::asio::use_service<Service>(io_service)),
+ impl_(service_.null())
+ {
+ service_.create(impl_, m);
+ }
+
+ /// Destructor.
+ ~basic_context()
+ {
+ service_.destroy(impl_);
+ }
+
+ /// Get the underlying implementation in the native type.
+ /**
+ * This function may be used to obtain the underlying implementation of the
+ * context. This is intended to allow access to context functionality that is
+ * not otherwise provided.
+ */
+ impl_type impl()
+ {
+ return impl_;
+ }
+
+ /// Set options on the context.
+ /**
+ * This function may be used to configure the SSL options used by the context.
+ *
+ * @param o A bitmask of options. The available option values are defined in
+ * the context_base class. The options are bitwise-ored with any existing
+ * value for the options.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void set_options(options o)
+ {
+ boost::system::error_code ec;
+ service_.set_options(impl_, o, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Set options on the context.
+ /**
+ * This function may be used to configure the SSL options used by the context.
+ *
+ * @param o A bitmask of options. The available option values are defined in
+ * the context_base class. The options are bitwise-ored with any existing
+ * value for the options.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code set_options(options o,
+ boost::system::error_code& ec)
+ {
+ return service_.set_options(impl_, o, ec);
+ }
+
+ /// Set the peer verification mode.
+ /**
+ * This function may be used to configure the peer verification mode used by
+ * the context.
+ *
+ * @param v A bitmask of peer verification modes. The available verify_mode
+ * values are defined in the context_base class.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void set_verify_mode(verify_mode v)
+ {
+ boost::system::error_code ec;
+ service_.set_verify_mode(impl_, v, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Set the peer verification mode.
+ /**
+ * This function may be used to configure the peer verification mode used by
+ * the context.
+ *
+ * @param v A bitmask of peer verification modes. The available verify_mode
+ * values are defined in the context_base class.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code set_verify_mode(verify_mode v,
+ boost::system::error_code& ec)
+ {
+ return service_.set_verify_mode(impl_, v, ec);
+ }
+
+ /// Load a certification authority file for performing verification.
+ /**
+ * This function is used to load one or more trusted certification authorities
+ * from a file.
+ *
+ * @param filename The name of a file containing certification authority
+ * certificates in PEM format.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void load_verify_file(const std::string& filename)
+ {
+ boost::system::error_code ec;
+ service_.load_verify_file(impl_, filename, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Load a certification authority file for performing verification.
+ /**
+ * This function is used to load the certificates for one or more trusted
+ * certification authorities from a file.
+ *
+ * @param filename The name of a file containing certification authority
+ * certificates in PEM format.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code load_verify_file(const std::string& filename,
+ boost::system::error_code& ec)
+ {
+ return service_.load_verify_file(impl_, filename, ec);
+ }
+
+ /// Add a directory containing certificate authority files to be used for
+ /// performing verification.
+ /**
+ * This function is used to specify the name of a directory containing
+ * certification authority certificates. Each file in the directory must
+ * contain a single certificate. The files must be named using the subject
+ * name's hash and an extension of ".0".
+ *
+ * @param path The name of a directory containing the certificates.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void add_verify_path(const std::string& path)
+ {
+ boost::system::error_code ec;
+ service_.add_verify_path(impl_, path, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Add a directory containing certificate authority files to be used for
+ /// performing verification.
+ /**
+ * This function is used to specify the name of a directory containing
+ * certification authority certificates. Each file in the directory must
+ * contain a single certificate. The files must be named using the subject
+ * name's hash and an extension of ".0".
+ *
+ * @param path The name of a directory containing the certificates.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code add_verify_path(const std::string& path,
+ boost::system::error_code& ec)
+ {
+ return service_.add_verify_path(impl_, path, ec);
+ }
+
+ /// Use a certificate from a file.
+ /**
+ * This function is used to load a certificate into the context from a file.
+ *
+ * @param filename The name of the file containing the certificate.
+ *
+ * @param format The file format (ASN.1 or PEM).
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void use_certificate_file(const std::string& filename, file_format format)
+ {
+ boost::system::error_code ec;
+ service_.use_certificate_file(impl_, filename, format, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Use a certificate from a file.
+ /**
+ * This function is used to load a certificate into the context from a file.
+ *
+ * @param filename The name of the file containing the certificate.
+ *
+ * @param format The file format (ASN.1 or PEM).
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code use_certificate_file(const std::string& filename,
+ file_format format, boost::system::error_code& ec)
+ {
+ return service_.use_certificate_file(impl_, filename, format, ec);
+ }
+
+ /// Use a certificate chain from a file.
+ /**
+ * This function is used to load a certificate chain into the context from a
+ * file.
+ *
+ * @param filename The name of the file containing the certificate. The file
+ * must use the PEM format.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void use_certificate_chain_file(const std::string& filename)
+ {
+ boost::system::error_code ec;
+ service_.use_certificate_chain_file(impl_, filename, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Use a certificate chain from a file.
+ /**
+ * This function is used to load a certificate chain into the context from a
+ * file.
+ *
+ * @param filename The name of the file containing the certificate. The file
+ * must use the PEM format.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code use_certificate_chain_file(
+ const std::string& filename, boost::system::error_code& ec)
+ {
+ return service_.use_certificate_chain_file(impl_, filename, ec);
+ }
+
+ /// Use a private key from a file.
+ /**
+ * This function is used to load a private key into the context from a file.
+ *
+ * @param filename The name of the file containing the private key.
+ *
+ * @param format The file format (ASN.1 or PEM).
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void use_private_key_file(const std::string& filename, file_format format)
+ {
+ boost::system::error_code ec;
+ service_.use_private_key_file(impl_, filename, format, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Use a private key from a file.
+ /**
+ * This function is used to load a private key into the context from a file.
+ *
+ * @param filename The name of the file containing the private key.
+ *
+ * @param format The file format (ASN.1 or PEM).
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code use_private_key_file(const std::string& filename,
+ file_format format, boost::system::error_code& ec)
+ {
+ return service_.use_private_key_file(impl_, filename, format, ec);
+ }
+
+ /// Use an RSA private key from a file.
+ /**
+ * This function is used to load an RSA private key into the context from a
+ * file.
+ *
+ * @param filename The name of the file containing the RSA private key.
+ *
+ * @param format The file format (ASN.1 or PEM).
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void use_rsa_private_key_file(const std::string& filename, file_format format)
+ {
+ boost::system::error_code ec;
+ service_.use_rsa_private_key_file(impl_, filename, format, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Use an RSA private key from a file.
+ /**
+ * This function is used to load an RSA private key into the context from a
+ * file.
+ *
+ * @param filename The name of the file containing the RSA private key.
+ *
+ * @param format The file format (ASN.1 or PEM).
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code use_rsa_private_key_file(
+ const std::string& filename, file_format format,
+ boost::system::error_code& ec)
+ {
+ return service_.use_rsa_private_key_file(impl_, filename, format, ec);
+ }
+
+ /// Use the specified file to obtain the temporary Diffie-Hellman parameters.
+ /**
+ * This function is used to load Diffie-Hellman parameters into the context
+ * from a file.
+ *
+ * @param filename The name of the file containing the Diffie-Hellman
+ * parameters. The file must use the PEM format.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void use_tmp_dh_file(const std::string& filename)
+ {
+ boost::system::error_code ec;
+ service_.use_tmp_dh_file(impl_, filename, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Use the specified file to obtain the temporary Diffie-Hellman parameters.
+ /**
+ * This function is used to load Diffie-Hellman parameters into the context
+ * from a file.
+ *
+ * @param filename The name of the file containing the Diffie-Hellman
+ * parameters. The file must use the PEM format.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code use_tmp_dh_file(const std::string& filename,
+ boost::system::error_code& ec)
+ {
+ return service_.use_tmp_dh_file(impl_, filename, ec);
+ }
+
+ /// Set the password callback.
+ /**
+ * This function is used to specify a callback function to obtain password
+ * information about an encrypted key in PEM format.
+ *
+ * @param callback The function object to be used for obtaining the password.
+ * The function signature of the handler must be:
+ * @code std::string password_callback(
+ * std::size_t max_length, // The maximum size for a password.
+ * password_purpose purpose // Whether password is for reading or writing.
+ * ); @endcode
+ * The return value of the callback is a string containing the password.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename PasswordCallback>
+ void set_password_callback(PasswordCallback callback)
+ {
+ boost::system::error_code ec;
+ service_.set_password_callback(impl_, callback, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Set the password callback.
+ /**
+ * This function is used to specify a callback function to obtain password
+ * information about an encrypted key in PEM format.
+ *
+ * @param callback The function object to be used for obtaining the password.
+ * The function signature of the handler must be:
+ * @code std::string password_callback(
+ * std::size_t max_length, // The maximum size for a password.
+ * password_purpose purpose // Whether password is for reading or writing.
+ * ); @endcode
+ * The return value of the callback is a string containing the password.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ template <typename PasswordCallback>
+ boost::system::error_code set_password_callback(PasswordCallback callback,
+ boost::system::error_code& ec)
+ {
+ return service_.set_password_callback(impl_, callback, ec);
+ }
+
+private:
+ /// The backend service implementation.
+ service_type& service_;
+
+ /// The underlying native implementation.
+ impl_type impl_;
+};
+
+} // namespace ssl
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SSL_BASIC_CONTEXT_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ssl/context.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ssl/context.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,37 @@
+//
+// context.hpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
+// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_SSL_CONTEXT_HPP
+#define BOOST_ASIO_SSL_CONTEXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/ssl/basic_context.hpp>
+#include <boost/asio/ssl/context_service.hpp>
+
+namespace boost {
+namespace asio {
+namespace ssl {
+
+/// Typedef for the typical usage of context.
+typedef basic_context<context_service> context;
+
+} // namespace ssl
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SSL_CONTEXT_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ssl/context_base.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ssl/context_base.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,166 @@
+//
+// context_base.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_SSL_CONTEXT_BASE_HPP
+#define BOOST_ASIO_SSL_CONTEXT_BASE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/ssl/detail/openssl_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace ssl {
+
+/// The context_base class is used as a base for the basic_context class
+/// template so that we have a common place to define various enums.
+class context_base
+{
+public:
+ /// Different methods supported by a context.
+ enum method
+ {
+ /// Generic SSL version 2.
+ sslv2,
+
+ /// SSL version 2 client.
+ sslv2_client,
+
+ /// SSL version 2 server.
+ sslv2_server,
+
+ /// Generic SSL version 3.
+ sslv3,
+
+ /// SSL version 3 client.
+ sslv3_client,
+
+ /// SSL version 3 server.
+ sslv3_server,
+
+ /// Generic TLS version 1.
+ tlsv1,
+
+ /// TLS version 1 client.
+ tlsv1_client,
+
+ /// TLS version 1 server.
+ tlsv1_server,
+
+ /// Generic SSL/TLS.
+ sslv23,
+
+ /// SSL/TLS client.
+ sslv23_client,
+
+ /// SSL/TLS server.
+ sslv23_server
+ };
+
+ /// Bitmask type for SSL options.
+ typedef int options;
+
+#if defined(GENERATING_DOCUMENTATION)
+ /// Implement various bug workarounds.
+ static const int default_workarounds = implementation_defined;
+
+ /// Always create a new key when using tmp_dh parameters.
+ static const int single_dh_use = implementation_defined;
+
+ /// Disable SSL v2.
+ static const int no_sslv2 = implementation_defined;
+
+ /// Disable SSL v3.
+ static const int no_sslv3 = implementation_defined;
+
+ /// Disable TLS v1.
+ static const int no_tlsv1 = implementation_defined;
+#else
+ BOOST_STATIC_CONSTANT(int, default_workarounds = SSL_OP_ALL);
+ BOOST_STATIC_CONSTANT(int, single_dh_use = SSL_OP_SINGLE_DH_USE);
+ BOOST_STATIC_CONSTANT(int, no_sslv2 = SSL_OP_NO_SSLv2);
+ BOOST_STATIC_CONSTANT(int, no_sslv3 = SSL_OP_NO_SSLv3);
+ BOOST_STATIC_CONSTANT(int, no_tlsv1 = SSL_OP_NO_TLSv1);
+#endif
+
+ /// File format types.
+ enum file_format
+ {
+ /// ASN.1 file.
+ asn1,
+
+ /// PEM file.
+ pem
+ };
+
+ /// Bitmask type for peer verification.
+ typedef int verify_mode;
+
+#if defined(GENERATING_DOCUMENTATION)
+ /// No verification.
+ static const int verify_none = implementation_defined;
+
+ /// Verify the peer.
+ static const int verify_peer = implementation_defined;
+
+ /// Fail verification if the peer has no certificate. Ignored unless
+ /// verify_peer is set.
+ static const int verify_fail_if_no_peer_cert = implementation_defined;
+
+ /// Do not request client certificate on renegotiation. Ignored unless
+ /// verify_peer is set.
+ static const int verify_client_once = implementation_defined;
+#else
+ BOOST_STATIC_CONSTANT(int, verify_none = SSL_VERIFY_NONE);
+ BOOST_STATIC_CONSTANT(int, verify_peer = SSL_VERIFY_PEER);
+ BOOST_STATIC_CONSTANT(int,
+ verify_fail_if_no_peer_cert = SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
+ BOOST_STATIC_CONSTANT(int, verify_client_once = SSL_VERIFY_CLIENT_ONCE);
+#endif
+
+ /// Purpose of PEM password.
+ enum password_purpose
+ {
+ /// The password is needed for reading/decryption.
+ for_reading,
+
+ /// The password is needed for writing/encryption.
+ for_writing
+ };
+
+protected:
+ /// Protected destructor to prevent deletion through this type.
+ ~context_base()
+ {
+ }
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+private:
+ // Workaround to enable the empty base optimisation with Borland C++.
+ char dummy_;
+#endif
+};
+
+} // namespace ssl
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SSL_CONTEXT_BASE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ssl/context_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ssl/context_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,177 @@
+//
+// context_service.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
+// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_SSL_CONTEXT_SERVICE_HPP
+#define BOOST_ASIO_SSL_CONTEXT_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <string>
+#include <boost/noncopyable.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/ssl/context_base.hpp>
+#include <boost/asio/ssl/detail/openssl_context_service.hpp>
+
+namespace boost {
+namespace asio {
+namespace ssl {
+
+/// Default service implementation for a context.
+class context_service
+#if defined(GENERATING_DOCUMENTATION)
+ : public boost::asio::io_service::service
+#else
+ : public boost::asio::detail::service_base<context_service>
+#endif
+{
+private:
+ // The type of the platform-specific implementation.
+ typedef detail::openssl_context_service service_impl_type;
+
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The unique service identifier.
+ static boost::asio::io_service::id id;
+#endif
+
+ /// The type of the context.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined impl_type;
+#else
+ typedef service_impl_type::impl_type impl_type;
+#endif
+
+ /// Constructor.
+ explicit context_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<context_service>(io_service),
+ service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ {
+ }
+
+ /// Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ /// Return a null context implementation.
+ impl_type null() const
+ {
+ return service_impl_.null();
+ }
+
+ /// Create a new context implementation.
+ void create(impl_type& impl, context_base::method m)
+ {
+ service_impl_.create(impl, m);
+ }
+
+ /// Destroy a context implementation.
+ void destroy(impl_type& impl)
+ {
+ service_impl_.destroy(impl);
+ }
+
+ /// Set options on the context.
+ boost::system::error_code set_options(impl_type& impl,
+ context_base::options o, boost::system::error_code& ec)
+ {
+ return service_impl_.set_options(impl, o, ec);
+ }
+
+ /// Set peer verification mode.
+ boost::system::error_code set_verify_mode(impl_type& impl,
+ context_base::verify_mode v, boost::system::error_code& ec)
+ {
+ return service_impl_.set_verify_mode(impl, v, ec);
+ }
+
+ /// Load a certification authority file for performing verification.
+ boost::system::error_code load_verify_file(impl_type& impl,
+ const std::string& filename, boost::system::error_code& ec)
+ {
+ return service_impl_.load_verify_file(impl, filename, ec);
+ }
+
+ /// Add a directory containing certification authority files to be used for
+ /// performing verification.
+ boost::system::error_code add_verify_path(impl_type& impl,
+ const std::string& path, boost::system::error_code& ec)
+ {
+ return service_impl_.add_verify_path(impl, path, ec);
+ }
+
+ /// Use a certificate from a file.
+ boost::system::error_code use_certificate_file(impl_type& impl,
+ const std::string& filename, context_base::file_format format,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.use_certificate_file(impl, filename, format, ec);
+ }
+
+ /// Use a certificate chain from a file.
+ boost::system::error_code use_certificate_chain_file(impl_type& impl,
+ const std::string& filename, boost::system::error_code& ec)
+ {
+ return service_impl_.use_certificate_chain_file(impl, filename, ec);
+ }
+
+ /// Use a private key from a file.
+ boost::system::error_code use_private_key_file(impl_type& impl,
+ const std::string& filename, context_base::file_format format,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.use_private_key_file(impl, filename, format, ec);
+ }
+
+ /// Use an RSA private key from a file.
+ boost::system::error_code use_rsa_private_key_file(impl_type& impl,
+ const std::string& filename, context_base::file_format format,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.use_rsa_private_key_file(impl, filename, format, ec);
+ }
+
+ /// Use the specified file to obtain the temporary Diffie-Hellman parameters.
+ boost::system::error_code use_tmp_dh_file(impl_type& impl,
+ const std::string& filename, boost::system::error_code& ec)
+ {
+ return service_impl_.use_tmp_dh_file(impl, filename, ec);
+ }
+
+ /// Set the password callback.
+ template <typename PasswordCallback>
+ boost::system::error_code set_password_callback(impl_type& impl,
+ PasswordCallback callback, boost::system::error_code& ec)
+ {
+ return service_impl_.set_password_callback(impl, callback, ec);
+ }
+
+private:
+ // The service that provides the platform-specific implementation.
+ service_impl_type& service_impl_;
+};
+
+} // namespace ssl
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SSL_CONTEXT_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ssl/detail/openssl_context_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ssl/detail/openssl_context_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,381 @@
+//
+// openssl_context_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
+// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_SSL_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP
+#define BOOST_ASIO_SSL_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstring>
+#include <string>
+#include <boost/function.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/ssl/context_base.hpp>
+#include <boost/asio/ssl/detail/openssl_init.hpp>
+#include <boost/asio/ssl/detail/openssl_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace ssl {
+namespace detail {
+
+class openssl_context_service
+ : public boost::asio::detail::service_base<openssl_context_service>
+{
+public:
+ // The native type of the context.
+ typedef ::SSL_CTX* impl_type;
+
+ // The type for the password callback function object.
+ typedef boost::function<std::string(std::size_t,
+ context_base::password_purpose)> password_callback_type;
+
+ // Constructor.
+ openssl_context_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<openssl_context_service>(io_service)
+ {
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ // Return a null context implementation.
+ static impl_type null()
+ {
+ return 0;
+ }
+
+ // Create a new context implementation.
+ void create(impl_type& impl, context_base::method m)
+ {
+ ::SSL_METHOD* ssl_method = 0;
+ switch (m)
+ {
+ case context_base::sslv2:
+ ssl_method = ::SSLv2_method();
+ break;
+ case context_base::sslv2_client:
+ ssl_method = ::SSLv2_client_method();
+ break;
+ case context_base::sslv2_server:
+ ssl_method = ::SSLv2_server_method();
+ break;
+ case context_base::sslv3:
+ ssl_method = ::SSLv3_method();
+ break;
+ case context_base::sslv3_client:
+ ssl_method = ::SSLv3_client_method();
+ break;
+ case context_base::sslv3_server:
+ ssl_method = ::SSLv3_server_method();
+ break;
+ case context_base::tlsv1:
+ ssl_method = ::TLSv1_method();
+ break;
+ case context_base::tlsv1_client:
+ ssl_method = ::TLSv1_client_method();
+ break;
+ case context_base::tlsv1_server:
+ ssl_method = ::TLSv1_server_method();
+ break;
+ case context_base::sslv23:
+ ssl_method = ::SSLv23_method();
+ break;
+ case context_base::sslv23_client:
+ ssl_method = ::SSLv23_client_method();
+ break;
+ case context_base::sslv23_server:
+ ssl_method = ::SSLv23_server_method();
+ break;
+ default:
+ break;
+ }
+ impl = ::SSL_CTX_new(ssl_method);
+ }
+
+ // Destroy a context implementation.
+ void destroy(impl_type& impl)
+ {
+ if (impl != null())
+ {
+ if (impl->default_passwd_callback_userdata)
+ {
+ password_callback_type* callback =
+ static_cast<password_callback_type*>(
+ impl->default_passwd_callback_userdata);
+ delete callback;
+ impl->default_passwd_callback_userdata = 0;
+ }
+
+ ::SSL_CTX_free(impl);
+ impl = null();
+ }
+ }
+
+ // Set options on the context.
+ boost::system::error_code set_options(impl_type& impl,
+ context_base::options o, boost::system::error_code& ec)
+ {
+ ::SSL_CTX_set_options(impl, o);
+
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Set peer verification mode.
+ boost::system::error_code set_verify_mode(impl_type& impl,
+ context_base::verify_mode v, boost::system::error_code& ec)
+ {
+ ::SSL_CTX_set_verify(impl, v, 0);
+
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Load a certification authority file for performing verification.
+ boost::system::error_code load_verify_file(impl_type& impl,
+ const std::string& filename, boost::system::error_code& ec)
+ {
+ if (::SSL_CTX_load_verify_locations(impl, filename.c_str(), 0) != 1)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Add a directory containing certification authority files to be used for
+ // performing verification.
+ boost::system::error_code add_verify_path(impl_type& impl,
+ const std::string& path, boost::system::error_code& ec)
+ {
+ if (::SSL_CTX_load_verify_locations(impl, 0, path.c_str()) != 1)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Use a certificate from a file.
+ boost::system::error_code use_certificate_file(impl_type& impl,
+ const std::string& filename, context_base::file_format format,
+ boost::system::error_code& ec)
+ {
+ int file_type;
+ switch (format)
+ {
+ case context_base::asn1:
+ file_type = SSL_FILETYPE_ASN1;
+ break;
+ case context_base::pem:
+ file_type = SSL_FILETYPE_PEM;
+ break;
+ default:
+ {
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+ }
+
+ if (::SSL_CTX_use_certificate_file(impl, filename.c_str(), file_type) != 1)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Use a certificate chain from a file.
+ boost::system::error_code use_certificate_chain_file(impl_type& impl,
+ const std::string& filename, boost::system::error_code& ec)
+ {
+ if (::SSL_CTX_use_certificate_chain_file(impl, filename.c_str()) != 1)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Use a private key from a file.
+ boost::system::error_code use_private_key_file(impl_type& impl,
+ const std::string& filename, context_base::file_format format,
+ boost::system::error_code& ec)
+ {
+ int file_type;
+ switch (format)
+ {
+ case context_base::asn1:
+ file_type = SSL_FILETYPE_ASN1;
+ break;
+ case context_base::pem:
+ file_type = SSL_FILETYPE_PEM;
+ break;
+ default:
+ {
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+ }
+
+ if (::SSL_CTX_use_PrivateKey_file(impl, filename.c_str(), file_type) != 1)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Use an RSA private key from a file.
+ boost::system::error_code use_rsa_private_key_file(impl_type& impl,
+ const std::string& filename, context_base::file_format format,
+ boost::system::error_code& ec)
+ {
+ int file_type;
+ switch (format)
+ {
+ case context_base::asn1:
+ file_type = SSL_FILETYPE_ASN1;
+ break;
+ case context_base::pem:
+ file_type = SSL_FILETYPE_PEM;
+ break;
+ default:
+ {
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+ }
+
+ if (::SSL_CTX_use_RSAPrivateKey_file(
+ impl, filename.c_str(), file_type) != 1)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Use the specified file to obtain the temporary Diffie-Hellman parameters.
+ boost::system::error_code use_tmp_dh_file(impl_type& impl,
+ const std::string& filename, boost::system::error_code& ec)
+ {
+ ::BIO* bio = ::BIO_new_file(filename.c_str(), "r");
+ if (!bio)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+
+ ::DH* dh = ::PEM_read_bio_DHparams(bio, 0, 0, 0);
+ if (!dh)
+ {
+ ::BIO_free(bio);
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+
+ ::BIO_free(bio);
+ int result = ::SSL_CTX_set_tmp_dh(impl, dh);
+ if (result != 1)
+ {
+ ::DH_free(dh);
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ static int password_callback(char* buf, int size, int purpose, void* data)
+ {
+ using namespace std; // For strncat and strlen.
+
+ if (data)
+ {
+ password_callback_type* callback =
+ static_cast<password_callback_type*>(data);
+ std::string passwd = (*callback)(static_cast<std::size_t>(size),
+ purpose ? context_base::for_writing : context_base::for_reading);
+ *buf = '\0';
+ strncat(buf, passwd.c_str(), size);
+ return strlen(buf);
+ }
+
+ return 0;
+ }
+
+ // Set the password callback.
+ template <typename Password_Callback>
+ boost::system::error_code set_password_callback(impl_type& impl,
+ Password_Callback callback, boost::system::error_code& ec)
+ {
+ // Allocate callback function object if not already present.
+ if (impl->default_passwd_callback_userdata)
+ {
+ password_callback_type* callback_function =
+ static_cast<password_callback_type*>(
+ impl->default_passwd_callback_userdata);
+ *callback_function = callback;
+ }
+ else
+ {
+ password_callback_type* callback_function =
+ new password_callback_type(callback);
+ impl->default_passwd_callback_userdata = callback_function;
+ }
+
+ // Set the password callback.
+ SSL_CTX_set_default_passwd_cb(impl,
+ &openssl_context_service::password_callback);
+
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+private:
+ // Ensure openssl is initialised.
+ openssl_init<> init_;
+};
+
+} // namespace detail
+} // namespace ssl
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SSL_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ssl/detail/openssl_init.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ssl/detail/openssl_init.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,145 @@
+//
+// openssl_init.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
+// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_SSL_DETAIL_OPENSSL_INIT_HPP
+#define BOOST_ASIO_SSL_DETAIL_OPENSSL_INIT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <vector>
+#include <boost/assert.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/tss_ptr.hpp>
+#include <boost/asio/ssl/detail/openssl_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace ssl {
+namespace detail {
+
+template <bool Do_Init = true>
+class openssl_init
+ : private boost::noncopyable
+{
+private:
+ // Structure to perform the actual initialisation.
+ class do_init
+ {
+ public:
+ do_init()
+ {
+ if (Do_Init)
+ {
+ ::SSL_library_init();
+ ::SSL_load_error_strings();
+ ::OpenSSL_add_ssl_algorithms();
+
+ mutexes_.resize(::CRYPTO_num_locks());
+ for (size_t i = 0; i < mutexes_.size(); ++i)
+ mutexes_[i].reset(new boost::asio::detail::mutex);
+ ::CRYPTO_set_locking_callback(&do_init::openssl_locking_func);
+ ::CRYPTO_set_id_callback(&do_init::openssl_id_func);
+ }
+ }
+
+ ~do_init()
+ {
+ if (Do_Init)
+ {
+ ::CRYPTO_set_id_callback(0);
+ ::CRYPTO_set_locking_callback(0);
+ ::ERR_free_strings();
+ ::ERR_remove_state(0);
+ ::EVP_cleanup();
+ ::CRYPTO_cleanup_all_ex_data();
+ ::CONF_modules_unload(1);
+ ::ENGINE_cleanup();
+ }
+ }
+
+ // Helper function to manage a do_init singleton. The static instance of the
+ // openssl_init object ensures that this function is always called before
+ // main, and therefore before any other threads can get started. The do_init
+ // instance must be static in this function to ensure that it gets
+ // initialised before any other global objects try to use it.
+ static boost::shared_ptr<do_init> instance()
+ {
+ static boost::shared_ptr<do_init> init(new do_init);
+ return init;
+ }
+
+ private:
+ static unsigned long openssl_id_func()
+ {
+ void* id = instance()->thread_id_;
+ if (id == 0)
+ instance()->thread_id_ = id = &id; // Ugh.
+ BOOST_ASSERT(sizeof(unsigned long) >= sizeof(void*));
+ return reinterpret_cast<unsigned long>(id);
+ }
+
+ static void openssl_locking_func(int mode, int n,
+ const char *file, int line)
+ {
+ if (mode & CRYPTO_LOCK)
+ instance()->mutexes_[n]->lock();
+ else
+ instance()->mutexes_[n]->unlock();
+ }
+
+ // Mutexes to be used in locking callbacks.
+ std::vector<boost::shared_ptr<boost::asio::detail::mutex> > mutexes_;
+
+ // The thread identifiers to be used by openssl.
+ boost::asio::detail::tss_ptr<void> thread_id_;
+ };
+
+public:
+ // Constructor.
+ openssl_init()
+ : ref_(do_init::instance())
+ {
+ while (&instance_ == 0); // Ensure openssl_init::instance_ is linked in.
+ }
+
+ // Destructor.
+ ~openssl_init()
+ {
+ }
+
+private:
+ // Instance to force initialisation of openssl at global scope.
+ static openssl_init instance_;
+
+ // Reference to singleton do_init object to ensure that openssl does not get
+ // cleaned up until the last user has finished with it.
+ boost::shared_ptr<do_init> ref_;
+};
+
+template <bool Do_Init>
+openssl_init<Do_Init> openssl_init<Do_Init>::instance_;
+
+} // namespace detail
+} // namespace ssl
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SSL_DETAIL_OPENSSL_INIT_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ssl/detail/openssl_operation.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ssl/detail/openssl_operation.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,518 @@
+//
+// openssl_operation.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
+//
+// Distributed under the 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 BOOST_ASIO_SSL_DETAIL_OPENSSL_OPERATION_HPP
+#define BOOST_ASIO_SSL_DETAIL_OPENSSL_OPERATION_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/function.hpp>
+#include <boost/assert.hpp>
+#include <boost/bind.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/placeholders.hpp>
+#include <boost/asio/write.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/ssl/detail/openssl_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace ssl {
+namespace detail {
+
+typedef boost::function<int (::SSL*)> ssl_primitive_func;
+typedef boost::function<void (const boost::system::error_code&, int)>
+ user_handler_func;
+
+// Network send_/recv buffer implementation
+//
+//
+class net_buffer
+{
+ static const int NET_BUF_SIZE = 16*1024 + 256; // SSL record size + spare
+
+ unsigned char buf_[NET_BUF_SIZE];
+ unsigned char* data_start_;
+ unsigned char* data_end_;
+
+public:
+ net_buffer()
+ {
+ data_start_ = data_end_ = buf_;
+ }
+ unsigned char* get_unused_start() { return data_end_; }
+ unsigned char* get_data_start() { return data_start_; }
+ size_t get_unused_len() { return (NET_BUF_SIZE - (data_end_ - buf_)); }
+ size_t get_data_len() { return (data_end_ - data_start_); }
+ void data_added(size_t count)
+ {
+ data_end_ += count;
+ data_end_ = data_end_ > (buf_ + NET_BUF_SIZE)?
+ (buf_ + NET_BUF_SIZE):
+ data_end_;
+ }
+ void data_removed(size_t count)
+ {
+ data_start_ += count;
+ if (data_start_ >= data_end_) reset();
+ }
+ void reset() { data_start_ = buf_; data_end_ = buf_; }
+ bool has_data() { return (data_start_ < data_end_); }
+}; // class net_buffer
+
+//
+// Operation class
+//
+//
+template <typename Stream>
+class openssl_operation
+{
+public:
+
+ // Constructor for asynchronous operations
+ openssl_operation(ssl_primitive_func primitive,
+ Stream& socket,
+ net_buffer& recv_buf,
+ SSL* session,
+ BIO* ssl_bio,
+ user_handler_func handler,
+ boost::asio::io_service::strand& strand
+ )
+ : primitive_(primitive)
+ , user_handler_(handler)
+ , strand_(&strand)
+ , recv_buf_(recv_buf)
+ , socket_(socket)
+ , ssl_bio_(ssl_bio)
+ , session_(session)
+ {
+ write_ = boost::bind(
+ &openssl_operation::do_async_write,
+ this, boost::arg<1>(), boost::arg<2>()
+ );
+ read_ = boost::bind(
+ &openssl_operation::do_async_read,
+ this
+ );
+ handler_= boost::bind(
+ &openssl_operation::async_user_handler,
+ this, boost::arg<1>(), boost::arg<2>()
+ );
+ }
+
+ // Constructor for synchronous operations
+ openssl_operation(ssl_primitive_func primitive,
+ Stream& socket,
+ net_buffer& recv_buf,
+ SSL* session,
+ BIO* ssl_bio)
+ : primitive_(primitive)
+ , strand_(0)
+ , recv_buf_(recv_buf)
+ , socket_(socket)
+ , ssl_bio_(ssl_bio)
+ , session_(session)
+ {
+ write_ = boost::bind(
+ &openssl_operation::do_sync_write,
+ this, boost::arg<1>(), boost::arg<2>()
+ );
+ read_ = boost::bind(
+ &openssl_operation::do_sync_read,
+ this
+ );
+ handler_ = boost::bind(
+ &openssl_operation::sync_user_handler,
+ this, boost::arg<1>(), boost::arg<2>()
+ );
+ }
+
+ // Start operation
+ // In case of asynchronous it returns 0, in sync mode returns success code
+ // or throws an error...
+ int start()
+ {
+ int rc = primitive_( session_ );
+
+ bool is_operation_done = (rc > 0);
+ // For connect/accept/shutdown, the operation
+ // is done, when return code is 1
+ // for write, it is done, when is retcode > 0
+ // for read, is is done when retcode > 0
+
+ int error_code = !is_operation_done ?
+ ::SSL_get_error( session_, rc ) :
+ 0;
+ int sys_error_code = ERR_get_error();
+
+ bool is_read_needed = (error_code == SSL_ERROR_WANT_READ);
+ bool is_write_needed = (error_code == SSL_ERROR_WANT_WRITE ||
+ ::BIO_ctrl_pending( ssl_bio_ ));
+ bool is_shut_down_received =
+ ((::SSL_get_shutdown( session_ ) & SSL_RECEIVED_SHUTDOWN) ==
+ SSL_RECEIVED_SHUTDOWN);
+ bool is_shut_down_sent =
+ ((::SSL_get_shutdown( session_ ) & SSL_SENT_SHUTDOWN) ==
+ SSL_SENT_SHUTDOWN);
+
+ if (is_shut_down_sent && is_shut_down_received && is_operation_done && !is_write_needed)
+ // SSL connection is shut down cleanly
+ return handler_(boost::system::error_code(), 1);
+
+ if (is_shut_down_received && !is_operation_done)
+ // Shutdown has been requested, while we were reading or writing...
+ // abort our action...
+ return handler_(boost::asio::error::shut_down, 0);
+
+ if (!is_operation_done && !is_read_needed && !is_write_needed
+ && !is_shut_down_sent)
+ {
+ // The operation has failed... It is not completed and does
+ // not want network communication nor does want to send shutdown out...
+ if (error_code == SSL_ERROR_SYSCALL)
+ {
+ return handler_(boost::system::error_code(
+ sys_error_code, boost::asio::error::system_category), rc);
+ }
+ else
+ {
+ return handler_(boost::system::error_code(
+ error_code, boost::asio::error::get_ssl_category()), rc);
+ }
+ }
+
+ if (!is_operation_done && !is_write_needed)
+ {
+ // We may have left over data that we can pass to SSL immediately
+ if (recv_buf_.get_data_len() > 0)
+ {
+ // Pass the buffered data to SSL
+ int written = ::BIO_write
+ (
+ ssl_bio_,
+ recv_buf_.get_data_start(),
+ recv_buf_.get_data_len()
+ );
+
+ if (written > 0)
+ {
+ recv_buf_.data_removed(written);
+ }
+ else if (written < 0)
+ {
+ if (!BIO_should_retry(ssl_bio_))
+ {
+ // Some serios error with BIO....
+ return handler_(boost::asio::error::no_recovery, 0);
+ }
+ }
+
+ return start();
+ }
+ else if (is_read_needed || (is_shut_down_sent && !is_shut_down_received))
+ {
+ return read_();
+ }
+ }
+
+ // Continue with operation, flush any SSL data out to network...
+ return write_(is_operation_done, rc);
+ }
+
+// Private implementation
+private:
+ typedef boost::function<int (const boost::system::error_code&, int)>
+ int_handler_func;
+ typedef boost::function<int (bool, int)> write_func;
+ typedef boost::function<int ()> read_func;
+
+ ssl_primitive_func primitive_;
+ user_handler_func user_handler_;
+ boost::asio::io_service::strand* strand_;
+ write_func write_;
+ read_func read_;
+ int_handler_func handler_;
+
+ net_buffer send_buf_; // buffers for network IO
+
+ // The recv buffer is owned by the stream, not the operation, since there can
+ // be left over bytes after passing the data up to the application, and these
+ // bytes need to be kept around for the next read operation issued by the
+ // application.
+ net_buffer& recv_buf_;
+
+ Stream& socket_;
+ BIO* ssl_bio_;
+ SSL* session_;
+
+ //
+ int sync_user_handler(const boost::system::error_code& error, int rc)
+ {
+ if (!error)
+ return rc;
+
+ throw boost::system::system_error(error);
+ }
+
+ int async_user_handler(boost::system::error_code error, int rc)
+ {
+ if (rc < 0)
+ {
+ if (!error)
+ error = boost::asio::error::no_recovery;
+ rc = 0;
+ }
+
+ user_handler_(error, rc);
+ return 0;
+ }
+
+ // Writes bytes asynchronously from SSL to NET
+ int do_async_write(bool is_operation_done, int rc)
+ {
+ int len = ::BIO_ctrl_pending( ssl_bio_ );
+ if ( len )
+ {
+ // There is something to write into net, do it...
+ len = (int)send_buf_.get_unused_len() > len?
+ len:
+ send_buf_.get_unused_len();
+
+ if (len == 0)
+ {
+ // In case our send buffer is full, we have just to wait until
+ // previous send to complete...
+ return 0;
+ }
+
+ // Read outgoing data from bio
+ len = ::BIO_read( ssl_bio_, send_buf_.get_unused_start(), len);
+
+ if (len > 0)
+ {
+ unsigned char *data_start = send_buf_.get_unused_start();
+ send_buf_.data_added(len);
+
+ BOOST_ASSERT(strand_);
+ boost::asio::async_write
+ (
+ socket_,
+ boost::asio::buffer(data_start, len),
+ strand_->wrap
+ (
+ boost::bind
+ (
+ &openssl_operation::async_write_handler,
+ this,
+ is_operation_done,
+ rc,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred
+ )
+ )
+ );
+
+ return 0;
+ }
+ else if (!BIO_should_retry(ssl_bio_))
+ {
+ // Seems like fatal error
+ // reading from SSL BIO has failed...
+ handler_(boost::asio::error::no_recovery, 0);
+ return 0;
+ }
+ }
+
+ if (is_operation_done)
+ {
+ // Finish the operation, with success
+ handler_(boost::system::error_code(), rc);
+ return 0;
+ }
+
+ // OPeration is not done and writing to net has been made...
+ // start operation again
+ start();
+
+ return 0;
+ }
+
+ void async_write_handler(bool is_operation_done, int rc,
+ const boost::system::error_code& error, size_t bytes_sent)
+ {
+ if (!error)
+ {
+ // Remove data from send buffer
+ send_buf_.data_removed(bytes_sent);
+
+ if (is_operation_done)
+ handler_(boost::system::error_code(), rc);
+ else
+ // Since the operation was not completed, try it again...
+ start();
+ }
+ else
+ handler_(error, rc);
+ }
+
+ int do_async_read()
+ {
+ // Wait for new data
+ BOOST_ASSERT(strand_);
+ socket_.async_read_some
+ (
+ boost::asio::buffer(recv_buf_.get_unused_start(),
+ recv_buf_.get_unused_len()),
+ strand_->wrap
+ (
+ boost::bind
+ (
+ &openssl_operation::async_read_handler,
+ this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred
+ )
+ )
+ );
+ return 0;
+ }
+
+ void async_read_handler(const boost::system::error_code& error,
+ size_t bytes_recvd)
+ {
+ if (!error)
+ {
+ recv_buf_.data_added(bytes_recvd);
+
+ // Pass the received data to SSL
+ int written = ::BIO_write
+ (
+ ssl_bio_,
+ recv_buf_.get_data_start(),
+ recv_buf_.get_data_len()
+ );
+
+ if (written > 0)
+ {
+ recv_buf_.data_removed(written);
+ }
+ else if (written < 0)
+ {
+ if (!BIO_should_retry(ssl_bio_))
+ {
+ // Some serios error with BIO....
+ handler_(boost::asio::error::no_recovery, 0);
+ return;
+ }
+ }
+
+ // and try the SSL primitive again
+ start();
+ }
+ else
+ {
+ // Error in network level...
+ // SSL can't continue either...
+ handler_(error, 0);
+ }
+ }
+
+ // Syncronous functions...
+ int do_sync_write(bool is_operation_done, int rc)
+ {
+ int len = ::BIO_ctrl_pending( ssl_bio_ );
+ if ( len )
+ {
+ // There is something to write into net, do it...
+ len = (int)send_buf_.get_unused_len() > len?
+ len:
+ send_buf_.get_unused_len();
+
+ // Read outgoing data from bio
+ len = ::BIO_read( ssl_bio_, send_buf_.get_unused_start(), len);
+
+ if (len > 0)
+ {
+ size_t sent_len = boost::asio::write(
+ socket_,
+ boost::asio::buffer(send_buf_.get_unused_start(), len)
+ );
+
+ send_buf_.data_added(len);
+ send_buf_.data_removed(sent_len);
+ }
+ else if (!BIO_should_retry(ssl_bio_))
+ {
+ // Seems like fatal error
+ // reading from SSL BIO has failed...
+ throw boost::system::system_error(boost::asio::error::no_recovery);
+ }
+ }
+
+ if (is_operation_done)
+ // Finish the operation, with success
+ return rc;
+
+ // Operation is not finished, start again.
+ return start();
+ }
+
+ int do_sync_read()
+ {
+ size_t len = socket_.read_some
+ (
+ boost::asio::buffer(recv_buf_.get_unused_start(),
+ recv_buf_.get_unused_len())
+ );
+
+ // Write data to ssl
+ recv_buf_.data_added(len);
+
+ // Pass the received data to SSL
+ int written = ::BIO_write
+ (
+ ssl_bio_,
+ recv_buf_.get_data_start(),
+ recv_buf_.get_data_len()
+ );
+
+ if (written > 0)
+ {
+ recv_buf_.data_removed(written);
+ }
+ else if (written < 0)
+ {
+ if (!BIO_should_retry(ssl_bio_))
+ {
+ // Some serios error with BIO....
+ throw boost::system::system_error(boost::asio::error::no_recovery);
+ }
+ }
+
+ // Try the operation again
+ return start();
+ }
+}; // class openssl_operation
+
+} // namespace detail
+} // namespace ssl
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SSL_DETAIL_OPENSSL_OPERATION_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ssl/detail/openssl_stream_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ssl/detail/openssl_stream_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,533 @@
+//
+// stream_service.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
+// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_SSL_DETAIL_OPENSSL_STREAM_SERVICE_HPP
+#define BOOST_ASIO_SSL_DETAIL_OPENSSL_STREAM_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <climits>
+#include <boost/config.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/function.hpp>
+#include <boost/bind.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/ssl/basic_context.hpp>
+#include <boost/asio/ssl/stream_base.hpp>
+#include <boost/asio/ssl/detail/openssl_operation.hpp>
+#include <boost/asio/ssl/detail/openssl_types.hpp>
+
+namespace boost {
+namespace asio {
+namespace ssl {
+namespace detail {
+
+class openssl_stream_service
+ : public boost::asio::detail::service_base<openssl_stream_service>
+{
+private:
+ enum { max_buffer_size = INT_MAX };
+
+ //Base handler for asyncrhonous operations
+ template <typename Stream>
+ class base_handler
+ {
+ public:
+ typedef boost::function<
+ void (const boost::system::error_code&, size_t)> func_t;
+
+ base_handler(boost::asio::io_service& io_service)
+ : op_(NULL)
+ , io_service_(io_service)
+ , work_(io_service)
+ {}
+
+ void do_func(const boost::system::error_code& error, size_t size)
+ {
+ func_(error, size);
+ }
+
+ void set_operation(openssl_operation<Stream>* op) { op_ = op; }
+ void set_func(func_t func) { func_ = func; }
+
+ ~base_handler()
+ {
+ delete op_;
+ }
+
+ private:
+ func_t func_;
+ openssl_operation<Stream>* op_;
+ boost::asio::io_service& io_service_;
+ boost::asio::io_service::work work_;
+ }; // class base_handler
+
+ // Handler for asynchronous IO (write/read) operations
+ template<typename Stream, typename Handler>
+ class io_handler
+ : public base_handler<Stream>
+ {
+ public:
+ io_handler(Handler handler, boost::asio::io_service& io_service)
+ : base_handler<Stream>(io_service)
+ , handler_(handler)
+ {
+ set_func(boost::bind(
+ &io_handler<Stream, Handler>::handler_impl,
+ this, boost::arg<1>(), boost::arg<2>() ));
+ }
+
+ private:
+ Handler handler_;
+ void handler_impl(const boost::system::error_code& error, size_t size)
+ {
+ handler_(error, size);
+ delete this;
+ }
+ }; // class io_handler
+
+ // Handler for asyncrhonous handshake (connect, accept) functions
+ template <typename Stream, typename Handler>
+ class handshake_handler
+ : public base_handler<Stream>
+ {
+ public:
+ handshake_handler(Handler handler, boost::asio::io_service& io_service)
+ : base_handler<Stream>(io_service)
+ , handler_(handler)
+ {
+ set_func(boost::bind(
+ &handshake_handler<Stream, Handler>::handler_impl,
+ this, boost::arg<1>(), boost::arg<2>() ));
+ }
+
+ private:
+ Handler handler_;
+ void handler_impl(const boost::system::error_code& error, size_t)
+ {
+ handler_(error);
+ delete this;
+ }
+
+ }; // class handshake_handler
+
+ // Handler for asyncrhonous shutdown
+ template <typename Stream, typename Handler>
+ class shutdown_handler
+ : public base_handler<Stream>
+ {
+ public:
+ shutdown_handler(Handler handler, boost::asio::io_service& io_service)
+ : base_handler<Stream>(io_service),
+ handler_(handler)
+ {
+ set_func(boost::bind(
+ &shutdown_handler<Stream, Handler>::handler_impl,
+ this, boost::arg<1>(), boost::arg<2>() ));
+ }
+
+ private:
+ Handler handler_;
+ void handler_impl(const boost::system::error_code& error, size_t)
+ {
+ handler_(error);
+ delete this;
+ }
+ }; // class shutdown_handler
+
+public:
+ // The implementation type.
+ typedef struct impl_struct
+ {
+ ::SSL* ssl;
+ ::BIO* ext_bio;
+ net_buffer recv_buf;
+ } * impl_type;
+
+ // Construct a new stream socket service for the specified io_service.
+ explicit openssl_stream_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<openssl_stream_service>(io_service),
+ strand_(io_service)
+ {
+ }
+
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ // Return a null stream implementation.
+ impl_type null() const
+ {
+ return 0;
+ }
+
+ // Create a new stream implementation.
+ template <typename Stream, typename Context_Service>
+ void create(impl_type& impl, Stream& next_layer,
+ basic_context<Context_Service>& context)
+ {
+ impl = new impl_struct;
+ impl->ssl = ::SSL_new(context.impl());
+ ::SSL_set_mode(impl->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
+ ::SSL_set_mode(impl->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+ ::BIO* int_bio = 0;
+ impl->ext_bio = 0;
+ ::BIO_new_bio_pair(&int_bio, 8192, &impl->ext_bio, 8192);
+ ::SSL_set_bio(impl->ssl, int_bio, int_bio);
+ }
+
+ // Destroy a stream implementation.
+ template <typename Stream>
+ void destroy(impl_type& impl, Stream& next_layer)
+ {
+ if (impl != 0)
+ {
+ ::BIO_free(impl->ext_bio);
+ ::SSL_free(impl->ssl);
+ delete impl;
+ impl = 0;
+ }
+ }
+
+ // Perform SSL handshaking.
+ template <typename Stream>
+ boost::system::error_code handshake(impl_type& impl, Stream& next_layer,
+ stream_base::handshake_type type, boost::system::error_code& ec)
+ {
+ try
+ {
+ openssl_operation<Stream> op(
+ type == stream_base::client ?
+ &ssl_wrap<mutex_type>::SSL_connect:
+ &ssl_wrap<mutex_type>::SSL_accept,
+ next_layer,
+ impl->recv_buf,
+ impl->ssl,
+ impl->ext_bio);
+ op.start();
+ }
+ catch (boost::system::system_error& e)
+ {
+ ec = e.code();
+ return ec;
+ }
+
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Start an asynchronous SSL handshake.
+ template <typename Stream, typename Handler>
+ void async_handshake(impl_type& impl, Stream& next_layer,
+ stream_base::handshake_type type, Handler handler)
+ {
+ typedef handshake_handler<Stream, Handler> connect_handler;
+
+ connect_handler* local_handler =
+ new connect_handler(handler, get_io_service());
+
+ openssl_operation<Stream>* op = new openssl_operation<Stream>
+ (
+ type == stream_base::client ?
+ &ssl_wrap<mutex_type>::SSL_connect:
+ &ssl_wrap<mutex_type>::SSL_accept,
+ next_layer,
+ impl->recv_buf,
+ impl->ssl,
+ impl->ext_bio,
+ boost::bind
+ (
+ &base_handler<Stream>::do_func,
+ local_handler,
+ boost::arg<1>(),
+ boost::arg<2>()
+ ),
+ strand_
+ );
+ local_handler->set_operation(op);
+
+ strand_.post(boost::bind(&openssl_operation<Stream>::start, op));
+ }
+
+ // Shut down SSL on the stream.
+ template <typename Stream>
+ boost::system::error_code shutdown(impl_type& impl, Stream& next_layer,
+ boost::system::error_code& ec)
+ {
+ try
+ {
+ openssl_operation<Stream> op(
+ &ssl_wrap<mutex_type>::SSL_shutdown,
+ next_layer,
+ impl->recv_buf,
+ impl->ssl,
+ impl->ext_bio);
+ op.start();
+ }
+ catch (boost::system::system_error& e)
+ {
+ ec = e.code();
+ return ec;
+ }
+
+ ec = boost::system::error_code();
+ return ec;
+ }
+
+ // Asynchronously shut down SSL on the stream.
+ template <typename Stream, typename Handler>
+ void async_shutdown(impl_type& impl, Stream& next_layer, Handler handler)
+ {
+ typedef shutdown_handler<Stream, Handler> disconnect_handler;
+
+ disconnect_handler* local_handler =
+ new disconnect_handler(handler, get_io_service());
+
+ openssl_operation<Stream>* op = new openssl_operation<Stream>
+ (
+ &ssl_wrap<mutex_type>::SSL_shutdown,
+ next_layer,
+ impl->recv_buf,
+ impl->ssl,
+ impl->ext_bio,
+ boost::bind
+ (
+ &base_handler<Stream>::do_func,
+ local_handler,
+ boost::arg<1>(),
+ boost::arg<2>()
+ ),
+ strand_
+ );
+ local_handler->set_operation(op);
+
+ strand_.post(boost::bind(&openssl_operation<Stream>::start, op));
+ }
+
+ // Write some data to the stream.
+ template <typename Stream, typename Const_Buffers>
+ std::size_t write_some(impl_type& impl, Stream& next_layer,
+ const Const_Buffers& buffers, boost::system::error_code& ec)
+ {
+ size_t bytes_transferred = 0;
+ try
+ {
+ std::size_t buffer_size = boost::asio::buffer_size(*buffers.begin());
+ if (buffer_size > max_buffer_size)
+ buffer_size = max_buffer_size;
+
+ boost::function<int (SSL*)> send_func =
+ boost::bind(&::SSL_write, boost::arg<1>(),
+ boost::asio::buffer_cast<const void*>(*buffers.begin()),
+ static_cast<int>(buffer_size));
+ openssl_operation<Stream> op(
+ send_func,
+ next_layer,
+ impl->recv_buf,
+ impl->ssl,
+ impl->ext_bio
+ );
+ bytes_transferred = static_cast<size_t>(op.start());
+ }
+ catch (boost::system::system_error& e)
+ {
+ ec = e.code();
+ return 0;
+ }
+
+ ec = boost::system::error_code();
+ return bytes_transferred;
+ }
+
+ // Start an asynchronous write.
+ template <typename Stream, typename Const_Buffers, typename Handler>
+ void async_write_some(impl_type& impl, Stream& next_layer,
+ const Const_Buffers& buffers, Handler handler)
+ {
+ typedef io_handler<Stream, Handler> send_handler;
+
+ send_handler* local_handler = new send_handler(handler, get_io_service());
+
+ std::size_t buffer_size = boost::asio::buffer_size(*buffers.begin());
+ if (buffer_size > max_buffer_size)
+ buffer_size = max_buffer_size;
+
+ boost::function<int (SSL*)> send_func =
+ boost::bind(&::SSL_write, boost::arg<1>(),
+ boost::asio::buffer_cast<const void*>(*buffers.begin()),
+ static_cast<int>(buffer_size));
+
+ openssl_operation<Stream>* op = new openssl_operation<Stream>
+ (
+ send_func,
+ next_layer,
+ impl->recv_buf,
+ impl->ssl,
+ impl->ext_bio,
+ boost::bind
+ (
+ &base_handler<Stream>::do_func,
+ local_handler,
+ boost::arg<1>(),
+ boost::arg<2>()
+ ),
+ strand_
+ );
+ local_handler->set_operation(op);
+
+ strand_.post(boost::bind(&openssl_operation<Stream>::start, op));
+ }
+
+ // Read some data from the stream.
+ template <typename Stream, typename Mutable_Buffers>
+ std::size_t read_some(impl_type& impl, Stream& next_layer,
+ const Mutable_Buffers& buffers, boost::system::error_code& ec)
+ {
+ size_t bytes_transferred = 0;
+ try
+ {
+ std::size_t buffer_size = boost::asio::buffer_size(*buffers.begin());
+ if (buffer_size > max_buffer_size)
+ buffer_size = max_buffer_size;
+
+ boost::function<int (SSL*)> recv_func =
+ boost::bind(&::SSL_read, boost::arg<1>(),
+ boost::asio::buffer_cast<void*>(*buffers.begin()),
+ static_cast<int>(buffer_size));
+ openssl_operation<Stream> op(recv_func,
+ next_layer,
+ impl->recv_buf,
+ impl->ssl,
+ impl->ext_bio
+ );
+
+ bytes_transferred = static_cast<size_t>(op.start());
+ }
+ catch (boost::system::system_error& e)
+ {
+ ec = e.code();
+ return 0;
+ }
+
+ ec = boost::system::error_code();
+ return bytes_transferred;
+ }
+
+ // Start an asynchronous read.
+ template <typename Stream, typename Mutable_Buffers, typename Handler>
+ void async_read_some(impl_type& impl, Stream& next_layer,
+ const Mutable_Buffers& buffers, Handler handler)
+ {
+ typedef io_handler<Stream, Handler> recv_handler;
+
+ recv_handler* local_handler = new recv_handler(handler, get_io_service());
+
+ std::size_t buffer_size = boost::asio::buffer_size(*buffers.begin());
+ if (buffer_size > max_buffer_size)
+ buffer_size = max_buffer_size;
+
+ boost::function<int (SSL*)> recv_func =
+ boost::bind(&::SSL_read, boost::arg<1>(),
+ boost::asio::buffer_cast<void*>(*buffers.begin()),
+ static_cast<int>(buffer_size));
+
+ openssl_operation<Stream>* op = new openssl_operation<Stream>
+ (
+ recv_func,
+ next_layer,
+ impl->recv_buf,
+ impl->ssl,
+ impl->ext_bio,
+ boost::bind
+ (
+ &base_handler<Stream>::do_func,
+ local_handler,
+ boost::arg<1>(),
+ boost::arg<2>()
+ ),
+ strand_
+ );
+ local_handler->set_operation(op);
+
+ strand_.post(boost::bind(&openssl_operation<Stream>::start, op));
+ }
+
+ // Peek at the incoming data on the stream.
+ template <typename Stream, typename Mutable_Buffers>
+ std::size_t peek(impl_type& impl, Stream& next_layer,
+ const Mutable_Buffers& buffers, boost::system::error_code& ec)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ // Determine the amount of data that may be read without blocking.
+ template <typename Stream>
+ std::size_t in_avail(impl_type& impl, Stream& next_layer,
+ boost::system::error_code& ec)
+ {
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+private:
+ boost::asio::io_service::strand strand_;
+
+ typedef boost::asio::detail::mutex mutex_type;
+
+ template<typename Mutex>
+ struct ssl_wrap
+ {
+ static Mutex ssl_mutex_;
+
+ static int SSL_accept(SSL *ssl)
+ {
+ typename Mutex::scoped_lock lock(ssl_mutex_);
+ return ::SSL_accept(ssl);
+ }
+
+ static int SSL_connect(SSL *ssl)
+ {
+ typename Mutex::scoped_lock lock(ssl_mutex_);
+ return ::SSL_connect(ssl);
+ }
+
+ static int SSL_shutdown(SSL *ssl)
+ {
+ typename Mutex::scoped_lock lock(ssl_mutex_);
+ return ::SSL_shutdown(ssl);
+ }
+ };
+};
+
+template<typename Mutex>
+Mutex openssl_stream_service::ssl_wrap<Mutex>::ssl_mutex_;
+
+} // namespace detail
+} // namespace ssl
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SSL_DETAIL_OPENSSL_STREAM_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ssl/detail/openssl_types.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ssl/detail/openssl_types.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,31 @@
+//
+// openssl_types.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP
+#define BOOST_ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <openssl/conf.h>
+#include <openssl/ssl.h>
+#include <openssl/engine.h>
+#include <openssl/err.h>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ssl/stream.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ssl/stream.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,505 @@
+//
+// stream.hpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
+// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_SSL_STREAM_HPP
+#define BOOST_ASIO_SSL_STREAM_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/type_traits.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/ssl/basic_context.hpp>
+#include <boost/asio/ssl/stream_base.hpp>
+#include <boost/asio/ssl/stream_service.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+namespace ssl {
+
+/// Provides stream-oriented functionality using SSL.
+/**
+ * The stream class template provides asynchronous and blocking stream-oriented
+ * functionality using SSL.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Example
+ * To use the SSL stream template with an ip::tcp::socket, you would write:
+ * @code
+ * boost::asio::io_service io_service;
+ * boost::asio::ssl::context context(io_service, boost::asio::ssl::context::sslv23);
+ * boost::asio::ssl::stream<boost::asio::ip::tcp::socket> sock(io_service, context);
+ * @endcode
+ *
+ * @par Concepts:
+ * AsyncReadStream, AsyncWriteStream, Stream, SyncRead_Stream, SyncWriteStream.
+ */
+template <typename Stream, typename Service = stream_service>
+class stream
+ : public stream_base,
+ private boost::noncopyable
+{
+public:
+ /// The type of the next layer.
+ typedef typename boost::remove_reference<Stream>::type next_layer_type;
+
+ /// The type of the lowest layer.
+ typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
+
+ /// The type of the service that will be used to provide stream operations.
+ typedef Service service_type;
+
+ /// The native implementation type of the stream.
+ typedef typename service_type::impl_type impl_type;
+
+ /// Construct a stream.
+ /**
+ * This constructor creates a stream and initialises the underlying stream
+ * object.
+ *
+ * @param arg The argument to be passed to initialise the underlying stream.
+ *
+ * @param context The SSL context to be used for the stream.
+ */
+ template <typename Arg, typename Context_Service>
+ explicit stream(Arg& arg, basic_context<Context_Service>& context)
+ : next_layer_(arg),
+ service_(boost::asio::use_service<Service>(next_layer_.get_io_service())),
+ impl_(service_.null())
+ {
+ service_.create(impl_, next_layer_, context);
+ }
+
+ /// Destructor.
+ ~stream()
+ {
+ service_.destroy(impl_, next_layer_);
+ }
+
+ /// (Deprecated: use get_io_service().) Get the io_service associated with
+ /// the object.
+ /**
+ * This function may be used to obtain the io_service object that the stream
+ * uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_service object that stream will use to
+ * dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_service& io_service()
+ {
+ return next_layer_.get_io_service();
+ }
+
+ /// Get the io_service associated with the object.
+ /**
+ * This function may be used to obtain the io_service object that the stream
+ * uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_service object that stream will use to
+ * dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_service& get_io_service()
+ {
+ return next_layer_.get_io_service();
+ }
+
+ /// Get a reference to the next layer.
+ /**
+ * This function returns a reference to the next layer in a stack of stream
+ * layers.
+ *
+ * @return A reference to the next layer in the stack of stream layers.
+ * Ownership is not transferred to the caller.
+ */
+ next_layer_type& next_layer()
+ {
+ return next_layer_;
+ }
+
+ /// Get a reference to the lowest layer.
+ /**
+ * This function returns a reference to the lowest layer in a stack of
+ * stream layers.
+ *
+ * @return A reference to the lowest layer in the stack of stream layers.
+ * Ownership is not transferred to the caller.
+ */
+ lowest_layer_type& lowest_layer()
+ {
+ return next_layer_.lowest_layer();
+ }
+
+ /// Get the underlying implementation in the native type.
+ /**
+ * This function may be used to obtain the underlying implementation of the
+ * context. This is intended to allow access to stream functionality that is
+ * not otherwise provided.
+ */
+ impl_type impl()
+ {
+ return impl_;
+ }
+
+ /// Perform SSL handshaking.
+ /**
+ * This function is used to perform SSL handshaking on the stream. The
+ * function call will block until handshaking is complete or an error occurs.
+ *
+ * @param type The type of handshaking to be performed, i.e. as a client or as
+ * a server.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void handshake(handshake_type type)
+ {
+ boost::system::error_code ec;
+ service_.handshake(impl_, next_layer_, type, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Perform SSL handshaking.
+ /**
+ * This function is used to perform SSL handshaking on the stream. The
+ * function call will block until handshaking is complete or an error occurs.
+ *
+ * @param type The type of handshaking to be performed, i.e. as a client or as
+ * a server.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code handshake(handshake_type type,
+ boost::system::error_code& ec)
+ {
+ return service_.handshake(impl_, next_layer_, type, ec);
+ }
+
+ /// Start an asynchronous SSL handshake.
+ /**
+ * This function is used to asynchronously perform an SSL handshake on the
+ * stream. This function call always returns immediately.
+ *
+ * @param type The type of handshaking to be performed, i.e. as a client or as
+ * a server.
+ *
+ * @param handler The handler to be called when the handshake operation
+ * completes. Copies will be made of the handler as required. The equivalent
+ * function signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation.
+ * ); @endcode
+ */
+ template <typename HandshakeHandler>
+ void async_handshake(handshake_type type, HandshakeHandler handler)
+ {
+ service_.async_handshake(impl_, next_layer_, type, handler);
+ }
+
+ /// Shut down SSL on the stream.
+ /**
+ * This function is used to shut down SSL on the stream. The function call
+ * will block until SSL has been shut down or an error occurs.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void shutdown()
+ {
+ boost::system::error_code ec;
+ service_.shutdown(impl_, next_layer_, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Shut down SSL on the stream.
+ /**
+ * This function is used to shut down SSL on the stream. The function call
+ * will block until SSL has been shut down or an error occurs.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code shutdown(boost::system::error_code& ec)
+ {
+ return service_.shutdown(impl_, next_layer_, ec);
+ }
+
+ /// Asynchronously shut down SSL on the stream.
+ /**
+ * This function is used to asynchronously shut down SSL on the stream. This
+ * function call always returns immediately.
+ *
+ * @param handler The handler to be called when the handshake operation
+ * completes. Copies will be made of the handler as required. The equivalent
+ * function signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error // Result of operation.
+ * ); @endcode
+ */
+ template <typename ShutdownHandler>
+ void async_shutdown(ShutdownHandler handler)
+ {
+ service_.async_shutdown(impl_, next_layer_, handler);
+ }
+
+ /// Write some data to the stream.
+ /**
+ * This function is used to write data on the stream. The function call will
+ * block until one or more bytes of data has been written successfully, or
+ * until an error occurs.
+ *
+ * @param buffers The data to be written.
+ *
+ * @returns The number of bytes written.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The write_some operation may not transmit all of the data to the
+ * peer. Consider using the @ref write function if you need to ensure that all
+ * data is written before the blocking operation completes.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = service_.write_some(impl_, next_layer_, buffers, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Write some data to the stream.
+ /**
+ * This function is used to write data on the stream. The function call will
+ * block until one or more bytes of data has been written successfully, or
+ * until an error occurs.
+ *
+ * @param buffers The data to be written to the stream.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes written. Returns 0 if an error occurred.
+ *
+ * @note The write_some operation may not transmit all of the data to the
+ * peer. Consider using the @ref write function if you need to ensure that all
+ * data is written before the blocking operation completes.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return service_.write_some(impl_, next_layer_, buffers, ec);
+ }
+
+ /// Start an asynchronous write.
+ /**
+ * This function is used to asynchronously write one or more bytes of data to
+ * the stream. The function call always returns immediately.
+ *
+ * @param buffers The data to be written to the stream. Although the buffers
+ * object may be copied as necessary, ownership of the underlying buffers is
+ * retained by the caller, which must guarantee that they remain valid until
+ * the handler is called.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The equivalent function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes written.
+ * ); @endcode
+ *
+ * @note The async_write_some operation may not transmit all of the data to
+ * the peer. Consider using the @ref async_write function if you need to
+ * ensure that all data is written before the blocking operation completes.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_write_some(const ConstBufferSequence& buffers,
+ WriteHandler handler)
+ {
+ service_.async_write_some(impl_, next_layer_, buffers, handler);
+ }
+
+ /// Read some data from the stream.
+ /**
+ * This function is used to read data from the stream. The function call will
+ * block until one or more bytes of data has been read successfully, or until
+ * an error occurs.
+ *
+ * @param buffers The buffers into which the data will be read.
+ *
+ * @returns The number of bytes read.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The read_some operation may not read all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that the
+ * requested amount of data is read before the blocking operation completes.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = service_.read_some(impl_, next_layer_, buffers, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Read some data from the stream.
+ /**
+ * This function is used to read data from the stream. The function call will
+ * block until one or more bytes of data has been read successfully, or until
+ * an error occurs.
+ *
+ * @param buffers The buffers into which the data will be read.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes read. Returns 0 if an error occurred.
+ *
+ * @note The read_some operation may not read all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that the
+ * requested amount of data is read before the blocking operation completes.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return service_.read_some(impl_, next_layer_, buffers, ec);
+ }
+
+ /// Start an asynchronous read.
+ /**
+ * This function is used to asynchronously read one or more bytes of data from
+ * the stream. The function call always returns immediately.
+ *
+ * @param buffers The buffers into which the data will be read. Although the
+ * buffers object may be copied as necessary, ownership of the underlying
+ * buffers is retained by the caller, which must guarantee that they remain
+ * valid until the handler is called.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The equivalent function
+ * signature of the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes read.
+ * ); @endcode
+ *
+ * @note The async_read_some operation may not read all of the requested
+ * number of bytes. Consider using the @ref async_read function if you need to
+ * ensure that the requested amount of data is read before the asynchronous
+ * operation completes.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_read_some(const MutableBufferSequence& buffers,
+ ReadHandler handler)
+ {
+ service_.async_read_some(impl_, next_layer_, buffers, handler);
+ }
+
+ /// Peek at the incoming data on the stream.
+ /**
+ * This function is used to peek at the incoming data on the stream, without
+ * removing it from the input queue. The function call will block until data
+ * has been read successfully or an error occurs.
+ *
+ * @param buffers The buffers into which the data will be read.
+ *
+ * @returns The number of bytes read.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t peek(const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = service_.peek(impl_, next_layer_, buffers, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Peek at the incoming data on the stream.
+ /**
+ * This function is used to peek at the incoming data on the stream, withoutxi
+ * removing it from the input queue. The function call will block until data
+ * has been read successfully or an error occurs.
+ *
+ * @param buffers The buffers into which the data will be read.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes read. Returns 0 if an error occurred.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t peek(const MutableBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return service_.peek(impl_, next_layer_, buffers, ec);
+ }
+
+ /// Determine the amount of data that may be read without blocking.
+ /**
+ * This function is used to determine the amount of data, in bytes, that may
+ * be read from the stream without blocking.
+ *
+ * @returns The number of bytes of data that can be read without blocking.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ std::size_t in_avail()
+ {
+ boost::system::error_code ec;
+ std::size_t s = service_.in_avail(impl_, next_layer_, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Determine the amount of data that may be read without blocking.
+ /**
+ * This function is used to determine the amount of data, in bytes, that may
+ * be read from the stream without blocking.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes of data that can be read without blocking.
+ */
+ std::size_t in_avail(boost::system::error_code& ec)
+ {
+ return service_.in_avail(impl_, next_layer_, ec);
+ }
+
+private:
+ /// The next layer.
+ Stream next_layer_;
+
+ /// The backend service implementation.
+ service_type& service_;
+
+ /// The underlying native implementation.
+ impl_type impl_;
+};
+
+} // namespace ssl
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SSL_STREAM_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ssl/stream_base.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ssl/stream_base.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,62 @@
+//
+// stream_base.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_SSL_STREAM_BASE_HPP
+#define BOOST_ASIO_SSL_STREAM_BASE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace ssl {
+
+/// The stream_base class is used as a base for the boost::asio::ssl::stream
+/// class template so that we have a common place to define various enums.
+class stream_base
+{
+public:
+ /// Different handshake types.
+ enum handshake_type
+ {
+ /// Perform handshaking as a client.
+ client,
+
+ /// Perform handshaking as a server.
+ server
+ };
+
+protected:
+ /// Protected destructor to prevent deletion through this type.
+ ~stream_base()
+ {
+ }
+
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
+private:
+ // Workaround to enable the empty base optimisation with Borland C++.
+ char dummy_;
+#endif
+};
+
+} // namespace ssl
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SSL_STREAM_BASE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/ssl/stream_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/ssl/stream_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,188 @@
+//
+// stream_service.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
+// Copyright (c) 2005-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_SSL_STREAM_SERVICE_HPP
+#define BOOST_ASIO_SSL_STREAM_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/ssl/basic_context.hpp>
+#include <boost/asio/ssl/stream_base.hpp>
+#include <boost/asio/ssl/detail/openssl_stream_service.hpp>
+
+namespace boost {
+namespace asio {
+namespace ssl {
+
+/// Default service implementation for an SSL stream.
+class stream_service
+#if defined(GENERATING_DOCUMENTATION)
+ : public boost::asio::io_service::service
+#else
+ : public boost::asio::detail::service_base<stream_service>
+#endif
+{
+private:
+ // The type of the platform-specific implementation.
+ typedef detail::openssl_stream_service service_impl_type;
+
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The unique service identifier.
+ static boost::asio::io_service::id id;
+#endif
+
+ /// The type of a stream implementation.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined impl_type;
+#else
+ typedef service_impl_type::impl_type impl_type;
+#endif
+
+ /// Construct a new stream service for the specified io_service.
+ explicit stream_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<stream_service>(io_service),
+ service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ {
+ }
+
+ /// Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ /// Return a null stream implementation.
+ impl_type null() const
+ {
+ return service_impl_.null();
+ }
+
+ /// Create a new stream implementation.
+ template <typename Stream, typename Context_Service>
+ void create(impl_type& impl, Stream& next_layer,
+ basic_context<Context_Service>& context)
+ {
+ service_impl_.create(impl, next_layer, context);
+ }
+
+ /// Destroy a stream implementation.
+ template <typename Stream>
+ void destroy(impl_type& impl, Stream& next_layer)
+ {
+ service_impl_.destroy(impl, next_layer);
+ }
+
+ /// Perform SSL handshaking.
+ template <typename Stream>
+ boost::system::error_code handshake(impl_type& impl, Stream& next_layer,
+ stream_base::handshake_type type, boost::system::error_code& ec)
+ {
+ return service_impl_.handshake(impl, next_layer, type, ec);
+ }
+
+ /// Start an asynchronous SSL handshake.
+ template <typename Stream, typename HandshakeHandler>
+ void async_handshake(impl_type& impl, Stream& next_layer,
+ stream_base::handshake_type type, HandshakeHandler handler)
+ {
+ service_impl_.async_handshake(impl, next_layer, type, handler);
+ }
+
+ /// Shut down SSL on the stream.
+ template <typename Stream>
+ boost::system::error_code shutdown(impl_type& impl, Stream& next_layer,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.shutdown(impl, next_layer, ec);
+ }
+
+ /// Asynchronously shut down SSL on the stream.
+ template <typename Stream, typename ShutdownHandler>
+ void async_shutdown(impl_type& impl, Stream& next_layer,
+ ShutdownHandler handler)
+ {
+ service_impl_.async_shutdown(impl, next_layer, handler);
+ }
+
+ /// Write some data to the stream.
+ template <typename Stream, typename ConstBufferSequence>
+ std::size_t write_some(impl_type& impl, Stream& next_layer,
+ const ConstBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return service_impl_.write_some(impl, next_layer, buffers, ec);
+ }
+
+ /// Start an asynchronous write.
+ template <typename Stream, typename ConstBufferSequence,
+ typename WriteHandler>
+ void async_write_some(impl_type& impl, Stream& next_layer,
+ const ConstBufferSequence& buffers, WriteHandler handler)
+ {
+ service_impl_.async_write_some(impl, next_layer, buffers, handler);
+ }
+
+ /// Read some data from the stream.
+ template <typename Stream, typename MutableBufferSequence>
+ std::size_t read_some(impl_type& impl, Stream& next_layer,
+ const MutableBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return service_impl_.read_some(impl, next_layer, buffers, ec);
+ }
+
+ /// Start an asynchronous read.
+ template <typename Stream, typename MutableBufferSequence,
+ typename ReadHandler>
+ void async_read_some(impl_type& impl, Stream& next_layer,
+ const MutableBufferSequence& buffers, ReadHandler handler)
+ {
+ service_impl_.async_read_some(impl, next_layer, buffers, handler);
+ }
+
+ /// Peek at the incoming data on the stream.
+ template <typename Stream, typename MutableBufferSequence>
+ std::size_t peek(impl_type& impl, Stream& next_layer,
+ const MutableBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return service_impl_.peek(impl, next_layer, buffers, ec);
+ }
+
+ /// Determine the amount of data that may be read without blocking.
+ template <typename Stream>
+ std::size_t in_avail(impl_type& impl, Stream& next_layer,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.in_avail(impl, next_layer, ec);
+ }
+
+private:
+ // The service that provides the platform-specific implementation.
+ service_impl_type& service_impl_;
+};
+
+} // namespace ssl
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_SSL_STREAM_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/strand.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/strand.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,188 @@
+//
+// strand.hpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_STRAND_HPP
+#define BOOST_ASIO_STRAND_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/strand_service.hpp>
+#include <boost/asio/detail/wrapped_handler.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Provides serialised handler execution.
+/**
+ * The io_service::strand class provides the ability to post and dispatch
+ * handlers with the guarantee that none of those handlers will execute
+ * concurrently.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Safe.
+ *
+ * @par Concepts:
+ * Dispatcher.
+ */
+class io_service::strand
+{
+public:
+ /// Constructor.
+ /**
+ * Constructs the strand.
+ *
+ * @param io_service The io_service object that the strand will use to
+ * dispatch handlers that are ready to be run.
+ */
+ explicit strand(boost::asio::io_service& io_service)
+ : service_(boost::asio::use_service<
+ boost::asio::detail::strand_service>(io_service))
+ {
+ service_.construct(impl_);
+ }
+
+ /// Destructor.
+ /**
+ * Destroys a strand.
+ *
+ * Handlers posted through the strand that have not yet been invoked will
+ * still be dispatched in a way that meets the guarantee of non-concurrency.
+ */
+ ~strand()
+ {
+ service_.destroy(impl_);
+ }
+
+ /// (Deprecated: use get_io_service().) Get the io_service associated with
+ /// the strand.
+ /**
+ * This function may be used to obtain the io_service object that the strand
+ * uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_service object that the strand will use to
+ * dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_service& io_service()
+ {
+ return service_.get_io_service();
+ }
+
+ /// Get the io_service associated with the strand.
+ /**
+ * This function may be used to obtain the io_service object that the strand
+ * uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_service object that the strand will use to
+ * dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_service& get_io_service()
+ {
+ return service_.get_io_service();
+ }
+
+ /// Request the strand to invoke the given handler.
+ /**
+ * This function is used to ask the strand to execute the given handler.
+ *
+ * The strand object guarantees that handlers posted or dispatched through
+ * the strand will not be executed concurrently. The handler may be executed
+ * inside this function if the guarantee can be met. If this function is
+ * called from within a handler that was posted or dispatched through the same
+ * strand, then the new handler will be executed immediately.
+ *
+ * The strand's guarantee is in addition to the guarantee provided by the
+ * underlying io_service. The io_service guarantees that the handler will only
+ * be called in a thread in which the io_service's run member function is
+ * currently being invoked.
+ *
+ * @param handler The handler to be called. The strand will make a copy of the
+ * handler object as required. The function signature of the handler must be:
+ * @code void handler(); @endcode
+ */
+ template <typename Handler>
+ void dispatch(Handler handler)
+ {
+ service_.dispatch(impl_, handler);
+ }
+
+ /// Request the strand to invoke the given handler and return
+ /// immediately.
+ /**
+ * This function is used to ask the strand to execute the given handler, but
+ * without allowing the strand to call the handler from inside this function.
+ *
+ * The strand object guarantees that handlers posted or dispatched through
+ * the strand will not be executed concurrently. The strand's guarantee is in
+ * addition to the guarantee provided by the underlying io_service. The
+ * io_service guarantees that the handler will only be called in a thread in
+ * which the io_service's run member function is currently being invoked.
+ *
+ * @param handler The handler to be called. The strand will make a copy of the
+ * handler object as required. The function signature of the handler must be:
+ * @code void handler(); @endcode
+ */
+ template <typename Handler>
+ void post(Handler handler)
+ {
+ service_.post(impl_, handler);
+ }
+
+ /// Create a new handler that automatically dispatches the wrapped handler
+ /// on the strand.
+ /**
+ * This function is used to create a new handler function object that, when
+ * invoked, will automatically pass the wrapped handler to the strand's
+ * dispatch function.
+ *
+ * @param handler The handler to be wrapped. The strand will make a copy of
+ * the handler object as required. The function signature of the handler must
+ * be: @code void handler(A1 a1, ... An an); @endcode
+ *
+ * @return A function object that, when invoked, passes the wrapped handler to
+ * the strand's dispatch function. Given a function object with the signature:
+ * @code R f(A1 a1, ... An an); @endcode
+ * If this function object is passed to the wrap function like so:
+ * @code strand.wrap(f); @endcode
+ * then the return value is a function object with the signature
+ * @code void g(A1 a1, ... An an); @endcode
+ * that, when invoked, executes code equivalent to:
+ * @code strand.dispatch(boost::bind(f, a1, ... an)); @endcode
+ */
+ template <typename Handler>
+#if defined(GENERATING_DOCUMENTATION)
+ unspecified
+#else
+ detail::wrapped_handler<strand, Handler>
+#endif
+ wrap(Handler handler)
+ {
+ return detail::wrapped_handler<io_service::strand, Handler>(*this, handler);
+ }
+
+private:
+ boost::asio::detail::strand_service& service_;
+ boost::asio::detail::strand_service::implementation_type impl_;
+};
+
+/// Typedef for backwards compatibility.
+typedef boost::asio::io_service::strand strand;
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_STRAND_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/stream_socket_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/stream_socket_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,288 @@
+//
+// stream_socket_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_STREAM_SOCKET_SERVICE_HPP
+#define BOOST_ASIO_STREAM_SOCKET_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/epoll_reactor.hpp>
+#include <boost/asio/detail/kqueue_reactor.hpp>
+#include <boost/asio/detail/select_reactor.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/win_iocp_socket_service.hpp>
+#include <boost/asio/detail/reactive_socket_service.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Default service implementation for a stream socket.
+template <typename Protocol>
+class stream_socket_service
+#if defined(GENERATING_DOCUMENTATION)
+ : public boost::asio::io_service::service
+#else
+ : public boost::asio::detail::service_base<stream_socket_service<Protocol> >
+#endif
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The unique service identifier.
+ static boost::asio::io_service::id id;
+#endif
+
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
+ /// The endpoint type.
+ typedef typename Protocol::endpoint endpoint_type;
+
+private:
+ // The type of the platform-specific implementation.
+#if defined(BOOST_ASIO_HAS_IOCP)
+ typedef detail::win_iocp_socket_service<Protocol> service_impl_type;
+#elif defined(BOOST_ASIO_HAS_EPOLL)
+ typedef detail::reactive_socket_service<
+ Protocol, detail::epoll_reactor<false> > service_impl_type;
+#elif defined(BOOST_ASIO_HAS_KQUEUE)
+ typedef detail::reactive_socket_service<
+ Protocol, detail::kqueue_reactor<false> > service_impl_type;
+#elif defined(BOOST_ASIO_HAS_DEV_POLL)
+ typedef detail::reactive_socket_service<
+ Protocol, detail::dev_poll_reactor<false> > service_impl_type;
+#else
+ typedef detail::reactive_socket_service<
+ Protocol, detail::select_reactor<false> > service_impl_type;
+#endif
+
+public:
+ /// The type of a stream socket implementation.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined implementation_type;
+#else
+ typedef typename service_impl_type::implementation_type implementation_type;
+#endif
+
+ /// The native socket type.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_type;
+#else
+ typedef typename service_impl_type::native_type native_type;
+#endif
+
+ /// Construct a new stream socket service for the specified io_service.
+ explicit stream_socket_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ stream_socket_service<Protocol> >(io_service),
+ service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ {
+ }
+
+ /// Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ /// Construct a new stream socket implementation.
+ void construct(implementation_type& impl)
+ {
+ service_impl_.construct(impl);
+ }
+
+ /// Destroy a stream socket implementation.
+ void destroy(implementation_type& impl)
+ {
+ service_impl_.destroy(impl);
+ }
+
+ /// Open a stream socket.
+ boost::system::error_code open(implementation_type& impl,
+ const protocol_type& protocol, boost::system::error_code& ec)
+ {
+ if (protocol.type() == SOCK_STREAM)
+ service_impl_.open(impl, protocol, ec);
+ else
+ ec = boost::asio::error::invalid_argument;
+ return ec;
+ }
+
+ /// Assign an existing native socket to a stream socket.
+ boost::system::error_code assign(implementation_type& impl,
+ const protocol_type& protocol, const native_type& native_socket,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.assign(impl, protocol, native_socket, ec);
+ }
+
+ /// Determine whether the socket is open.
+ bool is_open(const implementation_type& impl) const
+ {
+ return service_impl_.is_open(impl);
+ }
+
+ /// Close a stream socket implementation.
+ boost::system::error_code close(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.close(impl, ec);
+ }
+
+ /// Get the native socket implementation.
+ native_type native(implementation_type& impl)
+ {
+ return service_impl_.native(impl);
+ }
+
+ /// Cancel all asynchronous operations associated with the socket.
+ boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.cancel(impl, ec);
+ }
+
+ /// Determine whether the socket is at the out-of-band data mark.
+ bool at_mark(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.at_mark(impl, ec);
+ }
+
+ /// Determine the number of bytes available for reading.
+ std::size_t available(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.available(impl, ec);
+ }
+
+ /// Bind the stream socket to the specified local endpoint.
+ boost::system::error_code bind(implementation_type& impl,
+ const endpoint_type& endpoint, boost::system::error_code& ec)
+ {
+ return service_impl_.bind(impl, endpoint, ec);
+ }
+
+ /// Connect the stream socket to the specified endpoint.
+ boost::system::error_code connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ return service_impl_.connect(impl, peer_endpoint, ec);
+ }
+
+ /// Start an asynchronous connect.
+ template <typename ConnectHandler>
+ void async_connect(implementation_type& impl,
+ const endpoint_type& peer_endpoint, ConnectHandler handler)
+ {
+ service_impl_.async_connect(impl, peer_endpoint, handler);
+ }
+
+ /// Set a socket option.
+ template <typename SettableSocketOption>
+ boost::system::error_code set_option(implementation_type& impl,
+ const SettableSocketOption& option, boost::system::error_code& ec)
+ {
+ return service_impl_.set_option(impl, option, ec);
+ }
+
+ /// Get a socket option.
+ template <typename GettableSocketOption>
+ boost::system::error_code get_option(const implementation_type& impl,
+ GettableSocketOption& option, boost::system::error_code& ec) const
+ {
+ return service_impl_.get_option(impl, option, ec);
+ }
+
+ /// Perform an IO control command on the socket.
+ template <typename IoControlCommand>
+ boost::system::error_code io_control(implementation_type& impl,
+ IoControlCommand& command, boost::system::error_code& ec)
+ {
+ return service_impl_.io_control(impl, command, ec);
+ }
+
+ /// Get the local endpoint.
+ endpoint_type local_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.local_endpoint(impl, ec);
+ }
+
+ /// Get the remote endpoint.
+ endpoint_type remote_endpoint(const implementation_type& impl,
+ boost::system::error_code& ec) const
+ {
+ return service_impl_.remote_endpoint(impl, ec);
+ }
+
+ /// Disable sends or receives on the socket.
+ boost::system::error_code shutdown(implementation_type& impl,
+ socket_base::shutdown_type what, boost::system::error_code& ec)
+ {
+ return service_impl_.shutdown(impl, what, ec);
+ }
+
+ /// Send the given data to the peer.
+ template <typename ConstBufferSequence>
+ std::size_t send(implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return service_impl_.send(impl, buffers, flags, ec);
+ }
+
+ /// Start an asynchronous send.
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_send(implementation_type& impl,
+ const ConstBufferSequence& buffers,
+ socket_base::message_flags flags, WriteHandler handler)
+ {
+ service_impl_.async_send(impl, buffers, flags, handler);
+ }
+
+ /// Receive some data from the peer.
+ template <typename MutableBufferSequence>
+ std::size_t receive(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, boost::system::error_code& ec)
+ {
+ return service_impl_.receive(impl, buffers, flags, ec);
+ }
+
+ /// Start an asynchronous receive.
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_receive(implementation_type& impl,
+ const MutableBufferSequence& buffers,
+ socket_base::message_flags flags, ReadHandler handler)
+ {
+ service_impl_.async_receive(impl, buffers, flags, handler);
+ }
+
+private:
+ // The service that provides the platform-specific implementation.
+ service_impl_type& service_impl_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_STREAM_SOCKET_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/streambuf.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/streambuf.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,33 @@
+//
+// streambuf.hpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_STREAMBUF_HPP
+#define BOOST_ASIO_STREAMBUF_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/basic_streambuf.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Typedef for the typical usage of basic_streambuf.
+typedef basic_streambuf<> streambuf;
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_STREAMBUF_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/time_traits.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/time_traits.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,80 @@
+//
+// time_traits.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_TIME_TRAITS_HPP
+#define BOOST_ASIO_TIME_TRAITS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/socket_types.hpp> // Must come before posix_time.
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Time traits suitable for use with the deadline timer.
+template <typename Time>
+struct time_traits;
+
+/// Time traits specialised for posix_time.
+template <>
+struct time_traits<boost::posix_time::ptime>
+{
+ /// The time type.
+ typedef boost::posix_time::ptime time_type;
+
+ /// The duration type.
+ typedef boost::posix_time::time_duration duration_type;
+
+ /// Get the current time.
+ static time_type now()
+ {
+ return boost::posix_time::microsec_clock::universal_time();
+ }
+
+ /// Add a duration to a time.
+ static time_type add(const time_type& t, const duration_type& d)
+ {
+ return t + d;
+ }
+
+ /// Subtract one time from another.
+ static duration_type subtract(const time_type& t1, const time_type& t2)
+ {
+ return t1 - t2;
+ }
+
+ /// Test whether one time is less than another.
+ static bool less_than(const time_type& t1, const time_type& t2)
+ {
+ return t1 < t2;
+ }
+
+ /// Convert to POSIX duration type.
+ static boost::posix_time::time_duration to_posix_duration(
+ const duration_type& d)
+ {
+ return d;
+ }
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_TIME_TRAITS_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/version.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/version.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,23 @@
+//
+// version.hpp
+// ~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_VERSION_HPP
+#define BOOST_ASIO_VERSION_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+// BOOST_ASIO_VERSION % 100 is the sub-minor version
+// BOOST_ASIO_VERSION / 100 % 1000 is the minor version
+// BOOST_ASIO_VERSION / 100000 is the major version
+#define BOOST_ASIO_VERSION 100100 // 1.1.0
+
+#endif // BOOST_ASIO_VERSION_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/windows/basic_handle.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/windows/basic_handle.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,213 @@
+//
+// basic_handle.hpp
+// ~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_WINDOWS_BASIC_HANDLE_HPP
+#define BOOST_ASIO_WINDOWS_BASIC_HANDLE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+namespace boost {
+namespace asio {
+namespace windows {
+
+/// Provides Windows handle functionality.
+/**
+ * The windows::basic_handle class template provides the ability to wrap a
+ * Windows handle.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename HandleService>
+class basic_handle
+ : public basic_io_object<HandleService>
+{
+public:
+ /// The native representation of a handle.
+ typedef typename HandleService::native_type native_type;
+
+ /// A basic_handle is always the lowest layer.
+ typedef basic_handle<HandleService> lowest_layer_type;
+
+ /// Construct a basic_handle without opening it.
+ /**
+ * This constructor creates a handle without opening it.
+ *
+ * @param io_service The io_service object that the handle will use to
+ * dispatch handlers for any asynchronous operations performed on the handle.
+ */
+ explicit basic_handle(boost::asio::io_service& io_service)
+ : basic_io_object<HandleService>(io_service)
+ {
+ }
+
+ /// Construct a basic_handle on an existing native handle.
+ /**
+ * This constructor creates a handle object to hold an existing native handle.
+ *
+ * @param io_service The io_service object that the handle will use to
+ * dispatch handlers for any asynchronous operations performed on the handle.
+ *
+ * @param native_handle A native handle.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_handle(boost::asio::io_service& io_service,
+ const native_type& native_handle)
+ : basic_io_object<HandleService>(io_service)
+ {
+ boost::system::error_code ec;
+ this->service.assign(this->implementation, native_handle, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Get a reference to the lowest layer.
+ /**
+ * This function returns a reference to the lowest layer in a stack of
+ * layers. Since a basic_handle cannot contain any further layers, it simply
+ * returns a reference to itself.
+ *
+ * @return A reference to the lowest layer in the stack of layers. Ownership
+ * is not transferred to the caller.
+ */
+ lowest_layer_type& lowest_layer()
+ {
+ return *this;
+ }
+
+ /// Assign an existing native handle to the handle.
+ /*
+ * This function opens the handle to hold an existing native handle.
+ *
+ * @param native_handle A native handle.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void assign(const native_type& native_handle)
+ {
+ boost::system::error_code ec;
+ this->service.assign(this->implementation, native_handle, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Assign an existing native handle to the handle.
+ /*
+ * This function opens the handle to hold an existing native handle.
+ *
+ * @param native_handle A native handle.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code assign(const native_type& native_handle,
+ boost::system::error_code& ec)
+ {
+ return this->service.assign(this->implementation, native_handle, ec);
+ }
+
+ /// Determine whether the handle is open.
+ bool is_open() const
+ {
+ return this->service.is_open(this->implementation);
+ }
+
+ /// Close the handle.
+ /**
+ * This function is used to close the handle. Any asynchronous read or write
+ * operations will be cancelled immediately, and will complete with the
+ * boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void close()
+ {
+ boost::system::error_code ec;
+ this->service.close(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Close the handle.
+ /**
+ * This function is used to close the handle. Any asynchronous read or write
+ * operations will be cancelled immediately, and will complete with the
+ * boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code close(boost::system::error_code& ec)
+ {
+ return this->service.close(this->implementation, ec);
+ }
+
+ /// Get the native handle representation.
+ /**
+ * This function may be used to obtain the underlying representation of the
+ * handle. This is intended to allow access to native handle functionality
+ * that is not otherwise provided.
+ */
+ native_type native()
+ {
+ return this->service.native(this->implementation);
+ }
+
+ /// Cancel all asynchronous operations associated with the handle.
+ /**
+ * This function causes all outstanding asynchronous read or write operations
+ * to finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void cancel()
+ {
+ boost::system::error_code ec;
+ this->service.cancel(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ }
+
+ /// Cancel all asynchronous operations associated with the handle.
+ /**
+ * This function causes all outstanding asynchronous read or write operations
+ * to finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ boost::system::error_code cancel(boost::system::error_code& ec)
+ {
+ return this->service.cancel(this->implementation, ec);
+ }
+
+protected:
+ /// Protected destructor to prevent deletion through this type.
+ ~basic_handle()
+ {
+ }
+};
+
+} // namespace windows
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_WINDOWS_BASIC_HANDLE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/windows/basic_random_access_handle.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/windows/basic_random_access_handle.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,322 @@
+//
+// basic_random_access_handle.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP
+#define BOOST_ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/windows/basic_handle.hpp>
+#include <boost/asio/windows/random_access_handle_service.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+#if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
+ || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+namespace windows {
+
+/// Provides random-access handle functionality.
+/**
+ * The windows::basic_random_access_handle class template provides asynchronous
+ * and blocking random-access handle functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename RandomAccessHandleService = random_access_handle_service>
+class basic_random_access_handle
+ : public basic_handle<RandomAccessHandleService>
+{
+public:
+ /// The native representation of a handle.
+ typedef typename RandomAccessHandleService::native_type native_type;
+
+ /// Construct a basic_random_access_handle without opening it.
+ /**
+ * This constructor creates a random-access handle without opening it. The
+ * handle needs to be opened before data can be written to or or read from it.
+ *
+ * @param io_service The io_service object that the random-access handle will
+ * use to dispatch handlers for any asynchronous operations performed on the
+ * handle.
+ */
+ explicit basic_random_access_handle(boost::asio::io_service& io_service)
+ : basic_handle<RandomAccessHandleService>(io_service)
+ {
+ }
+
+ /// Construct a basic_random_access_handle on an existing native handle.
+ /**
+ * This constructor creates a random-access handle object to hold an existing
+ * native handle.
+ *
+ * @param io_service The io_service object that the random-access handle will
+ * use to dispatch handlers for any asynchronous operations performed on the
+ * handle.
+ *
+ * @param native_handle The new underlying handle implementation.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_random_access_handle(boost::asio::io_service& io_service,
+ const native_type& native_handle)
+ : basic_handle<RandomAccessHandleService>(io_service, native_handle)
+ {
+ }
+
+ /// Write some data to the handle at the specified offset.
+ /**
+ * This function is used to write data to the random-access handle. The
+ * function call will block until one or more bytes of the data has been
+ * written successfully, or until an error occurs.
+ *
+ * @param offset The offset at which the data will be written.
+ *
+ * @param buffers One or more data buffers to be written to the handle.
+ *
+ * @returns The number of bytes written.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The write_some_at operation may not write all of the data. Consider
+ * using the @ref write_at function if you need to ensure that all data is
+ * written before the blocking operation completes.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * handle.write_some_at(42, boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t write_some_at(boost::uint64_t offset,
+ const ConstBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.write_some_at(
+ this->implementation, offset, buffers, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Write some data to the handle at the specified offset.
+ /**
+ * This function is used to write data to the random-access handle. The
+ * function call will block until one or more bytes of the data has been
+ * written successfully, or until an error occurs.
+ *
+ * @param offset The offset at which the data will be written.
+ *
+ * @param buffers One or more data buffers to be written to the handle.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes written. Returns 0 if an error occurred.
+ *
+ * @note The write_some operation may not transmit all of the data to the
+ * peer. Consider using the @ref write_at function if you need to ensure that
+ * all data is written before the blocking operation completes.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t write_some_at(boost::uint64_t offset,
+ const ConstBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return this->service.write_some_at(
+ this->implementation, offset, buffers, ec);
+ }
+
+ /// Start an asynchronous write at the specified offset.
+ /**
+ * This function is used to asynchronously write data to the random-access
+ * handle. The function call always returns immediately.
+ *
+ * @param offset The offset at which the data will be written.
+ *
+ * @param buffers One or more data buffers to be written to the handle.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes written.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The write operation may not transmit all of the data to the peer.
+ * Consider using the @ref async_write_at function if you need to ensure that
+ * all data is written before the asynchronous operation completes.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * handle.async_write_some_at(42, boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_write_some_at(boost::uint64_t offset,
+ const ConstBufferSequence& buffers, WriteHandler handler)
+ {
+ this->service.async_write_some_at(
+ this->implementation, offset, buffers, handler);
+ }
+
+ /// Read some data from the handle at the specified offset.
+ /**
+ * This function is used to read data from the random-access handle. The
+ * function call will block until one or more bytes of data has been read
+ * successfully, or until an error occurs.
+ *
+ * @param offset The offset at which the data will be read.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ *
+ * @returns The number of bytes read.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The read_some operation may not read all of the requested number of
+ * bytes. Consider using the @ref read_at function if you need to ensure that
+ * the requested amount of data is read before the blocking operation
+ * completes.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code
+ * handle.read_some_at(42, boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t read_some_at(boost::uint64_t offset,
+ const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.read_some_at(
+ this->implementation, offset, buffers, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Read some data from the handle at the specified offset.
+ /**
+ * This function is used to read data from the random-access handle. The
+ * function call will block until one or more bytes of data has been read
+ * successfully, or until an error occurs.
+ *
+ * @param offset The offset at which the data will be read.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes read. Returns 0 if an error occurred.
+ *
+ * @note The read_some operation may not read all of the requested number of
+ * bytes. Consider using the @ref read_at function if you need to ensure that
+ * the requested amount of data is read before the blocking operation
+ * completes.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t read_some_at(boost::uint64_t offset,
+ const MutableBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return this->service.read_some_at(
+ this->implementation, offset, buffers, ec);
+ }
+
+ /// Start an asynchronous read at the specified offset.
+ /**
+ * This function is used to asynchronously read data from the random-access
+ * handle. The function call always returns immediately.
+ *
+ * @param offset The offset at which the data will be read.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes read.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The read operation may not read all of the requested number of bytes.
+ * Consider using the @ref async_read_at function if you need to ensure that
+ * the requested amount of data is read before the asynchronous operation
+ * completes.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code
+ * handle.async_read_some_at(42, boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_read_some_at(boost::uint64_t offset,
+ const MutableBufferSequence& buffers, ReadHandler handler)
+ {
+ this->service.async_read_some_at(
+ this->implementation, offset, buffers, handler);
+ }
+};
+
+} // namespace windows
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/windows/basic_stream_handle.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/windows/basic_stream_handle.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,304 @@
+//
+// basic_stream_handle.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP
+#define BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/windows/basic_handle.hpp>
+#include <boost/asio/windows/stream_handle_service.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+#if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \
+ || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+namespace windows {
+
+/// Provides stream-oriented handle functionality.
+/**
+ * The windows::basic_stream_handle class template provides asynchronous and
+ * blocking stream-oriented handle functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe._at_n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Concepts:
+ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
+ */
+template <typename StreamHandleService = stream_handle_service>
+class basic_stream_handle
+ : public basic_handle<StreamHandleService>
+{
+public:
+ /// The native representation of a handle.
+ typedef typename StreamHandleService::native_type native_type;
+
+ /// Construct a basic_stream_handle without opening it.
+ /**
+ * This constructor creates a stream handle without opening it. The handle
+ * needs to be opened and then connected or accepted before data can be sent
+ * or received on it.
+ *
+ * @param io_service The io_service object that the stream handle will use to
+ * dispatch handlers for any asynchronous operations performed on the handle.
+ */
+ explicit basic_stream_handle(boost::asio::io_service& io_service)
+ : basic_handle<StreamHandleService>(io_service)
+ {
+ }
+
+ /// Construct a basic_stream_handle on an existing native handle.
+ /**
+ * This constructor creates a stream handle object to hold an existing native
+ * handle.
+ *
+ * @param io_service The io_service object that the stream handle will use to
+ * dispatch handlers for any asynchronous operations performed on the handle.
+ *
+ * @param native_handle The new underlying handle implementation.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ basic_stream_handle(boost::asio::io_service& io_service,
+ const native_type& native_handle)
+ : basic_handle<StreamHandleService>(io_service, native_handle)
+ {
+ }
+
+ /// Write some data to the handle.
+ /**
+ * This function is used to write data to the stream handle. The function call
+ * will block until one or more bytes of the data has been written
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more data buffers to be written to the handle.
+ *
+ * @returns The number of bytes written.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The write_some operation may not transmit all of the data to the
+ * peer. Consider using the @ref write function if you need to ensure that
+ * all data is written before the blocking operation completes.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * handle.write_some(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.write_some(this->implementation, buffers, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Write some data to the handle.
+ /**
+ * This function is used to write data to the stream handle. The function call
+ * will block until one or more bytes of the data has been written
+ * successfully, or until an error occurs.
+ *
+ * @param buffers One or more data buffers to be written to the handle.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes written. Returns 0 if an error occurred.
+ *
+ * @note The write_some operation may not transmit all of the data to the
+ * peer. Consider using the @ref write function if you need to ensure that
+ * all data is written before the blocking operation completes.
+ */
+ template <typename ConstBufferSequence>
+ std::size_t write_some(const ConstBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return this->service.write_some(this->implementation, buffers, ec);
+ }
+
+ /// Start an asynchronous write.
+ /**
+ * This function is used to asynchronously write data to the stream handle.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more data buffers to be written to the handle.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes written.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The write operation may not transmit all of the data to the peer.
+ * Consider using the @ref async_write function if you need to ensure that all
+ * data is written before the asynchronous operation completes.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * handle.async_write_some(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_write_some(const ConstBufferSequence& buffers,
+ WriteHandler handler)
+ {
+ this->service.async_write_some(this->implementation, buffers, handler);
+ }
+
+ /// Read some data from the handle.
+ /**
+ * This function is used to read data from the stream handle. The function
+ * call will block until one or more bytes of data has been read successfully,
+ * or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ *
+ * @returns The number of bytes read.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @note The read_some operation may not read all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that
+ * the requested amount of data is read before the blocking operation
+ * completes.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code
+ * handle.read_some(boost::asio::buffer(data, size));
+ * @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->service.read_some(this->implementation, buffers, ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+ }
+
+ /// Read some data from the handle.
+ /**
+ * This function is used to read data from the stream handle. The function
+ * call will block until one or more bytes of data has been read successfully,
+ * or until an error occurs.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes read. Returns 0 if an error occurred.
+ *
+ * @note The read_some operation may not read all of the requested number of
+ * bytes. Consider using the @ref read function if you need to ensure that
+ * the requested amount of data is read before the blocking operation
+ * completes.
+ */
+ template <typename MutableBufferSequence>
+ std::size_t read_some(const MutableBufferSequence& buffers,
+ boost::system::error_code& ec)
+ {
+ return this->service.read_some(this->implementation, buffers, ec);
+ }
+
+ /// Start an asynchronous read.
+ /**
+ * This function is used to asynchronously read data from the stream handle.
+ * The function call always returns immediately.
+ *
+ * @param buffers One or more buffers into which the data will be read.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * std::size_t bytes_transferred // Number of bytes read.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @note The read operation may not read all of the requested number of bytes.
+ * Consider using the @ref async_read function if you need to ensure that the
+ * requested amount of data is read before the asynchronous operation
+ * completes.
+ *
+ * @par Example
+ * To read into a single data buffer use the @ref buffer function as follows:
+ * @code
+ * handle.async_read_some(boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on reading into multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_read_some(const MutableBufferSequence& buffers,
+ ReadHandler handler)
+ {
+ this->service.async_read_some(this->implementation, buffers, handler);
+ }
+};
+
+} // namespace windows
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/windows/random_access_handle.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/windows/random_access_handle.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,41 @@
+//
+// random_access_handle.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_HPP
+#define BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/windows/basic_random_access_handle.hpp>
+
+#if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
+ || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+namespace windows {
+
+/// Typedef for the typical usage of a random-access handle.
+typedef basic_random_access_handle<> random_access_handle;
+
+} // namespace windows
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/windows/random_access_handle_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/windows/random_access_handle_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,181 @@
+//
+// random_access_handle_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP
+#define BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/win_iocp_handle_service.hpp>
+
+#if !defined(BOOST_ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE)
+# if defined(BOOST_ASIO_HAS_IOCP)
+# define BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE 1
+# endif // defined(BOOST_ASIO_HAS_IOCP)
+#endif // !defined(BOOST_ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE)
+
+#if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
+ || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+namespace windows {
+
+/// Default service implementation for a random-access handle.
+class random_access_handle_service
+#if defined(GENERATING_DOCUMENTATION)
+ : public boost::asio::io_service::service
+#else
+ : public boost::asio::detail::service_base<random_access_handle_service>
+#endif
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The unique service identifier.
+ static boost::asio::io_service::id id;
+#endif
+
+private:
+ // The type of the platform-specific implementation.
+ typedef detail::win_iocp_handle_service service_impl_type;
+
+public:
+ /// The type of a random-access handle implementation.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined implementation_type;
+#else
+ typedef service_impl_type::implementation_type implementation_type;
+#endif
+
+ /// The native handle type.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_type;
+#else
+ typedef service_impl_type::native_type native_type;
+#endif
+
+ /// Construct a new random-access handle service for the specified io_service.
+ explicit random_access_handle_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<
+ random_access_handle_service>(io_service),
+ service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ {
+ }
+
+ /// Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ /// Construct a new random-access handle implementation.
+ void construct(implementation_type& impl)
+ {
+ service_impl_.construct(impl);
+ }
+
+ /// Destroy a random-access handle implementation.
+ void destroy(implementation_type& impl)
+ {
+ service_impl_.destroy(impl);
+ }
+
+ /// Assign an existing native handle to a random-access handle.
+ boost::system::error_code assign(implementation_type& impl,
+ const native_type& native_handle, boost::system::error_code& ec)
+ {
+ return service_impl_.assign(impl, native_handle, ec);
+ }
+
+ /// Determine whether the handle is open.
+ bool is_open(const implementation_type& impl) const
+ {
+ return service_impl_.is_open(impl);
+ }
+
+ /// Close a random-access handle implementation.
+ boost::system::error_code close(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.close(impl, ec);
+ }
+
+ /// Get the native handle implementation.
+ native_type native(implementation_type& impl)
+ {
+ return service_impl_.native(impl);
+ }
+
+ /// Cancel all asynchronous operations associated with the handle.
+ boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.cancel(impl, ec);
+ }
+
+ /// Write the given data at the specified offset.
+ template <typename ConstBufferSequence>
+ std::size_t write_some_at(implementation_type& impl, boost::uint64_t offset,
+ const ConstBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return service_impl_.write_some_at(impl, offset, buffers, ec);
+ }
+
+ /// Start an asynchronous write at the specified offset.
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_write_some_at(implementation_type& impl, boost::uint64_t offset,
+ const ConstBufferSequence& buffers, WriteHandler handler)
+ {
+ service_impl_.async_write_some_at(impl, offset, buffers, handler);
+ }
+
+ /// Read some data from the specified offset.
+ template <typename MutableBufferSequence>
+ std::size_t read_some_at(implementation_type& impl, boost::uint64_t offset,
+ const MutableBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return service_impl_.read_some_at(impl, offset, buffers, ec);
+ }
+
+ /// Start an asynchronous read at the specified offset.
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_read_some_at(implementation_type& impl, boost::uint64_t offset,
+ const MutableBufferSequence& buffers, ReadHandler handler)
+ {
+ service_impl_.async_read_some_at(impl, offset, buffers, handler);
+ }
+
+private:
+ // The service that provides the platform-specific implementation.
+ service_impl_type& service_impl_;
+};
+
+} // namespace windows
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/windows/stream_handle.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/windows/stream_handle.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,41 @@
+//
+// stream_handle.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_WINDOWS_STREAM_HANDLE_HPP
+#define BOOST_ASIO_WINDOWS_STREAM_HANDLE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/windows/basic_stream_handle.hpp>
+
+#if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \
+ || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+namespace windows {
+
+/// Typedef for the typical usage of a stream-oriented handle.
+typedef basic_stream_handle<> stream_handle;
+
+} // namespace windows
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_WINDOWS_STREAM_HANDLE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/windows/stream_handle_service.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/windows/stream_handle_service.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,179 @@
+//
+// stream_handle_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP
+#define BOOST_ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/service_base.hpp>
+#include <boost/asio/detail/win_iocp_handle_service.hpp>
+
+#if !defined(BOOST_ASIO_DISABLE_WINDOWS_STREAM_HANDLE)
+# if defined(BOOST_ASIO_HAS_IOCP)
+# define BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE 1
+# endif // defined(BOOST_ASIO_HAS_IOCP)
+#endif // !defined(BOOST_ASIO_DISABLE_WINDOWS_STREAM_HANDLE)
+
+#if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \
+ || defined(GENERATING_DOCUMENTATION)
+
+namespace boost {
+namespace asio {
+namespace windows {
+
+/// Default service implementation for a stream handle.
+class stream_handle_service
+#if defined(GENERATING_DOCUMENTATION)
+ : public boost::asio::io_service::service
+#else
+ : public boost::asio::detail::service_base<stream_handle_service>
+#endif
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// The unique service identifier.
+ static boost::asio::io_service::id id;
+#endif
+
+private:
+ // The type of the platform-specific implementation.
+ typedef detail::win_iocp_handle_service service_impl_type;
+
+public:
+ /// The type of a stream handle implementation.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined implementation_type;
+#else
+ typedef service_impl_type::implementation_type implementation_type;
+#endif
+
+ /// The native handle type.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_type;
+#else
+ typedef service_impl_type::native_type native_type;
+#endif
+
+ /// Construct a new stream handle service for the specified io_service.
+ explicit stream_handle_service(boost::asio::io_service& io_service)
+ : boost::asio::detail::service_base<stream_handle_service>(io_service),
+ service_impl_(boost::asio::use_service<service_impl_type>(io_service))
+ {
+ }
+
+ /// Destroy all user-defined handler objects owned by the service.
+ void shutdown_service()
+ {
+ }
+
+ /// Construct a new stream handle implementation.
+ void construct(implementation_type& impl)
+ {
+ service_impl_.construct(impl);
+ }
+
+ /// Destroy a stream handle implementation.
+ void destroy(implementation_type& impl)
+ {
+ service_impl_.destroy(impl);
+ }
+
+ /// Assign an existing native handle to a stream handle.
+ boost::system::error_code assign(implementation_type& impl,
+ const native_type& native_handle, boost::system::error_code& ec)
+ {
+ return service_impl_.assign(impl, native_handle, ec);
+ }
+
+ /// Determine whether the handle is open.
+ bool is_open(const implementation_type& impl) const
+ {
+ return service_impl_.is_open(impl);
+ }
+
+ /// Close a stream handle implementation.
+ boost::system::error_code close(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.close(impl, ec);
+ }
+
+ /// Get the native handle implementation.
+ native_type native(implementation_type& impl)
+ {
+ return service_impl_.native(impl);
+ }
+
+ /// Cancel all asynchronous operations associated with the handle.
+ boost::system::error_code cancel(implementation_type& impl,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.cancel(impl, ec);
+ }
+
+ /// Write the given data to the stream.
+ template <typename ConstBufferSequence>
+ std::size_t write_some(implementation_type& impl,
+ const ConstBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return service_impl_.write_some(impl, buffers, ec);
+ }
+
+ /// Start an asynchronous write.
+ template <typename ConstBufferSequence, typename WriteHandler>
+ void async_write_some(implementation_type& impl,
+ const ConstBufferSequence& buffers, WriteHandler handler)
+ {
+ service_impl_.async_write_some(impl, buffers, handler);
+ }
+
+ /// Read some data from the stream.
+ template <typename MutableBufferSequence>
+ std::size_t read_some(implementation_type& impl,
+ const MutableBufferSequence& buffers, boost::system::error_code& ec)
+ {
+ return service_impl_.read_some(impl, buffers, ec);
+ }
+
+ /// Start an asynchronous read.
+ template <typename MutableBufferSequence, typename ReadHandler>
+ void async_read_some(implementation_type& impl,
+ const MutableBufferSequence& buffers, ReadHandler handler)
+ {
+ service_impl_.async_read_some(impl, buffers, handler);
+ }
+
+private:
+ // The service that provides the platform-specific implementation.
+ service_impl_type& service_impl_;
+};
+
+} // namespace windows
+} // namespace asio
+} // namespace boost
+
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/write.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/write.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,517 @@
+//
+// write.hpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_WRITE_HPP
+#define BOOST_ASIO_WRITE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/basic_streambuf.hpp>
+#include <boost/asio/error.hpp>
+
+namespace boost {
+namespace asio {
+
+/**
+ * @defgroup write boost::asio::write
+ */
+/*@{*/
+
+/// Write all of the supplied data to a stream before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a stream.
+ * The call will block until one of the following conditions is true:
+ *
+ * @li All of the data in the supplied buffers has been written. That is, the
+ * bytes transferred is equal to the sum of the buffer sizes.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * write_some function.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the SyncWriteStream concept.
+ *
+ * @param buffers One or more buffers containing the data to be written. The sum
+ * of the buffer sizes indicates the maximum number of bytes to write to the
+ * stream.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code boost::asio::write(s, boost::asio::buffer(data, size)); @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ *
+ * @note This overload is equivalent to calling:
+ * @code boost::asio::write(
+ * s, buffers,
+ * boost::asio::transfer_all()); @endcode
+ */
+template <typename SyncWriteStream, typename ConstBufferSequence>
+std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers);
+
+/// Write a certain amount of data to a stream before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a stream.
+ * The call will block until one of the following conditions is true:
+ *
+ * @li All of the data in the supplied buffers has been written. That is, the
+ * bytes transferred is equal to the sum of the buffer sizes.
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * write_some function.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the SyncWriteStream concept.
+ *
+ * @param buffers One or more buffers containing the data to be written. The sum
+ * of the buffer sizes indicates the maximum number of bytes to write to the
+ * stream.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the write operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * const boost::system::error_code& error, // Result of latest write_some
+ * // operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes transferred
+ * // so far.
+ * ); @endcode
+ * A return value of true indicates that the write operation is complete. False
+ * indicates that further calls to the stream's write_some function are
+ * required.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code boost::asio::write(s, boost::asio::buffer(data, size),
+ * boost::asio::transfer_at_least(32)); @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+template <typename SyncWriteStream, typename ConstBufferSequence,
+ typename CompletionCondition>
+std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition);
+
+/// Write a certain amount of data to a stream before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a stream.
+ * The call will block until one of the following conditions is true:
+ *
+ * @li All of the data in the supplied buffers has been written. That is, the
+ * bytes transferred is equal to the sum of the buffer sizes.
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * write_some function.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the SyncWriteStream concept.
+ *
+ * @param buffers One or more buffers containing the data to be written. The sum
+ * of the buffer sizes indicates the maximum number of bytes to write to the
+ * stream.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the write operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * const boost::system::error_code& error, // Result of latest write_some
+ * // operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes transferred
+ * // so far.
+ * ); @endcode
+ * A return value of true indicates that the write operation is complete. False
+ * indicates that further calls to the stream's write_some function are
+ * required.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes written. If an error occurs, returns the total
+ * number of bytes successfully transferred prior to the error.
+ */
+template <typename SyncWriteStream, typename ConstBufferSequence,
+ typename CompletionCondition>
+std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition, boost::system::error_code& ec);
+
+/// Write all of the supplied data to a stream before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a stream.
+ * The call will block until one of the following conditions is true:
+ *
+ * @li All of the data in the supplied basic_streambuf has been written.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * write_some function.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the SyncWriteStream concept.
+ *
+ * @param b The basic_streambuf object from which data will be written.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This overload is equivalent to calling:
+ * @code boost::asio::write(
+ * s, b,
+ * boost::asio::transfer_all()); @endcode
+ */
+template <typename SyncWriteStream, typename Allocator>
+std::size_t write(SyncWriteStream& s, basic_streambuf<Allocator>& b);
+
+/// Write a certain amount of data to a stream before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a stream.
+ * The call will block until one of the following conditions is true:
+ *
+ * @li All of the data in the supplied basic_streambuf has been written.
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * write_some function.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the SyncWriteStream concept.
+ *
+ * @param b The basic_streambuf object from which data will be written.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the write operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * const boost::system::error_code& error, // Result of latest write_some
+ * // operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes transferred
+ * // so far.
+ * ); @endcode
+ * A return value of true indicates that the write operation is complete. False
+ * indicates that further calls to the stream's write_some function are
+ * required.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+template <typename SyncWriteStream, typename Allocator,
+ typename CompletionCondition>
+std::size_t write(SyncWriteStream& s, basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition);
+
+/// Write a certain amount of data to a stream before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a stream.
+ * The call will block until one of the following conditions is true:
+ *
+ * @li All of the data in the supplied basic_streambuf has been written.
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * write_some function.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the SyncWriteStream concept.
+ *
+ * @param b The basic_streambuf object from which data will be written.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the write operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * const boost::system::error_code& error, // Result of latest write_some
+ * // operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes transferred
+ * // so far.
+ * ); @endcode
+ * A return value of true indicates that the write operation is complete. False
+ * indicates that further calls to the stream's write_some function are
+ * required.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes written. If an error occurs, returns the total
+ * number of bytes successfully transferred prior to the error.
+ */
+template <typename SyncWriteStream, typename Allocator,
+ typename CompletionCondition>
+std::size_t write(SyncWriteStream& s, basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, boost::system::error_code& ec);
+
+/*@}*/
+/**
+ * @defgroup async_write boost::asio::async_write
+ */
+/*@{*/
+
+/// Start an asynchronous operation to write all of the supplied data to a
+/// stream.
+/**
+ * This function is used to asynchronously write a certain number of bytes of
+ * data to a stream. The function call always returns immediately. The
+ * asynchronous operation will continue until one of the following conditions
+ * is true:
+ *
+ * @li All of the data in the supplied buffers has been written. That is, the
+ * bytes transferred is equal to the sum of the buffer sizes.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * async_write_some function.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the AsyncWriteStream concept.
+ *
+ * @param buffers One or more buffers containing the data to be written.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes written from the
+ * // buffers. If an error occurred,
+ * // this will be less than the sum
+ * // of the buffer sizes.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * boost::asio::async_write(s, boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+template <typename AsyncWriteStream, typename ConstBufferSequence,
+ typename WriteHandler>
+void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
+ WriteHandler handler);
+
+/// Start an asynchronous operation to write a certain amount of data to a
+/// stream.
+/**
+ * This function is used to asynchronously write a certain number of bytes of
+ * data to a stream. The function call always returns immediately. The
+ * asynchronous operation will continue until one of the following conditions
+ * is true:
+ *
+ * @li All of the data in the supplied buffers has been written. That is, the
+ * bytes transferred is equal to the sum of the buffer sizes.
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * async_write_some function.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the AsyncWriteStream concept.
+ *
+ * @param buffers One or more buffers containing the data to be written.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the write operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * const boost::system::error_code& error, // Result of latest write_some
+ * // operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes transferred
+ * // so far.
+ * ); @endcode
+ * A return value of true indicates that the write operation is complete. False
+ * indicates that further calls to the stream's async_write_some function are
+ * required.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes written from the
+ * // buffers. If an error occurred,
+ * // this will be less than the sum
+ * // of the buffer sizes.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code boost::asio::async_write(s,
+ * boost::asio::buffer(data, size),
+ * boost::asio::transfer_at_least(32),
+ * handler); @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+template <typename AsyncWriteStream, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition, WriteHandler handler);
+
+/// Start an asynchronous operation to write all of the supplied data to a
+/// stream.
+/**
+ * This function is used to asynchronously write a certain number of bytes of
+ * data to a stream. The function call always returns immediately. The
+ * asynchronous operation will continue until one of the following conditions
+ * is true:
+ *
+ * @li All of the data in the supplied basic_streambuf has been written.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * async_write_some function.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the AsyncWriteStream concept.
+ *
+ * @param b A basic_streambuf object from which data will be written. Ownership
+ * of the streambuf is retained by the caller, which must guarantee that it
+ * remains valid until the handler is called.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes written from the
+ * // buffers. If an error occurred,
+ * // this will be less than the sum
+ * // of the buffer sizes.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ */
+template <typename AsyncWriteStream, typename Allocator, typename WriteHandler>
+void async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b,
+ WriteHandler handler);
+
+/// Start an asynchronous operation to write a certain amount of data to a
+/// stream.
+/**
+ * This function is used to asynchronously write a certain number of bytes of
+ * data to a stream. The function call always returns immediately. The
+ * asynchronous operation will continue until one of the following conditions
+ * is true:
+ *
+ * @li All of the data in the supplied basic_streambuf has been written.
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the stream's
+ * async_write_some function.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the AsyncWriteStream concept.
+ *
+ * @param b A basic_streambuf object from which data will be written. Ownership
+ * of the streambuf is retained by the caller, which must guarantee that it
+ * remains valid until the handler is called.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the write operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * const boost::system::error_code& error, // Result of latest write_some
+ * // operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes transferred
+ * // so far.
+ * ); @endcode
+ * A return value of true indicates that the write operation is complete. False
+ * indicates that further calls to the stream's async_write_some function are
+ * required.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ *
+ * std::size_t bytes_transferred // Number of bytes written from the
+ * // buffers. If an error occurred,
+ * // this will be less than the sum
+ * // of the buffer sizes.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ */
+template <typename AsyncWriteStream, typename Allocator,
+ typename CompletionCondition, typename WriteHandler>
+void async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, WriteHandler handler);
+
+/*@}*/
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/impl/write.ipp>
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_WRITE_HPP
Added: branches/CMake/release/libs/asio/include/boost/asio/write_at.hpp
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/include/boost/asio/write_at.hpp 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,552 @@
+//
+// write_at.hpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_WRITE_AT_HPP
+#define BOOST_ASIO_WRITE_AT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/push_options.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+#include <cstddef>
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/basic_streambuf.hpp>
+#include <boost/asio/error.hpp>
+
+namespace boost {
+namespace asio {
+
+/**
+ * @defgroup write_at boost::asio::write_at
+ */
+/*@{*/
+
+/// Write all of the supplied data at the specified offset before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a random
+ * access device at a specified offset. The call will block until one of the
+ * following conditions is true:
+ *
+ * @li All of the data in the supplied buffers has been written. That is, the
+ * bytes transferred is equal to the sum of the buffer sizes.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * write_some_at function.
+ *
+ * @param d The device to which the data is to be written. The type must support
+ * the SyncRandomAccessWriteDevice concept.
+ *
+ * @param offset The offset at which the data will be written.
+ *
+ * @param buffers One or more buffers containing the data to be written. The sum
+ * of the buffer sizes indicates the maximum number of bytes to write to the
+ * device.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code boost::asio::write_at(d, 42, boost::asio::buffer(data, size)); @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ *
+ * @note This overload is equivalent to calling:
+ * @code boost::asio::write_at(
+ * d, offset, buffers,
+ * boost::asio::transfer_all()); @endcode
+ */
+template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>
+std::size_t write_at(SyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, const ConstBufferSequence& buffers);
+
+/// Write a certain amount of data at a specified offset before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a random
+ * access device at a specified offset. The call will block until one of the
+ * following conditions is true:
+ *
+ * @li All of the data in the supplied buffers has been written. That is, the
+ * bytes transferred is equal to the sum of the buffer sizes.
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * write_some_at function.
+ *
+ * @param d The device to which the data is to be written. The type must support
+ * the SyncRandomAccessWriteDevice concept.
+ *
+ * @param offset The offset at which the data will be written.
+ *
+ * @param buffers One or more buffers containing the data to be written. The sum
+ * of the buffer sizes indicates the maximum number of bytes to write to the
+ * device.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the write operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * // Result of latest write_some_at operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes transferred so far.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of true indicates that the write operation is complete. False
+ * indicates that further calls to the device's write_some_at function are
+ * required.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code boost::asio::write_at(d, 42, boost::asio::buffer(data, size),
+ * boost::asio::transfer_at_least(32)); @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename CompletionCondition>
+std::size_t write_at(SyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition);
+
+/// Write a certain amount of data at a specified offset before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a random
+ * access device at a specified offset. The call will block until one of the
+ * following conditions is true:
+ *
+ * @li All of the data in the supplied buffers has been written. That is, the
+ * bytes transferred is equal to the sum of the buffer sizes.
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * write_some_at function.
+ *
+ * @param d The device to which the data is to be written. The type must support
+ * the SyncRandomAccessWriteDevice concept.
+ *
+ * @param offset The offset at which the data will be written.
+ *
+ * @param buffers One or more buffers containing the data to be written. The sum
+ * of the buffer sizes indicates the maximum number of bytes to write to the
+ * device.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the write operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * // Result of latest write_some_at operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes transferred so far.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of true indicates that the write operation is complete. False
+ * indicates that further calls to the device's write_some_at function are
+ * required.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes written. If an error occurs, returns the total
+ * number of bytes successfully transferred prior to the error.
+ */
+template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename CompletionCondition>
+std::size_t write_at(SyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition, boost::system::error_code& ec);
+
+/// Write all of the supplied data at the specified offset before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a random
+ * access device at a specified offset. The call will block until one of the
+ * following conditions is true:
+ *
+ * @li All of the data in the supplied basic_streambuf has been written.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * write_some_at function.
+ *
+ * @param d The device to which the data is to be written. The type must support
+ * the SyncRandomAccessWriteDevice concept.
+ *
+ * @param offset The offset at which the data will be written.
+ *
+ * @param b The basic_streambuf object from which data will be written.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This overload is equivalent to calling:
+ * @code boost::asio::write_at(
+ * d, 42, b,
+ * boost::asio::transfer_all()); @endcode
+ */
+template <typename SyncRandomAccessWriteDevice, typename Allocator>
+std::size_t write_at(SyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, basic_streambuf<Allocator>& b);
+
+/// Write a certain amount of data at a specified offset before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a random
+ * access device at a specified offset. The call will block until one of the
+ * following conditions is true:
+ *
+ * @li All of the data in the supplied basic_streambuf has been written.
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * write_some_at function.
+ *
+ * @param d The device to which the data is to be written. The type must support
+ * the SyncRandomAccessWriteDevice concept.
+ *
+ * @param offset The offset at which the data will be written.
+ *
+ * @param b The basic_streambuf object from which data will be written.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the write operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * // Result of latest write_some_at operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes transferred so far.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of true indicates that the write operation is complete. False
+ * indicates that further calls to the device's write_some_at function are
+ * required.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+template <typename SyncRandomAccessWriteDevice, typename Allocator,
+ typename CompletionCondition>
+std::size_t write_at(SyncRandomAccessWriteDevice& d, boost::uint64_t offset,
+ basic_streambuf<Allocator>& b, CompletionCondition completion_condition);
+
+/// Write a certain amount of data at a specified offset before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a random
+ * access device at a specified offset. The call will block until one of the
+ * following conditions is true:
+ *
+ * @li All of the data in the supplied basic_streambuf has been written.
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * write_some_at function.
+ *
+ * @param d The device to which the data is to be written. The type must support
+ * the SyncRandomAccessWriteDevice concept.
+ *
+ * @param offset The offset at which the data will be written.
+ *
+ * @param b The basic_streambuf object from which data will be written.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the write operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * // Result of latest write_some_at operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes transferred so far.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of true indicates that the write operation is complete. False
+ * indicates that further calls to the device's write_some_at function are
+ * required.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes written. If an error occurs, returns the total
+ * number of bytes successfully transferred prior to the error.
+ */
+template <typename SyncRandomAccessWriteDevice, typename Allocator,
+ typename CompletionCondition>
+std::size_t write_at(SyncRandomAccessWriteDevice& d, boost::uint64_t offset,
+ basic_streambuf<Allocator>& b, CompletionCondition completion_condition,
+ boost::system::error_code& ec);
+
+/*@}*/
+/**
+ * @defgroup async_write_at boost::asio::async_write_at
+ */
+/*@{*/
+
+/// Start an asynchronous operation to write all of the supplied data at the
+/// specified offset.
+/**
+ * This function is used to asynchronously write a certain number of bytes of
+ * data to a random access device at a specified offset. The function call
+ * always returns immediately. The asynchronous operation will continue until
+ * one of the following conditions is true:
+ *
+ * @li All of the data in the supplied buffers has been written. That is, the
+ * bytes transferred is equal to the sum of the buffer sizes.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * async_write_some_at function.
+ *
+ * @param d The device to which the data is to be written. The type must support
+ * the AsyncRandomAccessWriteDevice concept.
+ *
+ * @param offset The offset at which the data will be written.
+ *
+ * @param buffers One or more buffers containing the data to be written.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The function signature of
+ * the handler must be:
+ * @code void handler(
+ * // Result of operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes written from the buffers. If an error
+ * // occurred, this will be less than the sum of the buffer sizes.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * boost::asio::async_write_at(d, 42, boost::asio::buffer(data, size), handler);
+ * @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename WriteHandler>
+void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset,
+ const ConstBufferSequence& buffers, WriteHandler handler);
+
+/// Start an asynchronous operation to write a certain amount of data at the
+/// specified offset.
+/**
+ * This function is used to asynchronously write a certain number of bytes of
+ * data to a random access device at a specified offset. The function call
+ * always returns immediately. The asynchronous operation will continue until
+ * one of the following conditions is true:
+ *
+ * @li All of the data in the supplied buffers has been written. That is, the
+ * bytes transferred is equal to the sum of the buffer sizes.
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * async_write_some_at function.
+ *
+ * @param d The device to which the data is to be written. The type must support
+ * the AsyncRandomAccessWriteDevice concept.
+ *
+ * @param offset The offset at which the data will be written.
+ *
+ * @param buffers One or more buffers containing the data to be written.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the write operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * // Result of latest write_some_at operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes transferred so far.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of true indicates that the write operation is complete. False
+ * indicates that further calls to the device's async_write_some_at function are
+ * required.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * // Result of operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes written from the buffers. If an error
+ * // occurred, this will be less than the sum of the buffer sizes.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code boost::asio::async_write_at(d, 42,
+ * boost::asio::buffer(data, size),
+ * boost::asio::transfer_at_least(32),
+ * handler); @endcode
+ * See the @ref buffer documentation for information on writing multiple
+ * buffers in one go, and how to use it with arrays, boost::array or
+ * std::vector.
+ */
+template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename CompletionCondition, typename WriteHandler>
+void async_write_at(AsyncRandomAccessWriteDevice& d,
+ boost::uint64_t offset, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition, WriteHandler handler);
+
+/// Start an asynchronous operation to write all of the supplied data at the
+/// specified offset.
+/**
+ * This function is used to asynchronously write a certain number of bytes of
+ * data to a random access device at a specified offset. The function call
+ * always returns immediately. The asynchronous operation will continue until
+ * one of the following conditions is true:
+ *
+ * @li All of the data in the supplied basic_streambuf has been written.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * async_write_some_at function.
+ *
+ * @param d The device to which the data is to be written. The type must support
+ * the AsyncRandomAccessWriteDevice concept.
+ *
+ * @param offset The offset at which the data will be written.
+ *
+ * @param b A basic_streambuf object from which data will be written. Ownership
+ * of the streambuf is retained by the caller, which must guarantee that it
+ * remains valid until the handler is called.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * // Result of operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes written from the buffers. If an error
+ * // occurred, this will be less than the sum of the buffer sizes.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ */
+template <typename AsyncRandomAccessWriteDevice, typename Allocator,
+ typename WriteHandler>
+void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset,
+ basic_streambuf<Allocator>& b, WriteHandler handler);
+
+/// Start an asynchronous operation to write a certain amount of data at the
+/// specified offset.
+/**
+ * This function is used to asynchronously write a certain number of bytes of
+ * data to a random access device at a specified offset. The function call
+ * always returns immediately. The asynchronous operation will continue until
+ * one of the following conditions is true:
+ *
+ * @li All of the data in the supplied basic_streambuf has been written.
+ *
+ * @li The completion_condition function object returns true.
+ *
+ * This operation is implemented in terms of one or more calls to the device's
+ * async_write_some_at function.
+ *
+ * @param d The device to which the data is to be written. The type must support
+ * the AsyncRandomAccessWriteDevice concept.
+ *
+ * @param offset The offset at which the data will be written.
+ *
+ * @param b A basic_streambuf object from which data will be written. Ownership
+ * of the streambuf is retained by the caller, which must guarantee that it
+ * remains valid until the handler is called.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the write operation is complete. The signature of the function object
+ * must be:
+ * @code bool completion_condition(
+ * // Result of latest async_write_some_at operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes transferred so far.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of true indicates that the write operation is complete. False
+ * indicates that further calls to the device's async_write_some_at function are
+ * required.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ * // Result of operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes written from the buffers. If an error
+ * // occurred, this will be less than the sum of the buffer sizes.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_service::post().
+ */
+template <typename AsyncRandomAccessWriteDevice, typename Allocator,
+ typename CompletionCondition, typename WriteHandler>
+void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset,
+ basic_streambuf<Allocator>& b, CompletionCondition completion_condition,
+ WriteHandler handler);
+
+/*@}*/
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/impl/write_at.ipp>
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_WRITE_AT_HPP
Added: branches/CMake/release/libs/asio/module.cmake
==============================================================================
--- (empty file)
+++ branches/CMake/release/libs/asio/module.cmake 2008-07-01 14:19:22 EDT (Tue, 01 Jul 2008)
@@ -0,0 +1,2 @@
+boost_module(asio)
+
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk