deleting to reupload

This commit is contained in:
Zach Tibbitts 2007-02-08 20:23:18 +00:00
parent fcf85bd815
commit 0e734f1ccd
199 changed files with 1 additions and 44482 deletions

View File

@ -1,174 +0,0 @@
/*
Copyright (c) 2003, Arvid Norberg, Daniel Wallin
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_ALERT_HPP_INCLUDED
#define TORRENT_ALERT_HPP_INCLUDED
#include <memory>
#include <queue>
#include <string>
#include <cassert>
#include <typeinfo>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/thread/mutex.hpp>
#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/config.hpp"
#define TORRENT_MAX_ALERT_TYPES 10
namespace libtorrent {
class TORRENT_EXPORT alert
{
public:
enum severity_t { debug, info, warning, critical, fatal, none };
alert(severity_t severity, const std::string& msg);
virtual ~alert();
// a timestamp is automatically created in the constructor
boost::posix_time::ptime timestamp() const;
const std::string& msg() const;
severity_t severity() const;
virtual std::auto_ptr<alert> clone() const = 0;
private:
std::string m_msg;
severity_t m_severity;
boost::posix_time::ptime m_timestamp;
};
class TORRENT_EXPORT alert_manager
{
public:
alert_manager();
~alert_manager();
void post_alert(const alert& alert_);
bool pending() const;
std::auto_ptr<alert> get();
void set_severity(alert::severity_t severity);
bool should_post(alert::severity_t severity) const;
private:
std::queue<alert*> m_alerts;
alert::severity_t m_severity;
mutable boost::mutex m_mutex;
};
struct TORRENT_EXPORT unhandled_alert : std::exception
{
unhandled_alert() {}
};
namespace detail {
struct void_;
template<
class Handler
, BOOST_PP_ENUM_PARAMS(TORRENT_MAX_ALERT_TYPES, class T)
>
void handle_alert_dispatch(
const std::auto_ptr<alert>& alert_
, const Handler& handler
, const std::type_info& typeid_
, BOOST_PP_ENUM_BINARY_PARAMS(TORRENT_MAX_ALERT_TYPES, T, *p))
{
if (typeid_ == typeid(T0))
handler(*static_cast<T0*>(alert_.get()));
else
handle_alert_dispatch(
alert_
, handler
, typeid_
, BOOST_PP_ENUM_SHIFTED_PARAMS(TORRENT_MAX_ALERT_TYPES, p), (void_*)0
);
}
template<class Handler>
void handle_alert_dispatch(
const std::auto_ptr<alert>& alert_
, const Handler& handler
, const std::type_info& typeid_
, BOOST_PP_ENUM_PARAMS(TORRENT_MAX_ALERT_TYPES, void_* BOOST_PP_INTERCEPT))
{
throw unhandled_alert();
}
} // namespace detail
template<
BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(TORRENT_MAX_ALERT_TYPES, class T, detail::void_)
>
struct TORRENT_EXPORT handle_alert
{
template<class Handler>
handle_alert(
const std::auto_ptr<alert>& alert_
, const Handler& handler)
{
#define ALERT_POINTER_TYPE(z, n, text) (BOOST_PP_CAT(T, n)*)0
detail::handle_alert_dispatch(
alert_
, handler
, typeid(*alert_)
, BOOST_PP_ENUM(TORRENT_MAX_ALERT_TYPES, ALERT_POINTER_TYPE, _)
);
#undef ALERT_POINTER_TYPE
}
};
} // namespace libtorrent
#endif // TORRENT_ALERT_HPP_INCLUDED

View File

@ -1,300 +0,0 @@
/*
Copyright (c) 2003, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_ALERT_TYPES_HPP_INCLUDED
#define TORRENT_ALERT_TYPES_HPP_INCLUDED
#include "libtorrent/alert.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_connection.hpp"
#include "libtorrent/config.hpp"
namespace libtorrent
{
struct TORRENT_EXPORT tracker_alert: alert
{
tracker_alert(torrent_handle const& h
, int times
, int status
, std::string const& msg)
: alert(alert::warning, msg)
, handle(h)
, times_in_row(times)
, status_code(status)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new tracker_alert(*this)); }
torrent_handle handle;
int times_in_row;
int status_code;
};
struct TORRENT_EXPORT tracker_warning_alert: alert
{
tracker_warning_alert(torrent_handle const& h
, std::string const& msg)
: alert(alert::warning, msg)
, handle(h)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new tracker_warning_alert(*this)); }
torrent_handle handle;
};
struct TORRENT_EXPORT tracker_reply_alert: alert
{
tracker_reply_alert(torrent_handle const& h
, std::string const& msg)
: alert(alert::info, msg)
, handle(h)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new tracker_reply_alert(*this)); }
torrent_handle handle;
};
struct TORRENT_EXPORT tracker_announce_alert: alert
{
tracker_announce_alert(torrent_handle const& h, std::string const& msg)
: alert(alert::info, msg)
, handle(h)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new tracker_announce_alert(*this)); }
torrent_handle handle;
};
struct TORRENT_EXPORT hash_failed_alert: alert
{
hash_failed_alert(
torrent_handle const& h
, int index
, std::string const& msg)
: alert(alert::info, msg)
, handle(h)
, piece_index(index)
{ assert(index >= 0);}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new hash_failed_alert(*this)); }
torrent_handle handle;
int piece_index;
};
struct TORRENT_EXPORT peer_ban_alert: alert
{
peer_ban_alert(tcp::endpoint const& pip, torrent_handle h, std::string const& msg)
: alert(alert::info, msg)
, ip(pip)
, handle(h)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new peer_ban_alert(*this)); }
tcp::endpoint ip;
torrent_handle handle;
};
struct TORRENT_EXPORT peer_error_alert: alert
{
peer_error_alert(tcp::endpoint const& pip, peer_id const& pid_, std::string const& msg)
: alert(alert::debug, msg)
, ip(pip)
, pid(pid_)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new peer_error_alert(*this)); }
tcp::endpoint ip;
peer_id pid;
};
struct TORRENT_EXPORT chat_message_alert: alert
{
chat_message_alert(
const torrent_handle& h
, const tcp::endpoint& sender
, const std::string& msg)
: alert(alert::critical, msg)
, handle(h)
, ip(sender)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new chat_message_alert(*this)); }
torrent_handle handle;
tcp::endpoint ip;
};
struct TORRENT_EXPORT invalid_request_alert: alert
{
invalid_request_alert(
peer_request const& r
, torrent_handle const& h
, tcp::endpoint const& sender
, peer_id const& pid_
, std::string const& msg)
: alert(alert::debug, msg)
, handle(h)
, ip(sender)
, request(r)
, pid(pid_)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new invalid_request_alert(*this)); }
torrent_handle handle;
tcp::endpoint ip;
peer_request request;
peer_id pid;
};
struct TORRENT_EXPORT torrent_finished_alert: alert
{
torrent_finished_alert(
const torrent_handle& h
, const std::string& msg)
: alert(alert::warning, msg)
, handle(h)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new torrent_finished_alert(*this)); }
torrent_handle handle;
};
struct TORRENT_EXPORT url_seed_alert: alert
{
url_seed_alert(
const std::string& url_
, const std::string& msg)
: alert(alert::warning, msg)
, url(url_)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new url_seed_alert(*this)); }
std::string url;
};
struct TORRENT_EXPORT file_error_alert: alert
{
file_error_alert(
const torrent_handle& h
, const std::string& msg)
: alert(alert::fatal, msg)
, handle(h)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new file_error_alert(*this)); }
torrent_handle handle;
};
struct TORRENT_EXPORT metadata_failed_alert: alert
{
metadata_failed_alert(
const torrent_handle& h
, const std::string& msg)
: alert(alert::info, msg)
, handle(h)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new metadata_failed_alert(*this)); }
torrent_handle handle;
};
struct TORRENT_EXPORT metadata_received_alert: alert
{
metadata_received_alert(
const torrent_handle& h
, const std::string& msg)
: alert(alert::info, msg)
, handle(h)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new metadata_received_alert(*this)); }
torrent_handle handle;
};
struct TORRENT_EXPORT listen_failed_alert: alert
{
listen_failed_alert(
const std::string& msg)
: alert(alert::fatal, msg)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new listen_failed_alert(*this)); }
};
struct TORRENT_EXPORT fastresume_rejected_alert: alert
{
fastresume_rejected_alert(torrent_handle const& h
, std::string const& msg)
: alert(alert::warning, msg)
, handle(h)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new fastresume_rejected_alert(*this)); }
torrent_handle handle;
};
}
#endif

View File

@ -1,72 +0,0 @@
/*
Copyright (c) 2003, Magnus Jonsson
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TORRENT_ALLOCATE_RESOURCES_HPP_INCLUDED
#define TORRENT_ALLOCATE_RESOURCES_HPP_INCLUDED
#include <map>
#include <utility>
#include <boost/shared_ptr.hpp>
#include "libtorrent/resource_request.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/socket.hpp"
namespace libtorrent
{
class peer_connection;
class torrent;
int saturated_add(int a, int b);
// Function to allocate a limited resource fairly among many consumers.
// It takes into account the current use, and the consumer's desired use.
// Should be invoked periodically to allow it adjust to the situation (make
// sure "used" is updated between calls!).
// If resources = std::numeric_limits<int>::max() it means there is an infinite
// supply of resources (so everyone can get what they want).
void allocate_resources(
int resources
, std::map<sha1_hash, boost::shared_ptr<torrent> >& torrents
, resource_request torrent::* res);
void allocate_resources(
int resources
, std::map<tcp::endpoint, peer_connection*>& connections
, resource_request peer_connection::* res);
}
#endif

View File

@ -1,71 +0,0 @@
//
// asio.hpp
// ~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_HPP
#define ASIO_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/basic_datagram_socket.hpp"
#include "asio/basic_deadline_timer.hpp"
#include "asio/basic_io_object.hpp"
#include "asio/basic_resolver.hpp"
#include "asio/basic_socket_acceptor.hpp"
#include "asio/basic_socket_iostream.hpp"
#include "asio/basic_socket_streambuf.hpp"
#include "asio/basic_stream_socket.hpp"
#include "asio/basic_streambuf.hpp"
#include "asio/buffer.hpp"
#include "asio/buffered_read_stream_fwd.hpp"
#include "asio/buffered_read_stream.hpp"
#include "asio/buffered_stream_fwd.hpp"
#include "asio/buffered_stream.hpp"
#include "asio/buffered_write_stream_fwd.hpp"
#include "asio/buffered_write_stream.hpp"
#include "asio/completion_condition.hpp"
#include "asio/datagram_socket_service.hpp"
#include "asio/deadline_timer_service.hpp"
#include "asio/deadline_timer.hpp"
#include "asio/error_handler.hpp"
#include "asio/error.hpp"
#include "asio/handler_alloc_hook.hpp"
#include "asio/handler_invoke_hook.hpp"
#include "asio/io_service.hpp"
#include "asio/ip/address.hpp"
#include "asio/ip/address_v4.hpp"
#include "asio/ip/address_v6.hpp"
#include "asio/ip/basic_endpoint.hpp"
#include "asio/ip/basic_resolver_entry.hpp"
#include "asio/ip/basic_resolver_iterator.hpp"
#include "asio/ip/basic_resolver_query.hpp"
#include "asio/ip/host_name.hpp"
#include "asio/ip/multicast.hpp"
#include "asio/ip/resolver_query_base.hpp"
#include "asio/ip/tcp.hpp"
#include "asio/ip/udp.hpp"
#include "asio/is_read_buffered.hpp"
#include "asio/is_write_buffered.hpp"
#include "asio/placeholders.hpp"
#include "asio/read.hpp"
#include "asio/read_until.hpp"
#include "asio/resolver_service.hpp"
#include "asio/socket_acceptor_service.hpp"
#include "asio/socket_base.hpp"
#include "asio/strand.hpp"
#include "asio/stream_socket_service.hpp"
#include "asio/streambuf.hpp"
#include "asio/system_exception.hpp"
#include "asio/thread.hpp"
#include "asio/time_traits.hpp"
#include "asio/write.hpp"
#endif // ASIO_HPP

View File

@ -1,802 +0,0 @@
//
// basic_datagram_socket.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_DATAGRAM_SOCKET_HPP
#define ASIO_BASIC_DATAGRAM_SOCKET_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/basic_socket.hpp"
#include "asio/datagram_socket_service.hpp"
#include "asio/error_handler.hpp"
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.@n
* @e Shared @e objects: Unsafe.
*
* @par Concepts:
* Async_Object, Error_Source.
*/
template <typename Protocol,
typename Service = datagram_socket_service<Protocol> >
class basic_datagram_socket
: public basic_socket<Protocol, Service>
{
public:
/// The native representation of a socket.
typedef typename Service::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(asio::io_service& io_service)
: basic_socket<Protocol, Service>(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 asio::error Thrown on failure.
*/
basic_datagram_socket(asio::io_service& io_service,
const protocol_type& protocol)
: basic_socket<Protocol, Service>(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 asio::error Thrown on failure.
*/
basic_datagram_socket(asio::io_service& io_service,
const endpoint_type& endpoint)
: basic_socket<Protocol, Service>(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 asio::error Thrown on failure.
*/
basic_datagram_socket(asio::io_service& io_service,
const protocol_type& protocol, const native_type& native_socket)
: basic_socket<Protocol, Service>(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 asio::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(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 Const_Buffers>
std::size_t send(const Const_Buffers& buffers)
{
return this->service.send(this->implementation, buffers, 0, throw_error());
}
/// 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 asio::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 Const_Buffers>
std::size_t send(const Const_Buffers& buffers,
socket_base::message_flags flags)
{
return this->service.send(this->implementation, buffers, flags,
throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation.
* ); @endcode
*
* @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 Const_Buffers, typename Error_Handler>
std::size_t send(const Const_Buffers& buffers,
socket_base::message_flags flags, Error_Handler error_handler)
{
return this->service.send(this->implementation, buffers, flags,
error_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 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 asio::error& 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
* 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(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 Const_Buffers, typename Handler>
void async_send(const Const_Buffers& buffers, Handler 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 asio::error& 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
* 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 Const_Buffers, typename Handler>
void async_send(const Const_Buffers& buffers,
socket_base::message_flags flags, Handler 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 asio::error Thrown on failure.
*
* @par Example:
* To send a single data buffer use the @ref buffer function as follows:
* @code
* asio::ip::udp::endpoint destination(
* asio::ip::address::from_string("1.2.3.4"), 12345);
* socket.send_to(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 Const_Buffers>
std::size_t send_to(const Const_Buffers& buffers,
const endpoint_type& destination)
{
return this->service.send_to(this->implementation, buffers, destination, 0,
throw_error());
}
/// 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 asio::error Thrown on failure.
*/
template <typename Const_Buffers>
std::size_t send_to(const Const_Buffers& buffers,
const endpoint_type& destination, socket_base::message_flags flags)
{
return this->service.send_to(this->implementation, buffers, destination,
flags, throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation.
* ); @endcode
*
* @returns The number of bytes sent.
*/
template <typename Const_Buffers, typename Error_Handler>
std::size_t send_to(const Const_Buffers& buffers,
const endpoint_type& destination, socket_base::message_flags flags,
Error_Handler error_handler)
{
return this->service.send_to(this->implementation, buffers, destination,
flags, error_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 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 asio::error& 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
* asio::io_service::post().
*
* @par Example:
* To send a single data buffer use the @ref buffer function as follows:
* @code
* asio::ip::udp::endpoint destination(
* asio::ip::address::from_string("1.2.3.4"), 12345);
* socket.async_send_to(
* 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 Const_Buffers, typename Handler>
void async_send_to(const Const_Buffers& buffers,
const endpoint_type& destination, Handler 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 asio::error& 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
* asio::io_service::post().
*/
template <typename Const_Buffers, typename Handler>
void async_send_to(const Const_Buffers& buffers,
const endpoint_type& destination, socket_base::message_flags flags,
Handler 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 asio::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(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 Mutable_Buffers>
std::size_t receive(const Mutable_Buffers& buffers)
{
return this->service.receive(this->implementation, buffers, 0,
throw_error());
}
/// 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 asio::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 Mutable_Buffers>
std::size_t receive(const Mutable_Buffers& buffers,
socket_base::message_flags flags)
{
return this->service.receive(this->implementation, buffers, flags,
throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation.
* ); @endcode
*
* @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 Mutable_Buffers, typename Error_Handler>
std::size_t receive(const Mutable_Buffers& buffers,
socket_base::message_flags flags, Error_Handler error_handler)
{
return this->service.receive(this->implementation, buffers, flags,
error_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 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 asio::error& 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
* 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(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 Mutable_Buffers, typename Handler>
void async_receive(const Mutable_Buffers& buffers, Handler 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 asio::error& 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
* 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 Mutable_Buffers, typename Handler>
void async_receive(const Mutable_Buffers& buffers,
socket_base::message_flags flags, Handler 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 asio::error Thrown on failure.
*
* @par Example:
* To receive into a single data buffer use the @ref buffer function as
* follows:
* @code
* asio::ip::udp::endpoint sender_endpoint;
* socket.receive_from(
* 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 Mutable_Buffers>
std::size_t receive_from(const Mutable_Buffers& buffers,
endpoint_type& sender_endpoint)
{
return this->service.receive_from(this->implementation, buffers,
sender_endpoint, 0, throw_error());
}
/// 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 asio::error Thrown on failure.
*/
template <typename Mutable_Buffers>
std::size_t receive_from(const Mutable_Buffers& buffers,
endpoint_type& sender_endpoint, socket_base::message_flags flags)
{
return this->service.receive_from(this->implementation, buffers,
sender_endpoint, flags, throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation.
* ); @endcode
*
* @returns The number of bytes received.
*/
template <typename Mutable_Buffers, typename Error_Handler>
std::size_t receive_from(const Mutable_Buffers& buffers,
endpoint_type& sender_endpoint, socket_base::message_flags flags,
Error_Handler error_handler)
{
return this->service.receive_from(this->implementation, buffers,
sender_endpoint, flags, error_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 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 asio::error& 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
* 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(
* 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 Mutable_Buffers, typename Handler>
void async_receive_from(const Mutable_Buffers& buffers,
endpoint_type& sender_endpoint, Handler 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 asio::error& 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
* asio::io_service::post().
*/
template <typename Mutable_Buffers, typename Handler>
void async_receive_from(const Mutable_Buffers& buffers,
endpoint_type& sender_endpoint, socket_base::message_flags flags,
Handler handler)
{
this->service.async_receive_from(this->implementation, buffers,
sender_endpoint, flags, handler);
}
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_DATAGRAM_SOCKET_HPP

View File

@ -1,309 +0,0 @@
//
// basic_deadline_timer.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_DEADLINE_TIMER_HPP
#define ASIO_BASIC_DEADLINE_TIMER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/basic_io_object.hpp"
#include "asio/deadline_timer_service.hpp"
#include "asio/error.hpp"
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 asio::deadline_timer typedef.
*
* @par Thread Safety:
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*
* @par Concepts:
* Async_Object, Error_Source.
*
* @sa @ref deadline_timer_reset
*
* @par Examples:
* Performing a blocking wait:
* @code
* // Construct a timer without setting an expiry time.
* 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 asio::error& error)
* {
* if (!error)
* {
* // Timer expired.
* }
* }
*
* ...
*
* // Construct a timer with an absolute expiry time.
* 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
*/
template <typename Time_Type,
typename Time_Traits = asio::time_traits<Time_Type>,
typename Service = deadline_timer_service<Time_Type, Time_Traits> >
class basic_deadline_timer
: public basic_io_object<Service>
{
public:
/// The type used for reporting errors.
typedef asio::error error_type;
/// The time traits type.
typedef Time_Traits 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(asio::io_service& io_service)
: basic_io_object<Service>(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(asio::io_service& io_service,
const time_type& expiry_time)
: basic_io_object<Service>(io_service)
{
this->service.expires_at(this->implementation, expiry_time);
}
/// 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(asio::io_service& io_service,
const duration_type& expiry_time)
: basic_io_object<Service>(io_service)
{
this->service.expires_from_now(this->implementation, expiry_time);
}
/// 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 asio::error::operation_aborted error code.
*
* Cancelling the timer does not change the expiry time.
*
* @return The number of asynchronous operations that were cancelled.
*/
std::size_t cancel()
{
return this->service.cancel(this->implementation);
}
/// 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 asio::error::operation_aborted error code.
*
* See @ref deadline_timer_reset for more information on altering the expiry
* time of an active timer.
*
* @param expiry_time The expiry time to be used for the timer.
*
* @return The number of asynchronous operations that were cancelled.
*/
std::size_t expires_at(const time_type& expiry_time)
{
return this->service.expires_at(this->implementation, expiry_time);
}
/// 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 asio::error::operation_aborted error code.
*
* See @ref deadline_timer_reset for more information on altering the expiry
* time of an active timer.
*
* @param expiry_time The expiry time to be used for the timer.
*
* @return The number of asynchronous operations that were cancelled.
*/
std::size_t expires_from_now(const duration_type& expiry_time)
{
return this->service.expires_from_now(this->implementation, expiry_time);
}
/// 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 asio::error Thrown on failure.
*/
void wait()
{
this->service.wait(this->implementation);
}
/// 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 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 asio::error& 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
* asio::io_service::post().
*/
template <typename Handler>
void async_wait(Handler handler)
{
this->service.async_wait(this->implementation, handler);
}
};
/**
* @page deadline_timer_reset 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 asio::error& e)
* {
* if (e != asio::error::operation_aborted)
* {
* // Timer was not cancelled, take necessary action.
* }
* }
* @endcode
*
* @li The 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 asio::error passed to it
* contains the value asio::error::operation_aborted.
*
* @sa asio::basic_deadline_timer
*/
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_DEADLINE_TIMER_HPP

View File

@ -1,75 +0,0 @@
//
// basic_io_object.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_IO_OBJECT_HPP
#define ASIO_BASIC_IO_OBJECT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/io_service.hpp"
#include "asio/detail/noncopyable.hpp"
namespace asio {
/// Base class for all I/O objects.
template <typename Service>
class basic_io_object
: private noncopyable
{
public:
/// The type of the service that will be used to provide I/O operations.
typedef Service service_type;
/// The underlying implementation type of I/O object.
typedef typename service_type::implementation_type implementation_type;
/// 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.
*/
asio::io_service& io_service()
{
return service.io_service();
}
protected:
/// Construct a basic_io_object.
explicit basic_io_object(asio::io_service& io_service)
: service(asio::use_service<Service>(io_service))
{
service.construct(implementation);
}
/// Protected destructor to prevent deletion through this type.
~basic_io_object()
{
service.destroy(implementation);
}
// The backend service implementation.
service_type& service;
// The underlying native implementation.
implementation_type implementation;
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_IO_OBJECT_HPP

View File

@ -1,252 +0,0 @@
//
// basic_resolver.hpp
// ~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_RESOLVER_HPP
#define ASIO_BASIC_RESOLVER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/basic_io_object.hpp"
#include "asio/error.hpp"
#include "asio/error_handler.hpp"
#include "asio/resolver_service.hpp"
namespace asio {
/// 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.@n
* @e Shared @e objects: Unsafe.
*
* @par Concepts:
* Async_Object, Error_Source.
*/
template <typename Protocol, typename Service = resolver_service<Protocol> >
class basic_resolver
: public basic_io_object<Service>
{
public:
/// The protocol type.
typedef Protocol protocol_type;
/// The endpoint type.
typedef typename Protocol::endpoint endpoint_type;
/// The query type.
typedef typename Protocol::resolver_query query;
/// The iterator type.
typedef typename Protocol::resolver_iterator iterator;
/// The type used for reporting errors.
typedef asio::error error_type;
/// 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(asio::io_service& io_service)
: basic_io_object<Service>(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 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 asio::error Thrown on failure.
*
* @note A default constructed iterator represents the end of the list.
*
* @note A successful call to this function is guaranteed to return at least
* one entry.
*/
iterator resolve(const query& q)
{
return this->service.resolve(this->implementation, q, throw_error());
}
/// 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. Returns a default constructed iterator if an error
* occurs.
*
* @param error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation.
* ); @endcode
*
* @note A default constructed iterator represents the end of the list.
*
* @note A successful call to this function is guaranteed to return at least
* one entry.
*/
template <typename Error_Handler>
iterator resolve(const query& q, Error_Handler error_handler)
{
return this->service.resolve(this->implementation, q, error_handler);
}
/// 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 asio::error& 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
* asio::io_service::post().
*
* @note A default constructed iterator represents the end of the list.
*
* @note A successful resolve operation is guaranteed to pass at least one
* entry to the handler.
*/
template <typename Handler>
void async_resolve(const query& q, Handler 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 asio::error Thrown on failure.
*
* @note A default constructed iterator represents the end of the list.
*
* @note A successful call to this function is guaranteed to return at least
* one entry.
*/
iterator resolve(const endpoint_type& e)
{
return this->service.resolve(this->implementation, e, throw_error());
}
/// 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. Returns a default constructed iterator if an error
* occurs.
*
* @param error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation.
* ); @endcode
*
* @note A default constructed iterator represents the end of the list.
*
* @note A successful call to this function is guaranteed to return at least
* one entry.
*/
template <typename Error_Handler>
iterator resolve(const endpoint_type& e, Error_Handler error_handler)
{
return this->service.resolve(this->implementation, e, error_handler);
}
/// 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 asio::error& 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
* asio::io_service::post().
*
* @note A default constructed iterator represents the end of the list.
*
* @note A successful resolve operation is guaranteed to pass at least one
* entry to the handler.
*/
template <typename Handler>
void async_resolve(const endpoint_type& e, Handler handler)
{
return this->service.async_resolve(this->implementation, e, handler);
}
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_RESOLVER_HPP

View File

@ -1,919 +0,0 @@
//
// basic_socket.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_SOCKET_HPP
#define ASIO_BASIC_SOCKET_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/basic_io_object.hpp"
#include "asio/error.hpp"
#include "asio/error_handler.hpp"
#include "asio/socket_base.hpp"
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.@n
* @e Shared @e objects: Unsafe.
*
* @par Concepts:
* Error_Source, IO_Object.
*/
template <typename Protocol, typename Service>
class basic_socket
: public basic_io_object<Service>,
public socket_base
{
public:
/// The native representation of a socket.
typedef typename Service::native_type native_type;
/// The protocol type.
typedef Protocol protocol_type;
/// The endpoint type.
typedef typename Protocol::endpoint endpoint_type;
/// The type used for reporting errors.
typedef asio::error error_type;
/// A basic_socket is always the lowest layer.
typedef basic_socket<Protocol, Service> 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(asio::io_service& io_service)
: basic_io_object<Service>(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 asio::error Thrown on failure.
*/
basic_socket(asio::io_service& io_service,
const protocol_type& protocol)
: basic_io_object<Service>(io_service)
{
this->service.open(this->implementation, protocol, throw_error());
}
/// 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 asio::error Thrown on failure.
*/
basic_socket(asio::io_service& io_service,
const endpoint_type& endpoint)
: basic_io_object<Service>(io_service)
{
this->service.open(this->implementation, endpoint.protocol(),
throw_error());
this->service.bind(this->implementation, endpoint, throw_error());
}
/// 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 asio::error Thrown on failure.
*/
basic_socket(asio::io_service& io_service,
const protocol_type& protocol, const native_type& native_socket)
: basic_io_object<Service>(io_service)
{
this->service.assign(this->implementation, protocol, native_socket,
throw_error());
}
/// 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 asio::error Thrown on failure.
*
* @par Example:
* @code
* asio::ip::tcp::socket socket(io_service);
* socket.open(asio::ip::tcp::v4());
* @endcode
*/
void open(const protocol_type& protocol = protocol_type())
{
this->service.open(this->implementation, protocol, throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @par Example:
* @code
* asio::ip::tcp::socket socket(io_service);
* asio::error error;
* socket.open(asio::ip::tcp::v4(), asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename Error_Handler>
void open(const protocol_type& protocol, Error_Handler error_handler)
{
this->service.open(this->implementation, protocol, error_handler);
}
/// 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 asio::error Thrown on failure.
*/
void assign(const protocol_type& protocol, const native_type& native_socket)
{
this->service.assign(this->implementation, protocol, native_socket,
throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*/
template <typename Error_Handler>
void assign(const protocol_type& protocol, const native_type& native_socket,
Error_Handler error_handler)
{
this->service.assign(this->implementation, protocol, native_socket,
error_handler);
}
/// 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 asio::error::operation_aborted error.
*
* @throws asio::error Thrown on failure.
*/
void close()
{
this->service.close(this->implementation, throw_error());
}
/// 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 asio::error::operation_aborted error.
*
* @param error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @par Example:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::error error;
* socket.close(asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename Error_Handler>
void close(Error_Handler error_handler)
{
this->service.close(this->implementation, error_handler);
}
/// 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 asio::error::operation_aborted error.
*
* @throws asio::error Thrown on failure.
*/
void cancel()
{
this->service.cancel(this->implementation, throw_error());
}
/// 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 asio::error::operation_aborted error.
*
* @param error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*/
template <typename Error_Handler>
void cancel(Error_Handler error_handler)
{
this->service.cancel(this->implementation, error_handler);
}
/// 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 asio::error Thrown on failure.
*
* @par Example:
* @code
* asio::ip::tcp::socket socket(io_service);
* socket.open(asio::ip::tcp::v4());
* socket.bind(asio::ip::tcp::endpoint(
* asio::ip::tcp::v4(), 12345));
* @endcode
*/
void bind(const endpoint_type& endpoint)
{
this->service.bind(this->implementation, endpoint, throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @par Example:
* @code
* asio::ip::tcp::socket socket(io_service);
* socket.open(asio::ip::tcp::v4());
* asio::error error;
* socket.bind(asio::ip::tcp::endpoint(
* asio::ip::tcp::v4(), 12345),
* asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename Error_Handler>
void bind(const endpoint_type& endpoint, Error_Handler error_handler)
{
this->service.bind(this->implementation, endpoint, error_handler);
}
/// 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 asio::error Thrown on failure.
*
* @par Example:
* @code
* asio::ip::tcp::socket socket(io_service);
* asio::ip::tcp::endpoint endpoint(
* asio::ip::address::from_string("1.2.3.4"), 12345);
* socket.connect(endpoint);
* @endcode
*/
void connect(const endpoint_type& peer_endpoint)
{
this->service.connect(this->implementation, peer_endpoint, throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @par Example:
* @code
* asio::ip::tcp::socket socket(io_service);
* asio::ip::tcp::endpoint endpoint(
* asio::ip::address::from_string("1.2.3.4"), 12345);
* asio::error error;
* socket.connect(endpoint, asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename Error_Handler>
void connect(const endpoint_type& peer_endpoint, Error_Handler error_handler)
{
this->service.connect(this->implementation, peer_endpoint, error_handler);
}
/// 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 asio::error& 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
* asio::io_service::post().
*
* @par Example:
* @code
* void connect_handler(const asio::error& error)
* {
* if (!error)
* {
* // Connect succeeded.
* }
* }
*
* ...
*
* asio::ip::tcp::socket socket(io_service);
* asio::ip::tcp::endpoint endpoint(
* asio::ip::address::from_string("1.2.3.4"), 12345);
* socket.async_connect(endpoint, connect_handler);
* @endcode
*/
template <typename Handler>
void async_connect(const endpoint_type& peer_endpoint, Handler handler)
{
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 asio::error Thrown on failure.
*
* @sa Socket_Option @n
* asio::socket_base::broadcast @n
* asio::socket_base::do_not_route @n
* asio::socket_base::keep_alive @n
* asio::socket_base::linger @n
* asio::socket_base::receive_buffer_size @n
* asio::socket_base::receive_low_watermark @n
* asio::socket_base::reuse_address @n
* asio::socket_base::send_buffer_size @n
* asio::socket_base::send_low_watermark @n
* asio::ip::multicast::join_group @n
* asio::ip::multicast::leave_group @n
* asio::ip::multicast::enable_loopback @n
* asio::ip::multicast::outbound_interface @n
* asio::ip::multicast::hops @n
* asio::ip::tcp::no_delay
*
* @par Example:
* Setting the IPPROTO_TCP/TCP_NODELAY option:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::ip::tcp::no_delay option(true);
* socket.set_option(option);
* @endcode
*/
template <typename Socket_Option>
void set_option(const Socket_Option& option)
{
this->service.set_option(this->implementation, option, throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @sa Socket_Option @n
* asio::socket_base::broadcast @n
* asio::socket_base::do_not_route @n
* asio::socket_base::keep_alive @n
* asio::socket_base::linger @n
* asio::socket_base::receive_buffer_size @n
* asio::socket_base::receive_low_watermark @n
* asio::socket_base::reuse_address @n
* asio::socket_base::send_buffer_size @n
* asio::socket_base::send_low_watermark @n
* asio::ip::multicast::join_group @n
* asio::ip::multicast::leave_group @n
* asio::ip::multicast::enable_loopback @n
* asio::ip::multicast::outbound_interface @n
* asio::ip::multicast::hops @n
* asio::ip::tcp::no_delay
*
* @par Example:
* Setting the IPPROTO_TCP/TCP_NODELAY option:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::ip::tcp::no_delay option(true);
* asio::error error;
* socket.set_option(option, asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename Socket_Option, typename Error_Handler>
void set_option(const Socket_Option& option, Error_Handler error_handler)
{
this->service.set_option(this->implementation, option, error_handler);
}
/// 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 asio::error Thrown on failure.
*
* @sa Socket_Option @n
* asio::socket_base::broadcast @n
* asio::socket_base::do_not_route @n
* asio::socket_base::keep_alive @n
* asio::socket_base::linger @n
* asio::socket_base::receive_buffer_size @n
* asio::socket_base::receive_low_watermark @n
* asio::socket_base::reuse_address @n
* asio::socket_base::send_buffer_size @n
* asio::socket_base::send_low_watermark @n
* asio::ip::multicast::join_group @n
* asio::ip::multicast::leave_group @n
* asio::ip::multicast::enable_loopback @n
* asio::ip::multicast::outbound_interface @n
* asio::ip::multicast::hops @n
* asio::ip::tcp::no_delay
*
* @par Example:
* Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::ip::tcp::socket::keep_alive option;
* socket.get_option(option);
* bool is_set = option.get();
* @endcode
*/
template <typename Socket_Option>
void get_option(Socket_Option& option) const
{
this->service.get_option(this->implementation, option, throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @sa Socket_Option @n
* asio::socket_base::broadcast @n
* asio::socket_base::do_not_route @n
* asio::socket_base::keep_alive @n
* asio::socket_base::linger @n
* asio::socket_base::receive_buffer_size @n
* asio::socket_base::receive_low_watermark @n
* asio::socket_base::reuse_address @n
* asio::socket_base::send_buffer_size @n
* asio::socket_base::send_low_watermark @n
* asio::ip::multicast::join_group @n
* asio::ip::multicast::leave_group @n
* asio::ip::multicast::enable_loopback @n
* asio::ip::multicast::outbound_interface @n
* asio::ip::multicast::hops @n
* asio::ip::tcp::no_delay
*
* @par Example:
* Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::ip::tcp::socket::keep_alive option;
* asio::error error;
* socket.get_option(option, asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* bool is_set = option.get();
* @endcode
*/
template <typename Socket_Option, typename Error_Handler>
void get_option(Socket_Option& option, Error_Handler error_handler) const
{
this->service.get_option(this->implementation, option, error_handler);
}
/// 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 asio::error Thrown on failure.
*
* @sa IO_Control_Command @n
* asio::socket_base::bytes_readable @n
* asio::socket_base::non_blocking_io
*
* @par Example:
* Getting the number of bytes ready to read:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::ip::tcp::socket::bytes_readable command;
* socket.io_control(command);
* std::size_t bytes_readable = command.get();
* @endcode
*/
template <typename IO_Control_Command>
void io_control(IO_Control_Command& command)
{
this->service.io_control(this->implementation, command, throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @sa IO_Control_Command @n
* asio::socket_base::bytes_readable @n
* asio::socket_base::non_blocking_io
*
* @par Example:
* Getting the number of bytes ready to read:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::ip::tcp::socket::bytes_readable command;
* asio::error error;
* socket.io_control(command, asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* std::size_t bytes_readable = command.get();
* @endcode
*/
template <typename IO_Control_Command, typename Error_Handler>
void io_control(IO_Control_Command& command, Error_Handler error_handler)
{
this->service.io_control(this->implementation, command, error_handler);
}
/// 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 asio::error Thrown on failure.
*
* @par Example:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::ip::tcp::endpoint endpoint = socket.local_endpoint();
* @endcode
*/
endpoint_type local_endpoint() const
{
return this->service.local_endpoint(this->implementation, throw_error());
}
/// Get the local endpoint of the socket.
/**
* This function is used to obtain the locally bound endpoint of the socket.
*
* @param error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @returns An object that represents the local endpoint of the socket.
* Returns a default-constructed endpoint object if an error occurred and the
* error handler did not throw an exception.
*
* @par Example:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::error error;
* asio::ip::tcp::endpoint endpoint
* = socket.local_endpoint(asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename Error_Handler>
endpoint_type local_endpoint(Error_Handler error_handler) const
{
return this->service.local_endpoint(this->implementation, error_handler);
}
/// 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 asio::error Thrown on failure.
*
* @par Example:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::ip::tcp::endpoint endpoint = socket.remote_endpoint();
* @endcode
*/
endpoint_type remote_endpoint() const
{
return this->service.remote_endpoint(this->implementation, throw_error());
}
/// Get the remote endpoint of the socket.
/**
* This function is used to obtain the remote endpoint of the socket.
*
* @param error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @returns An object that represents the remote endpoint of the socket.
* Returns a default-constructed endpoint object if an error occurred and the
* error handler did not throw an exception.
*
* @par Example:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::error error;
* asio::ip::tcp::endpoint endpoint
* = socket.remote_endpoint(asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename Error_Handler>
endpoint_type remote_endpoint(Error_Handler error_handler) const
{
return this->service.remote_endpoint(this->implementation, error_handler);
}
/// 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 asio::error Thrown on failure.
*
* @par Example:
* Shutting down the send side of the socket:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* socket.shutdown(asio::ip::tcp::socket::shutdown_send);
* @endcode
*/
void shutdown(shutdown_type what)
{
this->service.shutdown(this->implementation, what, throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @par Example:
* Shutting down the send side of the socket:
* @code
* asio::ip::tcp::socket socket(io_service);
* ...
* asio::error error;
* socket.shutdown(asio::ip::tcp::socket::shutdown_send,
* asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename Error_Handler>
void shutdown(shutdown_type what, Error_Handler error_handler)
{
this->service.shutdown(this->implementation, what, error_handler);
}
protected:
/// Protected destructor to prevent deletion through this type.
~basic_socket()
{
}
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_SOCKET_HPP

View File

@ -1,854 +0,0 @@
//
// basic_socket_acceptor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_SOCKET_ACCEPTOR_HPP
#define ASIO_BASIC_SOCKET_ACCEPTOR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/basic_io_object.hpp"
#include "asio/basic_socket.hpp"
#include "asio/error.hpp"
#include "asio/error_handler.hpp"
#include "asio/socket_acceptor_service.hpp"
#include "asio/socket_base.hpp"
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.@n
* @e Shared @e objects: Unsafe.
*
* @par Concepts:
* Async_Object, Error_Source.
*
* @par Example:
* Opening a socket acceptor with the SO_REUSEADDR option enabled:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), port);
* acceptor.open(endpoint.protocol());
* acceptor.set_option(asio::ip::tcp::acceptor::reuse_address(true));
* acceptor.bind(endpoint);
* acceptor.listen();
* @endcode
*/
template <typename Protocol,
typename Service = socket_acceptor_service<Protocol> >
class basic_socket_acceptor
: public basic_io_object<Service>,
public socket_base
{
public:
/// The native representation of an acceptor.
typedef typename Service::native_type native_type;
/// The protocol type.
typedef Protocol protocol_type;
/// The endpoint type.
typedef typename Protocol::endpoint endpoint_type;
/// The type used for reporting errors.
typedef asio::error error_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(asio::io_service& io_service)
: basic_io_object<Service>(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 asio::error Thrown on failure.
*/
basic_socket_acceptor(asio::io_service& io_service,
const protocol_type& protocol)
: basic_io_object<Service>(io_service)
{
this->service.open(this->implementation, protocol, throw_error());
}
/// 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 asio::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(asio::io_service& io_service,
const endpoint_type& endpoint, bool reuse_addr = true)
: basic_io_object<Service>(io_service)
{
this->service.open(this->implementation, endpoint.protocol(),
throw_error());
if (reuse_addr)
{
this->service.set_option(this->implementation,
socket_base::reuse_address(true), throw_error());
}
this->service.bind(this->implementation, endpoint, throw_error());
this->service.listen(this->implementation,
socket_base::max_connections, throw_error());
}
/// 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 asio::error Thrown on failure.
*/
basic_socket_acceptor(asio::io_service& io_service,
const protocol_type& protocol, const native_type& native_acceptor)
: basic_io_object<Service>(io_service)
{
this->service.assign(this->implementation, protocol, native_acceptor,
throw_error());
}
/// 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.
*
* @par Example:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* acceptor.open(asio::ip::tcp::v4());
* @endcode
*/
void open(const protocol_type& protocol = protocol_type())
{
this->service.open(this->implementation, protocol, throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @par Example:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* asio::error error;
* acceptor.open(asio::ip::tcp::v4(),
* asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename Error_Handler>
void open(const protocol_type& protocol, Error_Handler error_handler)
{
this->service.open(this->implementation, protocol, error_handler);
}
/// 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 asio::error Thrown on failure.
*/
void assign(const protocol_type& protocol, const native_type& native_acceptor)
{
this->service.assign(this->implementation, protocol, native_acceptor,
throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*/
template <typename Error_Handler>
void assign(const protocol_type& protocol, const native_type& native_acceptor,
Error_Handler error_handler)
{
this->service.assign(this->implementation, protocol, native_acceptor,
error_handler);
}
/// 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 asio::error Thrown on failure.
*
* @par Example:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* acceptor.open(asio::ip::tcp::v4());
* acceptor.bind(asio::ip::tcp::endpoint(12345));
* @endcode
*/
void bind(const endpoint_type& endpoint)
{
this->service.bind(this->implementation, endpoint, throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @par Example:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* acceptor.open(asio::ip::tcp::v4());
* asio::error error;
* acceptor.bind(asio::ip::tcp::endpoint(12345),
* asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename Error_Handler>
void bind(const endpoint_type& endpoint, Error_Handler error_handler)
{
this->service.bind(this->implementation, endpoint, error_handler);
}
/// 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.
*/
void listen(int backlog = socket_base::max_connections)
{
this->service.listen(this->implementation, backlog, throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @par Example:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::error error;
* acceptor.listen(asio::socket_base::max_connections,
* asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename Error_Handler>
void listen(int backlog, Error_Handler error_handler)
{
this->service.listen(this->implementation, backlog, error_handler);
}
/// 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 asio::error Thrown on failure.
*/
void close()
{
this->service.close(this->implementation, throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @par Example:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::error error;
* acceptor.close(asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename Error_Handler>
void close(Error_Handler error_handler)
{
this->service.close(this->implementation, error_handler);
}
/// 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 asio::error::operation_aborted error.
*
* @throws asio::error Thrown on failure.
*/
void cancel()
{
this->service.cancel(this->implementation, throw_error());
}
/// 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 asio::error::operation_aborted error.
*
* @param error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*/
template <typename Error_Handler>
void cancel(Error_Handler error_handler)
{
this->service.cancel(this->implementation, error_handler);
}
/// 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 asio::error Thrown on failure.
*
* @sa Socket_Option @n
* asio::socket_base::reuse_address
* asio::socket_base::enable_connection_aborted
*
* @par Example:
* Setting the SOL_SOCKET/SO_REUSEADDR option:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::acceptor::reuse_address option(true);
* acceptor.set_option(option);
* @endcode
*/
template <typename Option>
void set_option(const Option& option)
{
this->service.set_option(this->implementation, option, throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @sa Socket_Option @n
* asio::socket_base::reuse_address
* asio::socket_base::enable_connection_aborted
*
* @par Example:
* Setting the SOL_SOCKET/SO_REUSEADDR option:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::acceptor::reuse_address option(true);
* asio::error error;
* acceptor.set_option(option, asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename Option, typename Error_Handler>
void set_option(const Option& option, Error_Handler error_handler)
{
this->service.set_option(this->implementation, option, error_handler);
}
/// 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 asio::error Thrown on failure.
*
* @sa Socket_Option @n
* asio::socket_base::reuse_address
*
* @par Example:
* Getting the value of the SOL_SOCKET/SO_REUSEADDR option:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::acceptor::reuse_address option;
* acceptor.get_option(option);
* bool is_set = option.get();
* @endcode
*/
template <typename Option>
void get_option(Option& option)
{
this->service.get_option(this->implementation, option, throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @sa Socket_Option @n
* asio::socket_base::reuse_address
*
* @par Example:
* Getting the value of the SOL_SOCKET/SO_REUSEADDR option:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::acceptor::reuse_address option;
* asio::error error;
* acceptor.get_option(option, asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* bool is_set = option.get();
* @endcode
*/
template <typename Option, typename Error_Handler>
void get_option(Option& option, Error_Handler error_handler)
{
this->service.get_option(this->implementation, option, error_handler);
}
/// 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 asio::error Thrown on failure.
*
* @par Example:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint();
* @endcode
*/
endpoint_type local_endpoint() const
{
return this->service.local_endpoint(this->implementation, throw_error());
}
/// Get the local endpoint of the acceptor.
/**
* This function is used to obtain the locally bound endpoint of the acceptor.
*
* @param error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @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
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::error error;
* asio::ip::tcp::endpoint endpoint
* = acceptor.local_endpoint(asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename Error_Handler>
endpoint_type local_endpoint(Error_Handler error_handler) const
{
return this->service.local_endpoint(this->implementation, error_handler);
}
/// 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 asio::error Thrown on failure.
*
* @par Example:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::socket socket(io_service);
* acceptor.accept(socket);
* @endcode
*/
template <typename Socket_Service>
void accept(basic_socket<protocol_type, Socket_Service>& peer)
{
this->service.accept(this->implementation, peer, throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @par Example:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::soocket socket(io_service);
* asio::error error;
* acceptor.accept(socket, asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename Socket_Service, typename Error_Handler>
void accept(basic_socket<protocol_type, Socket_Service>& peer,
Error_Handler error_handler)
{
this->service.accept(this->implementation, peer, error_handler);
}
/// 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 asio::error& 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
* asio::io_service::post().
*
* @par Example:
* @code
* void accept_handler(const asio::error& error)
* {
* if (!error)
* {
* // Accept succeeded.
* }
* }
*
* ...
*
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::socket socket(io_service);
* acceptor.async_accept(socket, accept_handler);
* @endcode
*/
template <typename Socket_Service, typename Handler>
void async_accept(basic_socket<protocol_type, Socket_Service>& peer,
Handler handler)
{
this->service.async_accept(this->implementation, peer, 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 asio::error Thrown on failure.
*
* @par Example:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::socket socket(io_service);
* asio::ip::tcp::endpoint endpoint;
* acceptor.accept_endpoint(socket, endpoint);
* @endcode
*/
template <typename Socket_Service>
void accept_endpoint(basic_socket<protocol_type, Socket_Service>& peer,
endpoint_type& peer_endpoint)
{
this->service.accept_endpoint(this->implementation, peer, peer_endpoint,
throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @par Example:
* @code
* asio::ip::tcp::acceptor acceptor(io_service);
* ...
* asio::ip::tcp::socket socket(io_service);
* asio::ip::tcp::endpoint endpoint;
* asio::error error;
* acceptor.accept_endpoint(socket, endpoint,
* asio::assign_error(error));
* if (error)
* {
* // An error occurred.
* }
* @endcode
*/
template <typename Socket_Service, typename Error_Handler>
void accept_endpoint(basic_socket<protocol_type, Socket_Service>& peer,
endpoint_type& peer_endpoint, Error_Handler error_handler)
{
this->service.accept_endpoint(this->implementation, peer, peer_endpoint,
error_handler);
}
/// 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 asio::error& 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
* asio::io_service::post().
*/
template <typename Socket_Service, typename Handler>
void async_accept_endpoint(basic_socket<protocol_type, Socket_Service>& peer,
endpoint_type& peer_endpoint, Handler handler)
{
this->service.async_accept_endpoint(this->implementation, peer,
peer_endpoint, handler);
}
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_SOCKET_ACCEPTOR_HPP

View File

@ -1,176 +0,0 @@
//
// basic_socket_iostream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_SOCKET_IOSTREAM_HPP
#define ASIO_BASIC_SOCKET_IOSTREAM_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/utility/base_from_member.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/basic_socket_streambuf.hpp"
#include "asio/stream_socket_service.hpp"
#if !defined(ASIO_SOCKET_IOSTREAM_MAX_ARITY)
#define ASIO_SOCKET_IOSTREAM_MAX_ARITY 5
#endif // !defined(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, Service> >::member)
// {
// try
// {
// rdbuf()->connect ( x1, ..., xn );
// }
// catch (asio::error&)
// {
// this->setstate(std::ios_base::failbit);
// if (this->exceptions() & std::ios_base::failbit)
// throw;
// }
// }
// This macro should only persist within this file.
#define 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, Service> >::member) \
{ \
try \
{ \
rdbuf()->connect( BOOST_PP_ENUM_PARAMS(n, x) ); \
} \
catch (asio::error&) \
{ \
this->setstate(std::ios_base::failbit); \
if (this->exceptions() & std::ios_base::failbit) \
throw; \
} \
} \
/**/
// A macro that should expand to:
// template < typename T1, ..., typename Tn >
// void connect( T1 x1, ..., Tn xn )
// {
// try
// {
// rdbuf()->connect ( x1, ..., xn );
// }
// catch (asio::error&)
// {
// this->setstate(std::ios_base::failbit);
// if (this->exceptions() & std::ios_base::failbit)
// throw;
// }
// }
// This macro should only persist within this file.
#define 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) ) \
{ \
try \
{ \
rdbuf()->connect( BOOST_PP_ENUM_PARAMS(n, x) ); \
} \
catch (asio::error&) \
{ \
this->setstate(std::ios_base::failbit); \
if (this->exceptions() & std::ios_base::failbit) \
throw; \
} \
} \
/**/
namespace asio {
/// Iostream interface for a socket.
template <typename Protocol,
typename Service = stream_socket_service<Protocol> >
class basic_socket_iostream
: public boost::base_from_member<basic_socket_streambuf<Protocol, Service> >,
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, Service> >::member)
{
}
#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(ASIO_SOCKET_IOSTREAM_MAX_ARITY),
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(ASIO_SOCKET_IOSTREAM_MAX_ARITY),
ASIO_PRIVATE_CONNECT_DEF, _ )
#endif
/// Close the connection.
void close()
{
rdbuf()->close();
}
/// Return a pointer to the underlying streambuf.
basic_socket_streambuf<Protocol, Service>* rdbuf() const
{
return const_cast<basic_socket_streambuf<Protocol, Service>*>(
&this->boost::base_from_member<
basic_socket_streambuf<Protocol, Service> >::member);
}
};
} // namespace asio
#undef ASIO_PRIVATE_CTR_DEF
#undef ASIO_PRIVATE_CONNECT_DEF
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_SOCKET_IOSTREAM_HPP

View File

@ -1,280 +0,0 @@
//
// basic_socket_streambuf.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_SOCKET_STREAMBUF_HPP
#define ASIO_BASIC_SOCKET_STREAMBUF_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <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 "asio/detail/pop_options.hpp"
#include "asio/basic_socket.hpp"
#include "asio/error_handler.hpp"
#include "asio/io_service.hpp"
#include "asio/stream_socket_service.hpp"
#if !defined(ASIO_SOCKET_STREAMBUF_MAX_ARITY)
#define ASIO_SOCKET_STREAMBUF_MAX_ARITY 5
#endif // !defined(ASIO_SOCKET_STREAMBUF_MAX_ARITY)
// A macro that should expand to:
// template < typename T1, ..., typename Tn >
// explicit basic_socket_streambuf( T1 x1, ..., Tn xn )
// : basic_socket<Protocol, Service>(
// boost::base_from_member<io_service>::member)
// {
// init_buffers();
// typedef typename Protocol::resolver_query resolver_query;
// resolver_query query( x1, ..., xn );
// resolve_and_connect(query);
// }
// This macro should only persist within this file.
#define ASIO_PRIVATE_CTR_DEF( z, n, data ) \
template < BOOST_PP_ENUM_PARAMS(n, typename T) > \
explicit basic_socket_streambuf( BOOST_PP_ENUM_BINARY_PARAMS(n, T, x) ) \
: basic_socket<Protocol, Service>( \
boost::base_from_member<io_service>::member) \
{ \
init_buffers(); \
typedef typename Protocol::resolver_query resolver_query; \
resolver_query query( BOOST_PP_ENUM_PARAMS(n, x) ); \
resolve_and_connect(query); \
} \
/**/
// A macro that should expand to:
// template < typename T1, ..., typename Tn >
// void connect( T1 x1, ..., Tn xn )
// {
// this->basic_socket<Protocol, Service>::close();
// init_buffers();
// typedef typename Protocol::resolver_query resolver_query;
// resolver_query query( x1, ..., xn );
// resolve_and_connect(query);
// }
// This macro should only persist within this file.
#define 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) ) \
{ \
this->basic_socket<Protocol, Service>::close(); \
init_buffers(); \
typedef typename Protocol::resolver_query resolver_query; \
resolver_query query( BOOST_PP_ENUM_PARAMS(n, x) ); \
resolve_and_connect(query); \
} \
/**/
namespace asio {
/// Iostream streambuf for a socket.
template <typename Protocol,
typename Service = stream_socket_service<Protocol> >
class basic_socket_streambuf
: public std::streambuf,
private boost::base_from_member<io_service>,
public basic_socket<Protocol, Service>
{
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, Service>(
boost::base_from_member<asio::io_service>::member)
{
init_buffers();
}
/// Establish a connection to the specified endpoint.
explicit basic_socket_streambuf(const endpoint_type& endpoint)
: basic_socket<Protocol, Service>(
boost::base_from_member<asio::io_service>::member)
{
init_buffers();
this->basic_socket<Protocol, Service>::connect(endpoint);
}
#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_streambuf(T1 t1, ..., TN tn);
#else
BOOST_PP_REPEAT_FROM_TO(
1, BOOST_PP_INC(ASIO_SOCKET_STREAMBUF_MAX_ARITY),
ASIO_PRIVATE_CTR_DEF, _ )
#endif
/// Destructor flushes buffered data.
~basic_socket_streambuf()
{
sync();
}
/// Establish a connection to the specified endpoint.
void connect(const endpoint_type& endpoint)
{
this->basic_socket<Protocol, Service>::close();
init_buffers();
this->basic_socket<Protocol, Service>::connect(endpoint);
}
#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(ASIO_SOCKET_STREAMBUF_MAX_ARITY),
ASIO_PRIVATE_CONNECT_DEF, _ )
#endif
/// Close the connection.
void close()
{
sync();
this->basic_socket<Protocol, Service>::close();
init_buffers();
}
protected:
int_type underflow()
{
if (gptr() == egptr())
{
asio::error error;
std::size_t bytes_transferred = this->service.receive(
this->implementation,
asio::buffer(asio::buffer(get_buffer_) + putback_max),
0, asio::assign_error(error));
if (error)
{
if (error != asio::error::eof)
throw error;
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 (!traits_type::eq_int_type(c, traits_type::eof()))
{
if (pptr() == epptr())
{
asio::const_buffer buffer =
asio::buffer(pbase(), pptr() - pbase());
while (asio::buffer_size(buffer) > 0)
{
std::size_t bytes_transferred = this->service.send(
this->implementation, asio::buffer(buffer),
0, asio::throw_error());
buffer = buffer + bytes_transferred;
}
setp(put_buffer_.begin(), put_buffer_.end());
}
*pptr() = traits_type::to_char_type(c);
pbump(1);
return c;
}
return traits_type::not_eof(c);
}
int sync()
{
asio::const_buffer buffer =
asio::buffer(pbase(), pptr() - pbase());
while (asio::buffer_size(buffer) > 0)
{
std::size_t bytes_transferred = this->service.send(
this->implementation, asio::buffer(buffer),
0, asio::throw_error());
buffer = buffer + bytes_transferred;
}
setp(put_buffer_.begin(), put_buffer_.end());
return 0;
}
private:
void init_buffers()
{
setg(get_buffer_.begin(),
get_buffer_.begin() + putback_max,
get_buffer_.begin() + putback_max);
setp(put_buffer_.begin(), put_buffer_.end());
}
void resolve_and_connect(const typename Protocol::resolver_query& query)
{
typedef typename Protocol::resolver resolver_type;
typedef typename Protocol::resolver_iterator iterator_type;
resolver_type resolver(
boost::base_from_member<asio::io_service>::member);
iterator_type iterator = resolver.resolve(query);
asio::error error(asio::error::host_not_found);
while (error && iterator != iterator_type())
{
this->basic_socket<Protocol, Service>::close();
this->basic_socket<Protocol, Service>::connect(
*iterator, asio::assign_error(error));
++iterator;
}
if (error)
throw error;
}
enum { putback_max = 8 };
enum { buffer_size = 512 };
boost::array<char, buffer_size> get_buffer_;
boost::array<char, buffer_size> put_buffer_;
};
} // namespace asio
#undef ASIO_PRIVATE_CTR_DEF
#undef ASIO_PRIVATE_CONNECT_DEF
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_SOCKET_STREAMBUF_HPP

View File

@ -1,816 +0,0 @@
//
// basic_stream_socket.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_STREAM_SOCKET_HPP
#define ASIO_BASIC_STREAM_SOCKET_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/basic_socket.hpp"
#include "asio/error_handler.hpp"
#include "asio/stream_socket_service.hpp"
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.@n
* @e Shared @e objects: Unsafe.
*
* @par Concepts:
* Async_Read_Stream, Async_Write_Stream, Error_Source, IO_Object, Stream,
* Sync_Read_Stream, Sync_Write_Stream.
*/
template <typename Protocol,
typename Service = stream_socket_service<Protocol> >
class basic_stream_socket
: public basic_socket<Protocol, Service>
{
public:
/// The native representation of a socket.
typedef typename Service::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(asio::io_service& io_service)
: basic_socket<Protocol, Service>(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 asio::error Thrown on failure.
*/
basic_stream_socket(asio::io_service& io_service,
const protocol_type& protocol)
: basic_socket<Protocol, Service>(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 asio::error Thrown on failure.
*/
basic_stream_socket(asio::io_service& io_service,
const endpoint_type& endpoint)
: basic_socket<Protocol, Service>(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 asio::error Thrown on failure.
*/
basic_stream_socket(asio::io_service& io_service,
const protocol_type& protocol, const native_type& native_socket)
: basic_socket<Protocol, Service>(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 asio::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(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 Const_Buffers>
std::size_t send(const Const_Buffers& buffers)
{
return this->service.send(this->implementation, buffers, 0, throw_error());
}
/// 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 asio::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(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 Const_Buffers>
std::size_t send(const Const_Buffers& buffers,
socket_base::message_flags flags)
{
return this->service.send(this->implementation, buffers, flags,
throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation.
* ); @endcode
*
* @returns The number of bytes sent. Returns 0 if an error occurred and the
* error handler did not throw an exception.
*
* @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 Const_Buffers, typename Error_Handler>
std::size_t send(const Const_Buffers& buffers,
socket_base::message_flags flags,
Error_Handler error_handler)
{
return this->service.send(this->implementation, buffers, flags,
error_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 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 asio::error& 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
* 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(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 Const_Buffers, typename Handler>
void async_send(const Const_Buffers& buffers, Handler 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 asio::error& 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
* 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(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 Const_Buffers, typename Handler>
void async_send(const Const_Buffers& buffers,
socket_base::message_flags flags, Handler 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 asio::error Thrown on failure. An error code of
* 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(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 Mutable_Buffers>
std::size_t receive(const Mutable_Buffers& buffers)
{
return this->service.receive(this->implementation, buffers, 0,
throw_error());
}
/// 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 asio::error Thrown on failure. An error code of
* 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(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 Mutable_Buffers>
std::size_t receive(const Mutable_Buffers& buffers,
socket_base::message_flags flags)
{
return this->service.receive(this->implementation, buffers, flags,
throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @returns The number of bytes received. Returns 0 if an error occurred and
* the error handler did not throw an exception.
*
* @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 Mutable_Buffers, typename Error_Handler>
std::size_t receive(const Mutable_Buffers& buffers,
socket_base::message_flags flags, Error_Handler error_handler)
{
return this->service.receive(this->implementation, buffers, flags,
error_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 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 asio::error& 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
* 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(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 Mutable_Buffers, typename Handler>
void async_receive(const Mutable_Buffers& buffers, Handler 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 asio::error& 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
* 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(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 Mutable_Buffers, typename Handler>
void async_receive(const Mutable_Buffers& buffers,
socket_base::message_flags flags, Handler 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 asio::error Thrown on failure. An error code of
* 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(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 Const_Buffers>
std::size_t write_some(const Const_Buffers& buffers)
{
return this->service.send(this->implementation, buffers, 0, throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation.
* ); @endcode
*
* @returns The number of bytes written. Returns 0 if an error occurred and
* the error handler did not throw an exception.
*
* @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 Const_Buffers, typename Error_Handler>
std::size_t write_some(const Const_Buffers& buffers,
Error_Handler error_handler)
{
return this->service.send(this->implementation, buffers, 0, error_handler);
}
/// 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 asio::error& 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
* 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(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 Const_Buffers, typename Handler>
void async_write_some(const Const_Buffers& buffers, Handler 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 asio::error Thrown on failure. An error code of
* 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(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 Mutable_Buffers>
std::size_t read_some(const Mutable_Buffers& buffers)
{
return this->service.receive(this->implementation, buffers, 0,
throw_error());
}
/// 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 error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation.
* ); @endcode
*
* @returns The number of bytes read. Returns 0 if an error occurred and the
* error handler did not throw an exception.
*
* @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 Mutable_Buffers, typename Error_Handler>
std::size_t read_some(const Mutable_Buffers& buffers,
Error_Handler error_handler)
{
return this->service.receive(this->implementation, buffers, 0,
error_handler);
}
/// 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 asio::error& 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
* 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(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 Mutable_Buffers, typename Handler>
void async_read_some(const Mutable_Buffers& buffers, Handler handler)
{
this->service.async_receive(this->implementation, buffers, 0, handler);
}
/// Peek at the incoming data on the stream socket.
/**
* This function is used to peek at the incoming data on the stream socket,
* without removing it from the input queue. The function call will block
* until data has been read successfully or an error occurs.
*
* @param buffers One or more buffers into which the data will be read.
*
* @returns The number of bytes read.
*
* @throws asio::error Thrown on failure.
*
* @par Example:
* To peek using a single data buffer use the @ref buffer function as
* follows:
* @code socket.peek(asio::buffer(data, size)); @endcode
* See the @ref buffer documentation for information on using multiple
* buffers in one go, and how to use it with arrays, boost::array or
* std::vector.
*/
template <typename Mutable_Buffers>
std::size_t peek(const Mutable_Buffers& buffers)
{
return this->service.receive(this->implementation, buffers,
socket_base::message_peek, throw_error());
}
/// Peek at the incoming data on the stream socket.
/**
* This function is used to peek at the incoming data on the stream socket,
* without removing it from the input queue. The function call will block
* until data has been read successfully or an error occurs.
*
* @param buffers One or more buffers into which the data will be read.
*
* @param error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation.
* ); @endcode
*
* @returns The number of bytes read. Returns 0 if an error occurred and the
* error handler did not throw an exception.
*/
template <typename Mutable_Buffers, typename Error_Handler>
std::size_t peek(const Mutable_Buffers& buffers, Error_Handler error_handler)
{
return this->service.receive(this->implementation, buffers,
socket_base::message_peek, error_handler);
}
/// 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 socket without blocking.
*
* @returns The number of bytes of data that can be read without blocking.
*
* @throws asio::error Thrown on failure.
*/
std::size_t in_avail()
{
socket_base::bytes_readable command;
this->service.io_control(this->implementation, command, throw_error());
return command.get();
}
/// 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 socket without blocking.
*
* @param error_handler A handler to be called when the operation completes,
* to indicate whether or not an error has occurred. Copies will be made of
* the handler as required. The function signature of the handler must be:
* @code void error_handler(
* const asio::error& error // Result of operation
* ); @endcode
*
* @returns The number of bytes of data that can be read without blocking.
*/
template <typename Error_Handler>
std::size_t in_avail(Error_Handler error_handler)
{
socket_base::bytes_readable command;
this->service.io_control(this->implementation, command, error_handler);
return command.get();
}
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_STREAM_SOCKET_HPP

View File

@ -1,200 +0,0 @@
//
// basic_streambuf.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BASIC_STREAMBUF_HPP
#define ASIO_BASIC_STREAMBUF_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <algorithm>
#include <limits>
#include <memory>
#include <stdexcept>
#include <streambuf>
#include <vector>
#include "asio/detail/pop_options.hpp"
#include "asio/buffer.hpp"
#include "asio/detail/noncopyable.hpp"
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 asio::const_buffer_container_1 const_buffers_type;
typedef asio::mutable_buffer_container_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 asio::buffer(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 asio::buffer(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)
{
while (n > 0)
{
sbumpc();
--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("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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BASIC_STREAMBUF_HPP

View File

@ -1,639 +0,0 @@
//
// buffer.hpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BUFFER_HPP
#define ASIO_BUFFER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include <boost/array.hpp>
#include <boost/type_traits/is_const.hpp>
#include <string>
#include <vector>
#include "asio/detail/pop_options.hpp"
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)
{
}
private:
friend void* asio::detail::buffer_cast_helper(
const mutable_buffer& b);
friend std::size_t asio::detail::buffer_size_helper(
const mutable_buffer& b);
void* data_;
std::size_t size_;
};
namespace detail {
inline void* buffer_cast_helper(const mutable_buffer& b)
{
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 Pointer_To_Pod_Type>
inline Pointer_To_Pod_Type buffer_cast(const mutable_buffer& b)
{
return static_cast<Pointer_To_Pod_Type>(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);
}
/// 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);
}
/// Adapts a single modifiable buffer so that it meets the requirements of the
/// Mutable_Buffers concept.
class mutable_buffer_container_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_buffer_container_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_(asio::detail::buffer_cast_helper(b)),
size_(asio::detail::buffer_size_helper(b))
{
}
private:
friend const void* asio::detail::buffer_cast_helper(
const const_buffer& b);
friend std::size_t asio::detail::buffer_size_helper(
const const_buffer& b);
const void* data_;
std::size_t size_;
};
namespace detail {
inline const void* buffer_cast_helper(const const_buffer& b)
{
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 Pointer_To_Pod_Type>
inline Pointer_To_Pod_Type buffer_cast(const const_buffer& b)
{
return static_cast<Pointer_To_Pod_Type>(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);
}
/// 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);
}
/// Adapts a single non-modifiable buffer so that it meets the requirements of
/// the Const_Buffers concept.
class const_buffer_container_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_buffer_container_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;
}
};
/** @defgroup buffer asio::buffer
*
* @brief The 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(asio::buffer(data, size)); @endcode
*
* In the above example, the return value of asio::buffer meets the
* requirements of the Const_Buffers 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 Mutable_Buffers 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(asio::buffer(d1));
*
* std::vector<char> d2(128);
* bytes_transferred = sock.read(asio::buffer(d2));
*
* boost::array<char, 128> d3;
* bytes_transferred = sock.read(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
* Mutable_Buffers (for read) or Const_Buffers (for write) concepts:
*
* @code
* char d1[128];
* std::vector<char> d2(128);
* boost::array<char, 128> d3;
*
* boost::array<mutable_buffer, 3> bufs1 = {
* asio::buffer(d1),
* asio::buffer(d2),
* asio::buffer(d3) };
* bytes_transferred = sock.read(bufs1);
*
* std::vector<const_buffer> bufs2;
* bufs2.push_back(asio::buffer(d1));
* bufs2.push_back(asio::buffer(d2));
* bufs2.push_back(asio::buffer(d3));
* bytes_transferred = sock.write(bufs2); @endcode
*/
/*@{*/
/// Create a new modifiable buffer from an existing buffer.
inline mutable_buffer_container_1 buffer(const mutable_buffer& b)
{
return mutable_buffer_container_1(b);
}
/// Create a new modifiable buffer from an existing buffer.
inline mutable_buffer_container_1 buffer(const mutable_buffer& b,
std::size_t max_size_in_bytes)
{
return mutable_buffer_container_1(
mutable_buffer(buffer_cast<void*>(b),
buffer_size(b) < max_size_in_bytes
? buffer_size(b) : max_size_in_bytes));
}
/// Create a new non-modifiable buffer from an existing buffer.
inline const_buffer_container_1 buffer(const const_buffer& b)
{
return const_buffer_container_1(b);
}
/// Create a new non-modifiable buffer from an existing buffer.
inline const_buffer_container_1 buffer(const const_buffer& b,
std::size_t max_size_in_bytes)
{
return const_buffer_container_1(
const_buffer(buffer_cast<const void*>(b),
buffer_size(b) < max_size_in_bytes
? buffer_size(b) : max_size_in_bytes));
}
/// Create a new modifiable buffer that represents the given memory range.
inline mutable_buffer_container_1 buffer(void* data, std::size_t size_in_bytes)
{
return mutable_buffer_container_1(mutable_buffer(data, size_in_bytes));
}
/// Create a new non-modifiable buffer that represents the given memory range.
inline const_buffer_container_1 buffer(const void* data,
std::size_t size_in_bytes)
{
return const_buffer_container_1(const_buffer(data, size_in_bytes));
}
/// Create a new modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline mutable_buffer_container_1 buffer(Pod_Type (&data)[N])
{
return mutable_buffer_container_1(mutable_buffer(data, N * sizeof(Pod_Type)));
}
/// Create a new modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline mutable_buffer_container_1 buffer(Pod_Type (&data)[N],
std::size_t max_size_in_bytes)
{
return mutable_buffer_container_1(
mutable_buffer(data,
N * sizeof(Pod_Type) < max_size_in_bytes
? N * sizeof(Pod_Type) : max_size_in_bytes));
}
/// Create a new non-modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline const_buffer_container_1 buffer(const Pod_Type (&data)[N])
{
return const_buffer_container_1(const_buffer(data, N * sizeof(Pod_Type)));
}
/// Create a new non-modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline const_buffer_container_1 buffer(const Pod_Type (&data)[N],
std::size_t max_size_in_bytes)
{
return const_buffer_container_1(
const_buffer(data,
N * sizeof(Pod_Type) < max_size_in_bytes
? N * sizeof(Pod_Type) : max_size_in_bytes));
}
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
// Borland C++ thinks the overloads:
//
// unspecified buffer(boost::array<Pod_Type, N>& array ...);
//
// and
//
// unspecified buffer(boost::array<const Pod_Type, 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 Pod_Type 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_buffer_container_1 container_type;
};
template <>
struct buffer_types_base<true>
{
typedef const_buffer buffer_type;
typedef const_buffer_container_1 container_type;
};
template <typename Pod_Type>
struct buffer_types
: public buffer_types_base<boost::is_const<Pod_Type>::value>
{
};
} // namespace detail
template <typename Pod_Type, std::size_t N>
inline typename detail::buffer_types<Pod_Type>::container_type
buffer(boost::array<Pod_Type, N>& data)
{
typedef typename asio::detail::buffer_types<Pod_Type>::buffer_type
buffer_type;
typedef typename asio::detail::buffer_types<Pod_Type>::container_type
container_type;
return container_type(
buffer_type(data.c_array(), data.size() * sizeof(Pod_Type)));
}
template <typename Pod_Type, std::size_t N>
inline typename detail::buffer_types<Pod_Type>::container_type
buffer(boost::array<Pod_Type, N>& data, std::size_t max_size_in_bytes)
{
typedef typename asio::detail::buffer_types<Pod_Type>::buffer_type
buffer_type;
typedef typename asio::detail::buffer_types<Pod_Type>::container_type
container_type;
return container_type(
buffer_type(data.c_array(),
data.size() * sizeof(Pod_Type) < max_size_in_bytes
? data.size() * sizeof(Pod_Type) : max_size_in_bytes));
}
#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
/// Create a new modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline mutable_buffer_container_1 buffer(boost::array<Pod_Type, N>& data)
{
return mutable_buffer_container_1(
mutable_buffer(data.c_array(), data.size() * sizeof(Pod_Type)));
}
/// Create a new modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline mutable_buffer_container_1 buffer(boost::array<Pod_Type, N>& data,
std::size_t max_size_in_bytes)
{
return mutable_buffer_container_1(
mutable_buffer(data.c_array(),
data.size() * sizeof(Pod_Type) < max_size_in_bytes
? data.size() * sizeof(Pod_Type) : max_size_in_bytes));
}
/// Create a new non-modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline const_buffer_container_1 buffer(boost::array<const Pod_Type, N>& data)
{
return const_buffer_container_1(
const_buffer(data.data(), data.size() * sizeof(Pod_Type)));
}
/// Create a new non-modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline const_buffer_container_1 buffer(boost::array<const Pod_Type, N>& data,
std::size_t max_size_in_bytes)
{
return const_buffer_container_1(
const_buffer(data.data(),
data.size() * sizeof(Pod_Type) < max_size_in_bytes
? data.size() * sizeof(Pod_Type) : max_size_in_bytes));
}
#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
/// Create a new non-modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline const_buffer_container_1 buffer(const boost::array<Pod_Type, N>& data)
{
return const_buffer_container_1(
const_buffer(data.data(), data.size() * sizeof(Pod_Type)));
}
/// Create a new non-modifiable buffer that represents the given POD array.
template <typename Pod_Type, std::size_t N>
inline const_buffer_container_1 buffer(const boost::array<Pod_Type, N>& data,
std::size_t max_size_in_bytes)
{
return const_buffer_container_1(
const_buffer(data.data(),
data.size() * sizeof(Pod_Type) < max_size_in_bytes
? data.size() * sizeof(Pod_Type) : 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 Pod_Type, typename Allocator>
inline mutable_buffer_container_1 buffer(std::vector<Pod_Type, Allocator>& data)
{
return mutable_buffer_container_1(
mutable_buffer(&data[0], data.size() * sizeof(Pod_Type)));
}
/// 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 Pod_Type, typename Allocator>
inline mutable_buffer_container_1 buffer(std::vector<Pod_Type, Allocator>& data,
std::size_t max_size_in_bytes)
{
return mutable_buffer_container_1(
mutable_buffer(&data[0],
data.size() * sizeof(Pod_Type) < max_size_in_bytes
? data.size() * sizeof(Pod_Type) : max_size_in_bytes));
}
/// 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 Pod_Type, typename Allocator>
inline const_buffer_container_1 buffer(
const std::vector<Pod_Type, Allocator>& data)
{
return const_buffer_container_1(
const_buffer(&data[0], data.size() * sizeof(Pod_Type)));
}
/// 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 Pod_Type, typename Allocator>
inline const_buffer_container_1 buffer(
const std::vector<Pod_Type, Allocator>& data, std::size_t max_size_in_bytes)
{
return const_buffer_container_1(
const_buffer(&data[0],
data.size() * sizeof(Pod_Type) < max_size_in_bytes
? data.size() * sizeof(Pod_Type) : max_size_in_bytes));
}
/// 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_buffer_container_1 buffer(const std::string& data)
{
return const_buffer_container_1(const_buffer(data.data(), data.size()));
}
/// 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_buffer_container_1 buffer(const std::string& data,
std::size_t max_size_in_bytes)
{
return const_buffer_container_1(
const_buffer(data.data(),
data.size() < max_size_in_bytes
? data.size() : max_size_in_bytes));
}
/*@}*/
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BUFFER_HPP

View File

@ -1,407 +0,0 @@
//
// buffered_read_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BUFFERED_READ_STREAM_HPP
#define ASIO_BUFFERED_READ_STREAM_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <cstring>
#include <boost/config.hpp>
#include <boost/type_traits.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/buffered_read_stream_fwd.hpp"
#include "asio/buffer.hpp"
#include "asio/error.hpp"
#include "asio/io_service.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/buffer_resize_guard.hpp"
#include "asio/detail/buffered_stream_storage.hpp"
#include "asio/detail/noncopyable.hpp"
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.@n
* @e Shared @e objects: Unsafe.
*
* @par Concepts:
* Async_Object, Async_Read_Stream, Async_Write_Stream, Error_Source, Stream,
* Sync_Read_Stream, Sync_Write_Stream.
*/
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;
/// The type used for reporting errors.
typedef typename next_layer_type::error_type error_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();
}
/// Get the io_service associated with the object.
asio::io_service& io_service()
{
return next_layer_.io_service();
}
/// Close the stream.
void close()
{
next_layer_.close();
}
/// Close the stream.
template <typename Error_Handler>
void close(Error_Handler error_handler)
{
next_layer_.close(error_handler);
}
/// Write the given data to the stream. Returns the number of bytes written.
/// Throws an exception on failure.
template <typename Const_Buffers>
std::size_t write_some(const Const_Buffers& 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 and the error handler did not throw.
template <typename Const_Buffers, typename Error_Handler>
std::size_t write_some(const Const_Buffers& buffers,
Error_Handler error_handler)
{
return next_layer_.write_some(buffers, error_handler);
}
/// Start an asynchronous write. The data being written must be valid for the
/// lifetime of the asynchronous operation.
template <typename Const_Buffers, typename Handler>
void async_write_some(const Const_Buffers& buffers, Handler 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 and the
/// error handler did not throw.
template <typename Error_Handler>
std::size_t fill(Error_Handler error_handler)
{
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),
error_handler));
resize_guard.commit();
return storage_.size() - previous_size;
}
template <typename Handler>
class fill_handler
{
public:
fill_handler(asio::io_service& io_service,
detail::buffered_stream_storage& storage,
std::size_t previous_size, Handler handler)
: io_service_(io_service),
storage_(storage),
previous_size_(previous_size),
handler_(handler)
{
}
template <typename Error>
void operator()(const Error& e, std::size_t bytes_transferred)
{
storage_.resize(previous_size_ + bytes_transferred);
io_service_.dispatch(detail::bind_handler(
handler_, e, bytes_transferred));
}
private:
asio::io_service& io_service_;
detail::buffered_stream_storage& storage_;
std::size_t previous_size_;
Handler handler_;
};
/// Start an asynchronous fill.
template <typename Handler>
void async_fill(Handler 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<Handler>(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 Mutable_Buffers>
std::size_t read_some(const Mutable_Buffers& 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 and the error handler did not throw an exception.
template <typename Mutable_Buffers, typename Error_Handler>
std::size_t read_some(const Mutable_Buffers& buffers,
Error_Handler error_handler)
{
if (storage_.empty() && !fill(error_handler))
return 0;
return copy(buffers);
}
template <typename Mutable_Buffers, typename Handler>
class read_some_handler
{
public:
read_some_handler(asio::io_service& io_service,
detail::buffered_stream_storage& storage,
const Mutable_Buffers& buffers, Handler handler)
: io_service_(io_service),
storage_(storage),
buffers_(buffers),
handler_(handler)
{
}
void operator()(const error_type& e, std::size_t)
{
if (e || storage_.empty())
{
std::size_t length = 0;
io_service_.dispatch(detail::bind_handler(handler_, e, length));
}
else
{
using namespace std; // For memcpy.
std::size_t bytes_avail = storage_.size();
std::size_t bytes_copied = 0;
typename Mutable_Buffers::const_iterator iter = buffers_.begin();
typename Mutable_Buffers::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_, e, bytes_copied));
}
}
private:
asio::io_service& io_service_;
detail::buffered_stream_storage& storage_;
Mutable_Buffers buffers_;
Handler 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 Mutable_Buffers, typename Handler>
void async_read_some(const Mutable_Buffers& buffers, Handler handler)
{
if (storage_.empty())
{
async_fill(read_some_handler<Mutable_Buffers, Handler>(
io_service(), storage_, buffers, handler));
}
else
{
std::size_t length = copy(buffers);
io_service().post(detail::bind_handler(handler, 0, length));
}
}
/// Peek at the incoming data on the stream. Returns the number of bytes read.
/// Throws an exception on failure.
template <typename Mutable_Buffers>
std::size_t peek(const Mutable_Buffers& 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 and the error handler did not throw.
template <typename Mutable_Buffers, typename Error_Handler>
std::size_t peek(const Mutable_Buffers& buffers, Error_Handler error_handler)
{
if (storage_.empty() && !fill(error_handler))
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.
template <typename Error_Handler>
std::size_t in_avail(Error_Handler error_handler)
{
return storage_.size();
}
private:
/// Copy data out of the internal buffer to the specified target buffer.
/// Returns the number of bytes copied.
template <typename Mutable_Buffers>
std::size_t copy(const Mutable_Buffers& buffers)
{
using namespace std; // For memcpy.
std::size_t bytes_avail = storage_.size();
std::size_t bytes_copied = 0;
typename Mutable_Buffers::const_iterator iter = buffers.begin();
typename Mutable_Buffers::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 Mutable_Buffers>
std::size_t peek_copy(const Mutable_Buffers& buffers)
{
using namespace std; // For memcpy.
std::size_t bytes_avail = storage_.size();
std::size_t bytes_copied = 0;
typename Mutable_Buffers::const_iterator iter = buffers.begin();
typename Mutable_Buffers::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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BUFFERED_READ_STREAM_HPP

View File

@ -1,29 +0,0 @@
//
// buffered_read_stream_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BUFFERED_READ_STREAM_FWD_HPP
#define ASIO_BUFFERED_READ_STREAM_FWD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
namespace asio {
template <typename Stream>
class buffered_read_stream;
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BUFFERED_READ_STREAM_FWD_HPP

View File

@ -1,249 +0,0 @@
//
// buffered_stream.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BUFFERED_STREAM_HPP
#define ASIO_BUFFERED_STREAM_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/buffered_read_stream.hpp"
#include "asio/buffered_write_stream.hpp"
#include "asio/buffered_stream_fwd.hpp"
#include "asio/error.hpp"
#include "asio/io_service.hpp"
#include "asio/detail/noncopyable.hpp"
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.@n
* @e Shared @e objects: Unsafe.
*
* @par Concepts:
* Async_Object, Async_Read_Stream, Async_Write_Stream, Error_Source, Stream,
* Sync_Read_Stream, Sync_Write_Stream.
*/
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;
/// The type used for reporting errors.
typedef typename next_layer_type::error_type error_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();
}
/// Get the io_service associated with the object.
asio::io_service& io_service()
{
return stream_impl_.io_service();
}
/// Close the stream.
void close()
{
stream_impl_.close();
}
/// Close the stream.
template <typename Error_Handler>
void close(Error_Handler error_handler)
{
stream_impl_.close(error_handler);
}
/// 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 and the error handler did not throw.
template <typename Error_Handler>
std::size_t flush(Error_Handler error_handler)
{
return stream_impl_.next_layer().flush(error_handler);
}
/// Start an asynchronous flush.
template <typename Handler>
void async_flush(Handler 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 Const_Buffers>
std::size_t write_some(const Const_Buffers& 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 and the error handler did not throw.
template <typename Const_Buffers, typename Error_Handler>
std::size_t write_some(const Const_Buffers& buffers,
Error_Handler error_handler)
{
return stream_impl_.write_some(buffers, error_handler);
}
/// Start an asynchronous write. The data being written must be valid for the
/// lifetime of the asynchronous operation.
template <typename Const_Buffers, typename Handler>
void async_write_some(const Const_Buffers& buffers, Handler 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 and the
/// error handler did not throw.
template <typename Error_Handler>
std::size_t fill(Error_Handler error_handler)
{
return stream_impl_.fill(error_handler);
}
/// Start an asynchronous fill.
template <typename Handler>
void async_fill(Handler 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 Mutable_Buffers>
std::size_t read_some(const Mutable_Buffers& 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 and the error handler did not throw an exception.
template <typename Mutable_Buffers, typename Error_Handler>
std::size_t read_some(const Mutable_Buffers& buffers,
Error_Handler error_handler)
{
return stream_impl_.read_some(buffers, error_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 Mutable_Buffers, typename Handler>
void async_read_some(const Mutable_Buffers& buffers, Handler 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 Mutable_Buffers>
std::size_t peek(const Mutable_Buffers& 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 and the error handler did not throw.
template <typename Mutable_Buffers, typename Error_Handler>
std::size_t peek(const Mutable_Buffers& buffers, Error_Handler error_handler)
{
return stream_impl_.peek(buffers, error_handler);
}
/// 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.
template <typename Error_Handler>
std::size_t in_avail(Error_Handler error_handler)
{
return stream_impl_.in_avail(error_handler);
}
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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BUFFERED_STREAM_HPP

View File

@ -1,29 +0,0 @@
//
// buffered_stream_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BUFFERED_STREAM_FWD_HPP
#define ASIO_BUFFERED_STREAM_FWD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
namespace asio {
template <typename Stream>
class buffered_stream;
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BUFFERED_STREAM_FWD_HPP

View File

@ -1,362 +0,0 @@
//
// buffered_write_stream.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BUFFERED_WRITE_STREAM_HPP
#define ASIO_BUFFERED_WRITE_STREAM_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <cstring>
#include <boost/config.hpp>
#include <boost/type_traits.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/buffered_write_stream_fwd.hpp"
#include "asio/buffer.hpp"
#include "asio/completion_condition.hpp"
#include "asio/error.hpp"
#include "asio/io_service.hpp"
#include "asio/write.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/buffered_stream_storage.hpp"
#include "asio/detail/noncopyable.hpp"
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.@n
* @e Shared @e objects: Unsafe.
*
* @par Concepts:
* Async_Object, Async_Read_Stream, Async_Write_Stream, Error_Source, Stream,
* Sync_Read_Stream, Sync_Write_Stream.
*/
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;
/// The type used for reporting errors.
typedef typename next_layer_type::error_type error_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();
}
/// Get the io_service associated with the object.
asio::io_service& io_service()
{
return next_layer_.io_service();
}
/// Close the stream.
void close()
{
next_layer_.close();
}
/// Close the stream.
template <typename Error_Handler>
void close(Error_Handler error_handler)
{
next_layer_.close(error_handler);
}
/// 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 and the error handler did not throw.
template <typename Error_Handler>
std::size_t flush(Error_Handler error_handler)
{
std::size_t bytes_written = write(next_layer_,
buffer(storage_.data(), storage_.size()),
transfer_all(), error_handler);
storage_.consume(bytes_written);
return bytes_written;
}
template <typename Handler>
class flush_handler
{
public:
flush_handler(asio::io_service& io_service,
detail::buffered_stream_storage& storage, Handler handler)
: io_service_(io_service),
storage_(storage),
handler_(handler)
{
}
void operator()(const error_type& e, std::size_t bytes_written)
{
storage_.consume(bytes_written);
io_service_.dispatch(detail::bind_handler(handler_, e, bytes_written));
}
private:
asio::io_service& io_service_;
detail::buffered_stream_storage& storage_;
Handler handler_;
};
/// Start an asynchronous flush.
template <typename Handler>
void async_flush(Handler handler)
{
async_write(next_layer_, buffer(storage_.data(), storage_.size()),
flush_handler<Handler>(io_service(), storage_, handler));
}
/// Write the given data to the stream. Returns the number of bytes written.
/// Throws an exception on failure.
template <typename Const_Buffers>
std::size_t write_some(const Const_Buffers& 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 Const_Buffers, typename Error_Handler>
std::size_t write_some(const Const_Buffers& buffers,
Error_Handler error_handler)
{
if (storage_.size() == storage_.capacity() && !flush(error_handler))
return 0;
return copy(buffers);
}
template <typename Const_Buffers, typename Handler>
class write_some_handler
{
public:
write_some_handler(asio::io_service& io_service,
detail::buffered_stream_storage& storage,
const Const_Buffers& buffers, Handler handler)
: io_service_(io_service),
storage_(storage),
buffers_(buffers),
handler_(handler)
{
}
void operator()(const error_type& e, std::size_t)
{
if (e)
{
std::size_t length = 0;
io_service_.dispatch(detail::bind_handler(handler_, e, 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 Const_Buffers::const_iterator iter = buffers_.begin();
typename Const_Buffers::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_, e, bytes_copied));
}
}
private:
asio::io_service& io_service_;
detail::buffered_stream_storage& storage_;
Const_Buffers buffers_;
Handler handler_;
};
/// Start an asynchronous write. The data being written must be valid for the
/// lifetime of the asynchronous operation.
template <typename Const_Buffers, typename Handler>
void async_write_some(const Const_Buffers& buffers, Handler handler)
{
if (storage_.size() == storage_.capacity())
{
async_flush(write_some_handler<Const_Buffers, Handler>(
io_service(), storage_, buffers, handler));
}
else
{
std::size_t bytes_copied = copy(buffers);
io_service().post(detail::bind_handler(handler, 0, bytes_copied));
}
}
/// Read some data from the stream. Returns the number of bytes read. Throws
/// an exception on failure.
template <typename Mutable_Buffers>
std::size_t read_some(const Mutable_Buffers& 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 and the error handler did not throw an exception.
template <typename Mutable_Buffers, typename Error_Handler>
std::size_t read_some(const Mutable_Buffers& buffers,
Error_Handler error_handler)
{
return next_layer_.read_some(buffers, error_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 Mutable_Buffers, typename Handler>
void async_read_some(const Mutable_Buffers& buffers, Handler 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 Mutable_Buffers>
std::size_t peek(const Mutable_Buffers& 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 and the error handler did not throw.
template <typename Mutable_Buffers, typename Error_Handler>
std::size_t peek(const Mutable_Buffers& buffers, Error_Handler error_handler)
{
return next_layer_.peek(buffers, error_handler);
}
/// 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.
template <typename Error_Handler>
std::size_t in_avail(Error_Handler error_handler)
{
return next_layer_.in_avail(error_handler);
}
private:
/// Copy data into the internal buffer from the specified source buffer.
/// Returns the number of bytes copied.
template <typename Const_Buffers>
std::size_t copy(const Const_Buffers& 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 Const_Buffers::const_iterator iter = buffers.begin();
typename Const_Buffers::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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BUFFERED_WRITE_STREAM_HPP

View File

@ -1,29 +0,0 @@
//
// buffered_write_stream_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_BUFFERED_WRITE_STREAM_FWD_HPP
#define ASIO_BUFFERED_WRITE_STREAM_FWD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
namespace asio {
template <typename Stream>
class buffered_write_stream;
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_BUFFERED_WRITE_STREAM_FWD_HPP

View File

@ -1,101 +0,0 @@
//
// completion_condition.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_COMPLETION_CONDITION_HPP
#define ASIO_COMPLETION_CONDITION_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
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.
#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.
#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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_COMPLETION_CONDITION_HPP

View File

@ -1,295 +0,0 @@
//
// datagram_socket_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DATAGRAM_SOCKET_SERVICE_HPP
#define ASIO_DATAGRAM_SOCKET_SERVICE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/io_service.hpp"
#include "asio/detail/epoll_reactor.hpp"
#include "asio/detail/kqueue_reactor.hpp"
#include "asio/detail/select_reactor.hpp"
#include "asio/detail/reactive_socket_service.hpp"
#include "asio/detail/win_iocp_socket_service.hpp"
namespace asio {
/// Default service implementation for a datagram socket.
template <typename Protocol>
class datagram_socket_service
: public asio::io_service::service
{
public:
/// 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(ASIO_HAS_IOCP)
typedef detail::win_iocp_socket_service<Protocol> service_impl_type;
#elif defined(ASIO_HAS_EPOLL)
typedef detail::reactive_socket_service<
Protocol, detail::epoll_reactor<false> > service_impl_type;
#elif defined(ASIO_HAS_KQUEUE)
typedef detail::reactive_socket_service<
Protocol, detail::kqueue_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(asio::io_service& io_service)
: asio::io_service::service(io_service),
service_impl_(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.
template <typename Error_Handler>
void open(implementation_type& impl, const protocol_type& protocol,
Error_Handler error_handler)
{
if (protocol.type() == SOCK_DGRAM)
service_impl_.open(impl, protocol, error_handler);
else
error_handler(asio::error(asio::error::invalid_argument));
}
/// Assign an existing native socket to a datagram socket.
template <typename Error_Handler>
void assign(implementation_type& impl, const protocol_type& protocol,
const native_type& native_socket, Error_Handler error_handler)
{
service_impl_.assign(impl, protocol, native_socket, error_handler);
}
/// Close a datagram socket implementation.
template <typename Error_Handler>
void close(implementation_type& impl, Error_Handler error_handler)
{
service_impl_.close(impl, error_handler);
}
/// Get the native socket implementation.
native_type native(implementation_type& impl)
{
return service_impl_.native(impl);
}
/// Cancel all asynchronous operations associated with the socket.
template <typename Error_Handler>
void cancel(implementation_type& impl, Error_Handler error_handler)
{
service_impl_.cancel(impl, error_handler);
}
// Bind the datagram socket to the specified local endpoint.
template <typename Error_Handler>
void bind(implementation_type& impl, const endpoint_type& endpoint,
Error_Handler error_handler)
{
service_impl_.bind(impl, endpoint, error_handler);
}
/// Connect the datagram socket to the specified endpoint.
template <typename Error_Handler>
void connect(implementation_type& impl, const endpoint_type& peer_endpoint,
Error_Handler error_handler)
{
service_impl_.connect(impl, peer_endpoint, error_handler);
}
/// Start an asynchronous connect.
template <typename Handler>
void async_connect(implementation_type& impl,
const endpoint_type& peer_endpoint, Handler handler)
{
service_impl_.async_connect(impl, peer_endpoint, handler);
}
/// Set a socket option.
template <typename Option, typename Error_Handler>
void set_option(implementation_type& impl, const Option& option,
Error_Handler error_handler)
{
service_impl_.set_option(impl, option, error_handler);
}
/// Get a socket option.
template <typename Option, typename Error_Handler>
void get_option(const implementation_type& impl, Option& option,
Error_Handler error_handler) const
{
service_impl_.get_option(impl, option, error_handler);
}
/// Perform an IO control command on the socket.
template <typename IO_Control_Command, typename Error_Handler>
void io_control(implementation_type& impl, IO_Control_Command& command,
Error_Handler error_handler)
{
service_impl_.io_control(impl, command, error_handler);
}
/// Get the local endpoint.
template <typename Error_Handler>
endpoint_type local_endpoint(const implementation_type& impl,
Error_Handler error_handler) const
{
endpoint_type endpoint;
service_impl_.get_local_endpoint(impl, endpoint, error_handler);
return endpoint;
}
/// Get the remote endpoint.
template <typename Error_Handler>
endpoint_type remote_endpoint(const implementation_type& impl,
Error_Handler error_handler) const
{
endpoint_type endpoint;
service_impl_.get_remote_endpoint(impl, endpoint, error_handler);
return endpoint;
}
/// Disable sends or receives on the socket.
template <typename Error_Handler>
void shutdown(implementation_type& impl, socket_base::shutdown_type what,
Error_Handler error_handler)
{
service_impl_.shutdown(impl, what, error_handler);
}
/// Send the given data to the peer.
template <typename Const_Buffers, typename Error_Handler>
std::size_t send(implementation_type& impl, const Const_Buffers& buffers,
socket_base::message_flags flags, Error_Handler error_handler)
{
return service_impl_.send(impl, buffers, flags, error_handler);
}
/// Start an asynchronous send.
template <typename Const_Buffers, typename Handler>
void async_send(implementation_type& impl, const Const_Buffers& buffers,
socket_base::message_flags flags, Handler handler)
{
service_impl_.async_send(impl, buffers, flags, handler);
}
/// Send a datagram to the specified endpoint.
template <typename Const_Buffers, typename Error_Handler>
std::size_t send_to(implementation_type& impl, const Const_Buffers& buffers,
const endpoint_type& destination, socket_base::message_flags flags,
Error_Handler error_handler)
{
return service_impl_.send_to(impl, buffers, destination, flags,
error_handler);
}
/// Start an asynchronous send.
template <typename Const_Buffers, typename Handler>
void async_send_to(implementation_type& impl, const Const_Buffers& buffers,
const endpoint_type& destination, socket_base::message_flags flags,
Handler handler)
{
service_impl_.async_send_to(impl, buffers, destination, flags, handler);
}
/// Receive some data from the peer.
template <typename Mutable_Buffers, typename Error_Handler>
std::size_t receive(implementation_type& impl, const Mutable_Buffers& buffers,
socket_base::message_flags flags, Error_Handler error_handler)
{
return service_impl_.receive(impl, buffers, flags, error_handler);
}
/// Start an asynchronous receive.
template <typename Mutable_Buffers, typename Handler>
void async_receive(implementation_type& impl, const Mutable_Buffers& buffers,
socket_base::message_flags flags, Handler handler)
{
service_impl_.async_receive(impl, buffers, flags, handler);
}
/// Receive a datagram with the endpoint of the sender.
template <typename Mutable_Buffers, typename Error_Handler>
std::size_t receive_from(implementation_type& impl,
const Mutable_Buffers& buffers, endpoint_type& sender_endpoint,
socket_base::message_flags flags, Error_Handler error_handler)
{
return service_impl_.receive_from(impl, buffers, sender_endpoint, flags,
error_handler);
}
/// Start an asynchronous receive that will get the endpoint of the sender.
template <typename Mutable_Buffers, typename Handler>
void async_receive_from(implementation_type& impl,
const Mutable_Buffers& buffers, endpoint_type& sender_endpoint,
socket_base::message_flags flags, Handler 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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DATAGRAM_SOCKET_SERVICE_HPP

View File

@ -1,37 +0,0 @@
//
// deadline_timer.hpp
// ~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DEADLINE_TIMER_HPP
#define ASIO_DEADLINE_TIMER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/socket_types.hpp" // Must come before posix_time.
#include "asio/detail/push_options.hpp"
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/basic_deadline_timer.hpp"
namespace asio {
/// Typedef for the typical usage of timer.
typedef basic_deadline_timer<boost::posix_time::ptime> deadline_timer;
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DEADLINE_TIMER_HPP

View File

@ -1,152 +0,0 @@
//
// deadline_timer_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DEADLINE_TIMER_SERVICE_HPP
#define ASIO_DEADLINE_TIMER_SERVICE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/io_service.hpp"
#include "asio/time_traits.hpp"
#include "asio/detail/deadline_timer_service.hpp"
#include "asio/detail/epoll_reactor.hpp"
#include "asio/detail/kqueue_reactor.hpp"
#include "asio/detail/select_reactor.hpp"
namespace asio {
/// Default service implementation for a timer.
template <typename Time_Type,
typename Time_Traits = asio::time_traits<Time_Type> >
class deadline_timer_service
: public asio::io_service::service
{
public:
/// The time traits type.
typedef Time_Traits 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(ASIO_HAS_IOCP)
typedef detail::deadline_timer_service<
traits_type, detail::select_reactor<true> > service_impl_type;
#elif defined(ASIO_HAS_EPOLL)
typedef detail::deadline_timer_service<
traits_type, detail::epoll_reactor<false> > service_impl_type;
#elif defined(ASIO_HAS_KQUEUE)
typedef detail::deadline_timer_service<
traits_type, detail::kqueue_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(asio::io_service& io_service)
: asio::io_service::service(io_service),
service_impl_(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)
{
return service_impl_.cancel(impl);
}
/// 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)
{
return service_impl_.expires_at(impl, expiry_time);
}
/// 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)
{
return service_impl_.expires_from_now(impl, expiry_time);
}
// Perform a blocking wait on the timer.
void wait(implementation_type& impl)
{
service_impl_.wait(impl);
}
// Start an asynchronous wait on the timer.
template <typename Handler>
void async_wait(implementation_type& impl, Handler handler)
{
service_impl_.async_wait(impl, handler);
}
private:
// The service that provides the platform-specific implementation.
service_impl_type& service_impl_;
};
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DEADLINE_TIMER_SERVICE_HPP

View File

@ -1,349 +0,0 @@
//
// bind_handler.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_BIND_HANDLER_HPP
#define ASIO_DETAIL_BIND_HANDLER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp"
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 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)
{
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)
{
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 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)
{
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)
{
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 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)
{
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)
{
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 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)
{
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)
{
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 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)
{
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)
{
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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_BIND_HANDLER_HPP

View File

@ -1,70 +0,0 @@
//
// buffer_resize_guard.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP
#define ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <limits>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP

View File

@ -1,127 +0,0 @@
//
// buffered_stream_storage.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP
#define ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include <cassert>
#include <cstddef>
#include <cstring>
#include <vector>
#include "asio/detail/pop_options.hpp"
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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP

View File

@ -1,90 +0,0 @@
//
// call_stack.hpp
// ~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_CALL_STACK_HPP
#define ASIO_DETAIL_CALL_STACK_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/tss_ptr.hpp"
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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_CALL_STACK_HPP

View File

@ -1,150 +0,0 @@
//
// const_buffers_iterator.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP
#define ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/buffer.hpp"
namespace asio {
namespace detail {
// A proxy iterator for a sub-range in a list of buffers.
template <typename Const_Buffers>
class const_buffers_iterator
: public boost::iterator_facade<const_buffers_iterator<Const_Buffers>,
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 Const_Buffers& 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 = asio::buffer_size(current_buffer_);
if (position - position_ < buffer_size)
{
current_buffer_position_ = position - position_;
position_ = position;
return;
}
position_ += buffer_size;
++current_;
}
current_buffer_ = 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_ != asio::buffer_size(current_buffer_))
return;
++current_;
current_buffer_position_ = 0;
while (current_ != end_)
{
current_buffer_ = *current_;
if (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 Const_Buffers::const_iterator iter = current_;
while (iter != begin_)
{
--iter;
asio::const_buffer buffer = *iter;
std::size_t buffer_size = 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 asio::buffer_cast<const char*>(
current_buffer_)[current_buffer_position_];
}
asio::const_buffer current_buffer_;
std::size_t current_buffer_position_;
typename Const_Buffers::const_iterator begin_;
typename Const_Buffers::const_iterator current_;
typename Const_Buffers::const_iterator end_;
std::size_t position_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_CONST_BUFFERS_ITERATOR_HPP

View File

@ -1,196 +0,0 @@
//
// consuming_buffers.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_CONSUMING_BUFFERS_HPP
#define ASIO_DETAIL_CONSUMING_BUFFERS_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <algorithm>
#include <cstddef>
#include <boost/config.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include "asio/detail/pop_options.hpp"
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_(first),
begin_remainder_(begin_remainder),
end_remainder_(end_remainder)
{
}
private:
friend class boost::iterator_core_access;
void increment()
{
if (!at_end_)
{
if (begin_remainder_ == end_remainder_)
at_end_ = true;
else
first_ = *begin_remainder_++;
}
}
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_;
};
// 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_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_CONSUMING_BUFFERS_HPP

View File

@ -1,182 +0,0 @@
//
// deadline_timer_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP
#define ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/error.hpp"
#include "asio/io_service.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_ops.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/timer_queue.hpp"
namespace asio {
namespace detail {
template <typename Time_Traits, typename Timer_Scheduler>
class deadline_timer_service
: public asio::io_service::service
{
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 asio::detail::noncopyable
{
time_type expiry;
bool might_have_pending_waits;
};
// Constructor.
deadline_timer_service(asio::io_service& io_service)
: asio::io_service::service(io_service),
scheduler_(asio::use_service<Timer_Scheduler>(io_service))
{
scheduler_.add_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)
{
cancel(impl);
}
// Cancel any asynchronous wait operations associated with the timer.
std::size_t cancel(implementation_type& impl)
{
if (!impl.might_have_pending_waits)
return 0;
std::size_t count = scheduler_.cancel_timer(timer_queue_, &impl);
impl.might_have_pending_waits = false;
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)
{
std::size_t count = cancel(impl);
impl.expiry = expiry_time;
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)
{
return expires_at(impl, Time_Traits::add(Time_Traits::now(), expiry_time));
}
// Perform a blocking wait on the timer.
void wait(implementation_type& impl)
{
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;
socket_ops::select(0, 0, 0, 0, &tv);
now = Time_Traits::now();
}
}
template <typename Handler>
class wait_handler
{
public:
wait_handler(asio::io_service& io_service, Handler handler)
: io_service_(io_service),
work_(io_service),
handler_(handler)
{
}
void operator()(int result)
{
asio::error e(result);
io_service_.post(detail::bind_handler(handler_, e));
}
private:
asio::io_service& io_service_;
asio::io_service::work work_;
Handler handler_;
};
// 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>(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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP

View File

@ -1,593 +0,0 @@
//
// epoll_reactor.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_EPOLL_REACTOR_HPP
#define ASIO_DETAIL_EPOLL_REACTOR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/epoll_reactor_fwd.hpp"
#if defined(ASIO_HAS_EPOLL)
#include "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 "asio/detail/pop_options.hpp"
#include "asio/io_service.hpp"
#include "asio/system_exception.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/hash_map.hpp"
#include "asio/detail/mutex.hpp"
#include "asio/detail/task_io_service.hpp"
#include "asio/detail/thread.hpp"
#include "asio/detail/reactor_op_queue.hpp"
#include "asio/detail/select_interrupter.hpp"
#include "asio/detail/signal_blocker.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/timer_queue.hpp"
namespace asio {
namespace detail {
template <bool Own_Thread>
class epoll_reactor
: public asio::io_service::service
{
public:
// Constructor.
epoll_reactor(asio::io_service& io_service)
: asio::io_service::service(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)
{
// Start the reactor's internal thread only if needed.
if (Own_Thread)
{
asio::detail::signal_blocker sb;
thread_ = new 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()
{
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)
{
// No need to lock according to epoll documentation.
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, Handler handler)
{
asio::detail::mutex::scoped_lock lock(mutex_);
if (shutdown_)
return;
if (!read_op_queue_.has_operation(descriptor))
if (handler(0))
return;
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)
{
int error = errno;
read_op_queue_.dispatch_all_operations(descriptor, error);
}
}
}
// 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, Handler handler)
{
asio::detail::mutex::scoped_lock lock(mutex_);
if (shutdown_)
return;
if (!write_op_queue_.has_operation(descriptor))
if (handler(0))
return;
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)
{
int error = errno;
write_op_queue_.dispatch_all_operations(descriptor, error);
}
}
}
// 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, Handler handler)
{
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)
{
int error = errno;
except_op_queue_.dispatch_all_operations(descriptor, error);
}
}
}
// 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.
template <typename Handler>
void start_write_and_except_ops(socket_type descriptor, Handler handler)
{
asio::detail::mutex::scoped_lock lock(mutex_);
if (shutdown_)
return;
bool need_mod = write_op_queue_.enqueue_operation(descriptor, handler);
need_mod = except_op_queue_.enqueue_operation(descriptor, handler)
&& need_mod;
if (need_mod)
{
epoll_event ev = { 0, { 0 } };
ev.events = EPOLLOUT | EPOLLPRI | EPOLLERR | EPOLLHUP;
if (read_op_queue_.has_operation(descriptor))
ev.events |= EPOLLIN;
ev.data.fd = descriptor;
int result = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
if (result != 0)
{
int error = errno;
write_op_queue_.dispatch_all_operations(descriptor, error);
except_op_queue_.dispatch_all_operations(descriptor, error);
}
}
}
// 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)
{
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
// epoll_reactor's mutex, and so should only be used from within a reactor
// handler.
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)
{
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)
{
asio::detail::mutex::scoped_lock lock(mutex_);
timer_queues_.push_back(&timer_queue);
}
// 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)
{
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)
{
asio::detail::mutex::scoped_lock lock(mutex_);
return timer_queue.cancel_timer(token);
}
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)
{
asio::detail::mutex::scoped_lock lock(mutex_);
// Dispatch any operation cancellations that were made while the select
// loop was not running.
read_op_queue_.dispatch_cancellations();
write_op_queue_.dispatch_cancellations();
except_op_queue_.dispatch_cancellations();
// Check if the thread is supposed to stop.
if (stop_thread_)
{
// Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
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())
{
// Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
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 = epoll_wait(epoll_fd_, events, 128, timeout);
lock.lock();
wait_in_progress_ = false;
// Block signals while dispatching operations.
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
{
if (events[i].events & (EPOLLERR | EPOLLHUP))
{
except_op_queue_.dispatch_all_operations(descriptor, 0);
read_op_queue_.dispatch_all_operations(descriptor, 0);
write_op_queue_.dispatch_all_operations(descriptor, 0);
epoll_event ev = { 0, { 0 } };
ev.events = 0;
ev.data.fd = descriptor;
epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);
}
else
{
bool more_reads = false;
bool more_writes = false;
bool more_except = false;
// Exception operations must be processed first to ensure that any
// out-of-band data is read before normal data.
if (events[i].events & EPOLLPRI)
more_except = except_op_queue_.dispatch_operation(descriptor, 0);
else
more_except = except_op_queue_.has_operation(descriptor);
if (events[i].events & EPOLLIN)
more_reads = read_op_queue_.dispatch_operation(descriptor, 0);
else
more_reads = read_op_queue_.has_operation(descriptor);
if (events[i].events & EPOLLOUT)
more_writes = write_op_queue_.dispatch_operation(descriptor, 0);
else
more_writes = write_op_queue_.has_operation(descriptor);
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)
{
int error = errno;
read_op_queue_.dispatch_all_operations(descriptor, error);
write_op_queue_.dispatch_all_operations(descriptor, error);
except_op_queue_.dispatch_all_operations(descriptor, error);
}
}
}
}
read_op_queue_.dispatch_cancellations();
write_op_queue_.dispatch_cancellations();
except_op_queue_.dispatch_cancellations();
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
timer_queues_[i]->dispatch_timers();
// Issue any pending cancellations.
for (size_t i = 0; i < pending_cancellations_.size(); ++i)
cancel_ops_unlocked(pending_cancellations_[i]);
pending_cancellations_.clear();
// Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
}
// Run the select loop in the thread.
void run_thread()
{
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)
{
system_exception e("epoll", errno);
boost::throw_exception(e);
}
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())
{
return minimum_wait_duration.total_milliseconds();
}
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();
}
// Mutex to protect access to internal data.
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_;
// 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.
asio::detail::thread* thread_;
// Whether the service has been shut down.
bool shutdown_;
};
} // namespace detail
} // namespace asio
#endif // defined(ASIO_HAS_EPOLL)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_EPOLL_REACTOR_HPP

View File

@ -1,47 +0,0 @@
//
// epoll_reactor_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP
#define ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#if !defined(ASIO_DISABLE_EPOLL)
#if defined(__linux__) // This service is only supported on Linux.
#include "asio/detail/push_options.hpp"
#include <linux/version.h>
#include "asio/detail/pop_options.hpp"
#if LINUX_VERSION_CODE >= KERNEL_VERSION (2,5,45) // Only kernels >= 2.5.45.
// Define this to indicate that epoll is supported on the target platform.
#define ASIO_HAS_EPOLL 1
namespace asio {
namespace detail {
template <bool Own_Thread>
class epoll_reactor;
} // namespace detail
} // namespace asio
#endif // LINUX_VERSION_CODE >= KERNEL_VERSION (2,5,45)
#endif // defined(__linux__)
#endif // !defined(ASIO_DISABLE_EPOLL)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_EPOLL_REACTOR_FWD_HPP

View File

@ -1,50 +0,0 @@
//
// event.hpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_EVENT_HPP
#define ASIO_DETAIL_EVENT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if !defined(BOOST_HAS_THREADS)
# include "asio/detail/null_event.hpp"
#elif defined(BOOST_WINDOWS)
# include "asio/detail/win_event.hpp"
#elif defined(BOOST_HAS_PTHREADS)
# include "asio/detail/posix_event.hpp"
#else
# error Only Windows and POSIX are supported!
#endif
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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_EVENT_HPP

View File

@ -1,41 +0,0 @@
//
// fd_set_adapter.hpp
// ~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_FD_SET_ADAPTER_HPP
#define ASIO_DETAIL_FD_SET_ADAPTER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/detail/posix_fd_set_adapter.hpp"
#include "asio/detail/win_fd_set_adapter.hpp"
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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_FD_SET_ADAPTER_HPP

View File

@ -1,256 +0,0 @@
//
// handler_alloc_helpers.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP
#define ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/detail/workaround.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/handler_alloc_hook.hpp"
#include "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
// asio_handler_alloc_helpers namespace is defined here for that purpose.
namespace 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 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 asio;
asio_handler_deallocate(p, s, h);
#endif
}
} // namespace asio_handler_alloc_helpers
namespace asio {
namespace detail {
// Traits for handler allocation.
template <typename Handler, typename Object>
struct handler_alloc_traits
{
typedef Handler handler_type;
typedef Object value_type;
typedef Object* pointer_type;
BOOST_STATIC_CONSTANT(std::size_t, value_size = sizeof(Object));
};
template <typename Alloc_Traits>
class handler_ptr;
// Helper class to provide RAII on uninitialised handler memory.
template <typename Alloc_Traits>
class raw_handler_ptr
: private noncopyable
{
public:
typedef typename Alloc_Traits::handler_type handler_type;
typedef typename Alloc_Traits::value_type value_type;
typedef typename Alloc_Traits::pointer_type pointer_type;
BOOST_STATIC_CONSTANT(std::size_t, value_size = Alloc_Traits::value_size);
// Constructor allocates the memory.
raw_handler_ptr(handler_type& handler)
: handler_(handler),
pointer_(static_cast<pointer_type>(
asio_handler_alloc_helpers::allocate(value_size, &handler_)))
{
}
// Destructor automatically deallocates memory, unless it has been stolen by
// a handler_ptr object.
~raw_handler_ptr()
{
if (pointer_)
asio_handler_alloc_helpers::deallocate(
pointer_, value_size, &handler_);
}
private:
friend class handler_ptr<Alloc_Traits>;
handler_type& handler_;
pointer_type pointer_;
};
// Helper class to provide RAII on uninitialised handler memory.
template <typename Alloc_Traits>
class handler_ptr
: private noncopyable
{
public:
typedef typename Alloc_Traits::handler_type handler_type;
typedef typename Alloc_Traits::value_type value_type;
typedef typename Alloc_Traits::pointer_type pointer_type;
BOOST_STATIC_CONSTANT(std::size_t, value_size = Alloc_Traits::value_size);
typedef raw_handler_ptr<Alloc_Traits> raw_ptr_type;
// Take ownership of existing memory.
handler_ptr(handler_type& handler, pointer_type pointer)
: handler_(handler),
pointer_(pointer)
{
}
// Construct object in raw memory and take ownership if construction succeeds.
handler_ptr(raw_ptr_type& raw_ptr)
: handler_(raw_ptr.handler_),
pointer_(new (raw_ptr.pointer_) value_type)
{
raw_ptr.pointer_ = 0;
}
// Construct object in raw memory and take ownership if construction succeeds.
template <typename Arg1>
handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1)
: handler_(raw_ptr.handler_),
pointer_(new (raw_ptr.pointer_) value_type(a1))
{
raw_ptr.pointer_ = 0;
}
// Construct object in raw memory and take ownership if construction succeeds.
template <typename Arg1, typename Arg2>
handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2)
: handler_(raw_ptr.handler_),
pointer_(new (raw_ptr.pointer_) value_type(a1, a2))
{
raw_ptr.pointer_ = 0;
}
// Construct object in raw memory and take ownership if construction succeeds.
template <typename Arg1, typename Arg2, typename Arg3>
handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3)
: handler_(raw_ptr.handler_),
pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3))
{
raw_ptr.pointer_ = 0;
}
// Construct object in raw memory and take ownership if construction succeeds.
template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4)
: handler_(raw_ptr.handler_),
pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4))
{
raw_ptr.pointer_ = 0;
}
// Construct object in raw memory and take ownership if construction succeeds.
template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
typename Arg5>
handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
Arg5& a5)
: handler_(raw_ptr.handler_),
pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5))
{
raw_ptr.pointer_ = 0;
}
// Construct object in raw memory and take ownership if construction succeeds.
template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
typename Arg5, typename Arg6>
handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
Arg5& a5, Arg6& a6)
: handler_(raw_ptr.handler_),
pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5, a6))
{
raw_ptr.pointer_ = 0;
}
// Construct object in raw memory and take ownership if construction succeeds.
template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
typename Arg5, typename Arg6, typename Arg7>
handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
Arg5& a5, Arg6& a6, Arg7& a7)
: handler_(raw_ptr.handler_),
pointer_(new (raw_ptr.pointer_) value_type(a1, a2, a3, a4, a5, a6, a7))
{
raw_ptr.pointer_ = 0;
}
// Construct object in raw memory and take ownership if construction succeeds.
template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
typename Arg5, typename Arg6, typename Arg7, typename Arg8>
handler_ptr(raw_ptr_type& raw_ptr, Arg1& a1, Arg2& a2, Arg3& a3, Arg4& a4,
Arg5& a5, Arg6& a6, Arg7& a7, Arg8& a8)
: handler_(raw_ptr.handler_),
pointer_(new (raw_ptr.pointer_) value_type(
a1, a2, a3, a4, a5, a6, a7, a8))
{
raw_ptr.pointer_ = 0;
}
// Destructor automatically deallocates memory, unless it has been released.
~handler_ptr()
{
reset();
}
// Get the memory.
pointer_type get() const
{
return pointer_;
}
// Release ownership of the memory.
pointer_type release()
{
pointer_type tmp = pointer_;
pointer_ = 0;
return tmp;
}
// Explicitly destroy and deallocate the memory.
void reset()
{
if (pointer_)
{
pointer_->value_type::~value_type();
asio_handler_alloc_helpers::deallocate(
pointer_, value_size, &handler_);
pointer_ = 0;
}
}
private:
handler_type& handler_;
pointer_type pointer_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP

View File

@ -1,47 +0,0 @@
//
// handler_invoke_helpers.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP
#define ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/detail/workaround.hpp>
#include "asio/detail/pop_options.hpp"
#include "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 asio_handler_invoke_helpers
// namespace is defined here for that purpose.
namespace 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 asio;
asio_handler_invoke(function, context);
#endif
}
} // namespace asio_handler_invoke_helpers
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP

View File

@ -1,197 +0,0 @@
//
// hash_map.hpp
// ~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_HASH_MAP_HPP
#define ASIO_DETAIL_HASH_MAP_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cassert>
#include <list>
#include <utility>
#include <boost/functional/hash.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/detail/noncopyable.hpp"
namespace asio {
namespace detail {
using boost::hash_value;
template <typename K, typename V>
class hash_map
: private noncopyable
{
public:
// The type of a value in the map.
typedef std::pair<const 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 = 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 = 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 = 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 = 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:
// The list of all values in the hash map.
std::list<value_type> values_;
// 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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_HASH_MAP_HPP

View File

@ -1,137 +0,0 @@
//
// io_control.hpp
// ~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_IO_CONTROL_HPP
#define ASIO_DETAIL_IO_CONTROL_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/detail/socket_types.hpp"
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_(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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_IO_CONTROL_HPP

View File

@ -1,596 +0,0 @@
//
// kqueue_reactor.hpp
// ~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_KQUEUE_REACTOR_HPP
#define ASIO_DETAIL_KQUEUE_REACTOR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/kqueue_reactor_fwd.hpp"
#if defined(ASIO_HAS_KQUEUE)
#include "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 "asio/detail/pop_options.hpp"
#include "asio/io_service.hpp"
#include "asio/system_exception.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/mutex.hpp"
#include "asio/detail/task_io_service.hpp"
#include "asio/detail/thread.hpp"
#include "asio/detail/reactor_op_queue.hpp"
#include "asio/detail/select_interrupter.hpp"
#include "asio/detail/signal_blocker.hpp"
#include "asio/detail/socket_types.hpp"
#include "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 asio {
namespace detail {
template <bool Own_Thread>
class kqueue_reactor
: public asio::io_service::service
{
public:
// Constructor.
kqueue_reactor(asio::io_service& io_service)
: asio::io_service::service(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)
{
// Start the reactor's internal thread only if needed.
if (Own_Thread)
{
asio::detail::signal_blocker sb;
thread_ = new 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()
{
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)
{
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, Handler handler)
{
asio::detail::mutex::scoped_lock lock(mutex_);
if (shutdown_)
return;
if (!read_op_queue_.has_operation(descriptor))
if (handler(0))
return;
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)
{
int error = errno;
read_op_queue_.dispatch_all_operations(descriptor, error);
}
}
}
// 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, Handler handler)
{
asio::detail::mutex::scoped_lock lock(mutex_);
if (shutdown_)
return;
if (!write_op_queue_.has_operation(descriptor))
if (handler(0))
return;
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)
{
int error = errno;
write_op_queue_.dispatch_all_operations(descriptor, error);
}
}
}
// 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, Handler handler)
{
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)
{
int error = errno;
except_op_queue_.dispatch_all_operations(descriptor, error);
}
}
}
// 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.
template <typename Handler>
void start_write_and_except_ops(socket_type descriptor, Handler handler)
{
asio::detail::mutex::scoped_lock lock(mutex_);
if (shutdown_)
return;
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)
{
int error = errno;
write_op_queue_.dispatch_all_operations(descriptor, error);
}
}
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)
{
int error = errno;
except_op_queue_.dispatch_all_operations(descriptor, error);
write_op_queue_.dispatch_all_operations(descriptor, error);
}
}
}
// 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)
{
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
// kqueue_reactor's mutex, and so should only be used from within a reactor
// handler.
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)
{
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)
{
asio::detail::mutex::scoped_lock lock(mutex_);
timer_queues_.push_back(&timer_queue);
}
// 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)
{
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)
{
asio::detail::mutex::scoped_lock lock(mutex_);
return timer_queue.cancel_timer(token);
}
private:
friend class task_io_service<kqueue_reactor<Own_Thread> >;
// Run the kqueue loop.
void run(bool block)
{
asio::detail::mutex::scoped_lock lock(mutex_);
// Dispatch any operation cancellations that were made while the select
// loop was not running.
read_op_queue_.dispatch_cancellations();
write_op_queue_.dispatch_cancellations();
except_op_queue_.dispatch_cancellations();
// Check if the thread is supposed to stop.
if (stop_thread_)
{
// Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
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())
{
// Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
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 = kevent(kqueue_fd_, 0, 0, events, 128, timeout);
lock.lock();
wait_in_progress_ = false;
// Block signals while dispatching operations.
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)
{
int error = events[i].data;
except_op_queue_.dispatch_all_operations(descriptor, error);
read_op_queue_.dispatch_all_operations(descriptor, error);
}
else if (events[i].flags & EV_OOBAND)
{
more_except = except_op_queue_.dispatch_operation(descriptor, 0);
if (events[i].data > 0)
more_reads = read_op_queue_.dispatch_operation(descriptor, 0);
else
more_reads = read_op_queue_.has_operation(descriptor);
}
else
{
more_reads = read_op_queue_.dispatch_operation(descriptor, 0);
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)
{
int error = errno;
except_op_queue_.dispatch_all_operations(descriptor, error);
read_op_queue_.dispatch_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)
{
int error = events[i].data;
write_op_queue_.dispatch_all_operations(descriptor, error);
}
else
{
more_writes = write_op_queue_.dispatch_operation(descriptor, 0);
}
// 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)
{
int error = errno;
write_op_queue_.dispatch_all_operations(descriptor, error);
}
}
}
read_op_queue_.dispatch_cancellations();
write_op_queue_.dispatch_cancellations();
except_op_queue_.dispatch_cancellations();
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
timer_queues_[i]->dispatch_timers();
// Issue any pending cancellations.
for (std::size_t i = 0; i < pending_cancellations_.size(); ++i)
cancel_ops_unlocked(pending_cancellations_[i]);
pending_cancellations_.clear();
// Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
}
// Run the select loop in the thread.
void run_thread()
{
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)
{
system_exception e("kqueue", errno);
boost::throw_exception(e);
}
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 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();
}
// Mutex to protect access to internal data.
asio::detail::mutex mutex_;
// The epoll 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 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_;
// 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.
asio::detail::thread* thread_;
// Whether the service has been shut down.
bool shutdown_;
};
} // namespace detail
} // namespace asio
#endif // defined(ASIO_HAS_KQUEUE)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_KQUEUE_REACTOR_HPP

View File

@ -1,41 +0,0 @@
//
// kqueue_reactor_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP
#define ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#if !defined(ASIO_DISABLE_KQUEUE)
#if defined(__MACH__) && defined(__APPLE__)
// Define this to indicate that epoll is supported on the target platform.
#define ASIO_HAS_KQUEUE 1
namespace asio {
namespace detail {
template <bool Own_Thread>
class kqueue_reactor;
} // namespace detail
} // namespace asio
#endif // defined(__MACH__) && defined(__APPLE__)
#endif // !defined(ASIO_DISABLE_KQUEUE)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP

View File

@ -1,50 +0,0 @@
//
// mutex.hpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_MUTEX_HPP
#define ASIO_DETAIL_MUTEX_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if !defined(BOOST_HAS_THREADS)
# include "asio/detail/null_mutex.hpp"
#elif defined(BOOST_WINDOWS)
# include "asio/detail/win_mutex.hpp"
#elif defined(BOOST_HAS_PTHREADS)
# include "asio/detail/posix_mutex.hpp"
#else
# error Only Windows and POSIX are supported!
#endif
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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_MUTEX_HPP

View File

@ -1,55 +0,0 @@
//
// noncopyable.hpp
// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_NONCOPYABLE_HPP
#define ASIO_DETAIL_NONCOPYABLE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include <boost/noncopyable.hpp>
#include <boost/detail/workaround.hpp>
#include "asio/detail/pop_options.hpp"
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 asio::detail::noncopyable;
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_NONCOPYABLE_HPP

View File

@ -1,68 +0,0 @@
//
// null_event.hpp
// ~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_NULL_EVENT_HPP
#define ASIO_DETAIL_NULL_EVENT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if !defined(BOOST_HAS_THREADS)
#include "asio/detail/noncopyable.hpp"
namespace asio {
namespace detail {
class null_event
: private noncopyable
{
public:
// Constructor.
null_event()
{
}
// Destructor.
~null_event()
{
}
// Signal the event.
void signal()
{
}
// Reset the event.
void clear()
{
}
// Wait for the event to become signalled.
void wait()
{
}
};
} // namespace detail
} // namespace asio
#endif // !defined(BOOST_HAS_THREADS)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_NULL_EVENT_HPP

View File

@ -1,66 +0,0 @@
//
// null_mutex.hpp
// ~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_NULL_MUTEX_HPP
#define ASIO_DETAIL_NULL_MUTEX_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if !defined(BOOST_HAS_THREADS)
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/scoped_lock.hpp"
namespace asio {
namespace detail {
class null_mutex
: private noncopyable
{
public:
typedef 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
#endif // !defined(BOOST_HAS_THREADS)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_NULL_MUTEX_HPP

View File

@ -1,63 +0,0 @@
//
// null_signal_blocker.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_NULL_SIGNAL_BLOCKER_HPP
#define ASIO_DETAIL_NULL_SIGNAL_BLOCKER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if !defined(BOOST_HAS_THREADS)
#include "asio/detail/noncopyable.hpp"
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
#endif // !defined(BOOST_HAS_THREADS)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_NULL_SIGNAL_BLOCKER_HPP

View File

@ -1,67 +0,0 @@
//
// null_thread.hpp
// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_NULL_THREAD_HPP
#define ASIO_DETAIL_NULL_THREAD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if !defined(BOOST_HAS_THREADS)
#include "asio/detail/push_options.hpp"
#include <boost/throw_exception.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/error.hpp"
#include "asio/system_exception.hpp"
#include "asio/detail/noncopyable.hpp"
namespace asio {
namespace detail {
class null_thread
: private noncopyable
{
public:
// Constructor.
template <typename Function>
null_thread(Function f)
{
system_exception e("thread", asio::error::not_supported);
boost::throw_exception(e);
}
// Destructor.
~null_thread()
{
}
// Wait for the thread to exit.
void join()
{
}
};
} // namespace detail
} // namespace asio
#endif // !defined(BOOST_HAS_THREADS)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_NULL_THREAD_HPP

View File

@ -1,70 +0,0 @@
//
// null_tss_ptr.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_NULL_TSS_PTR_HPP
#define ASIO_DETAIL_NULL_TSS_PTR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if !defined(BOOST_HAS_THREADS)
#include "asio/detail/noncopyable.hpp"
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
#endif // !defined(BOOST_HAS_THREADS)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_NULL_TSS_PTR_HPP

View File

@ -1,312 +0,0 @@
//
// old_win_sdk_compat.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_OLD_WIN_SDK_COMPAT_HPP
#define ASIO_DETAIL_OLD_WIN_SDK_COMPAT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
// Guess whether we are building against on old Platform SDK.
#if !defined(IPPROTO_IPV6)
#define ASIO_HAS_OLD_WIN_SDK 1
#endif // !defined(IPPROTO_IPV6)
#if defined(ASIO_HAS_OLD_WIN_SDK)
// Emulation of types that are missing from old Platform SDKs.
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
{
u_char s6_addr[16];
};
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_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
#endif // defined(ASIO_HAS_OLD_WIN_SDK)
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_OLD_WIN_SDK_COMPAT_HPP

View File

@ -1,104 +0,0 @@
//
// pipe_select_interrupter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP
#define ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
#include "asio/detail/push_options.hpp"
#include <fcntl.h>
#include "asio/detail/pop_options.hpp"
#include "asio/detail/socket_types.hpp"
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);
}
}
// 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
#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP

View File

@ -1,88 +0,0 @@
//
// pop_options.hpp
// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the 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

View File

@ -1,107 +0,0 @@
//
// posix_event.hpp
// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_POSIX_EVENT_HPP
#define ASIO_DETAIL_POSIX_EVENT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if defined(BOOST_HAS_PTHREADS)
#include "asio/detail/push_options.hpp"
#include <boost/throw_exception.hpp>
#include <pthread.h>
#include "asio/detail/pop_options.hpp"
#include "asio/system_exception.hpp"
#include "asio/detail/noncopyable.hpp"
namespace asio {
namespace detail {
class posix_event
: private noncopyable
{
public:
// Constructor.
posix_event()
: signalled_(false)
{
int error = ::pthread_mutex_init(&mutex_, 0);
if (error != 0)
{
system_exception e("event", error);
boost::throw_exception(e);
}
error = ::pthread_cond_init(&cond_, 0);
if (error != 0)
{
::pthread_mutex_destroy(&mutex_);
system_exception e("event", error);
boost::throw_exception(e);
}
}
// Destructor.
~posix_event()
{
::pthread_cond_destroy(&cond_);
::pthread_mutex_destroy(&mutex_);
}
// Signal the event.
void signal()
{
::pthread_mutex_lock(&mutex_); // Ignore EINVAL and EDEADLK.
signalled_ = true;
::pthread_cond_signal(&cond_); // Ignore EINVAL.
::pthread_mutex_unlock(&mutex_); // Ignore EINVAL and EPERM.
}
// Reset the event.
void clear()
{
::pthread_mutex_lock(&mutex_); // Ignore EINVAL and EDEADLK.
signalled_ = false;
::pthread_mutex_unlock(&mutex_); // Ignore EINVAL and EPERM.
}
// Wait for the event to become signalled.
void wait()
{
::pthread_mutex_lock(&mutex_); // Ignore EINVAL and EDEADLK.
while (!signalled_)
::pthread_cond_wait(&cond_, &mutex_); // Ignore EINVAL.
::pthread_mutex_unlock(&mutex_); // Ignore EINVAL and EPERM.
}
private:
::pthread_mutex_t mutex_;
::pthread_cond_t cond_;
bool signalled_;
};
} // namespace detail
} // namespace asio
#endif // defined(BOOST_HAS_PTHREADS)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_POSIX_EVENT_HPP

View File

@ -1,71 +0,0 @@
//
// posix_fd_set_adapter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP
#define ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/socket_types.hpp"
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
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)
{
FD_ZERO(&fd_set_);
}
void set(socket_type descriptor)
{
if (max_descriptor_ == invalid_socket || descriptor > max_descriptor_)
max_descriptor_ = descriptor;
FD_SET(descriptor, &fd_set_);
}
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:
fd_set fd_set_;
socket_type max_descriptor_;
};
} // namespace detail
} // namespace asio
#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP

View File

@ -1,94 +0,0 @@
//
// posix_mutex.hpp
// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_POSIX_MUTEX_HPP
#define ASIO_DETAIL_POSIX_MUTEX_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if defined(BOOST_HAS_PTHREADS)
#include "asio/detail/push_options.hpp"
#include <boost/throw_exception.hpp>
#include <pthread.h>
#include "asio/detail/pop_options.hpp"
#include "asio/system_exception.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/scoped_lock.hpp"
namespace asio {
namespace detail {
class posix_mutex
: private noncopyable
{
public:
typedef asio::detail::scoped_lock<posix_mutex> scoped_lock;
// Constructor.
posix_mutex()
{
int error = ::pthread_mutex_init(&mutex_, 0);
if (error != 0)
{
system_exception e("mutex", error);
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)
{
system_exception e("mutex", error);
boost::throw_exception(e);
}
}
// Unlock the mutex.
void unlock()
{
int error = ::pthread_mutex_unlock(&mutex_);
if (error != 0)
{
system_exception e("mutex", error);
boost::throw_exception(e);
}
}
private:
::pthread_mutex_t mutex_;
};
} // namespace detail
} // namespace asio
#endif // defined(BOOST_HAS_PTHREADS)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_POSIX_MUTEX_HPP

View File

@ -1,89 +0,0 @@
//
// posix_signal_blocker.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP
#define ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if defined(BOOST_HAS_PTHREADS)
#include "asio/detail/push_options.hpp"
#include <csignal>
#include <pthread.h>
#include "asio/detail/pop_options.hpp"
#include "asio/detail/noncopyable.hpp"
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
#endif // defined(BOOST_HAS_PTHREADS)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP

View File

@ -1,125 +0,0 @@
//
// posix_thread.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_POSIX_THREAD_HPP
#define ASIO_DETAIL_POSIX_THREAD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if defined(BOOST_HAS_PTHREADS)
#include "asio/detail/push_options.hpp"
#include <memory>
#include <boost/throw_exception.hpp>
#include <pthread.h>
#include "asio/detail/pop_options.hpp"
#include "asio/system_exception.hpp"
#include "asio/detail/noncopyable.hpp"
namespace asio {
namespace detail {
extern "C" void* asio_detail_posix_thread_function(void* arg);
class posix_thread
: private noncopyable
{
public:
// Constructor.
template <typename Function>
posix_thread(Function f)
: joined_(false)
{
std::auto_ptr<func_base> arg(new func<Function>(f));
int error = ::pthread_create(&thread_, 0,
asio_detail_posix_thread_function, arg.get());
if (error != 0)
{
system_exception e("thread", error);
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
#endif // defined(BOOST_HAS_PTHREADS)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_POSIX_THREAD_HPP

View File

@ -1,84 +0,0 @@
//
// posix_tss_ptr.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_POSIX_TSS_PTR_HPP
#define ASIO_DETAIL_POSIX_TSS_PTR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if defined(BOOST_HAS_PTHREADS)
#include "asio/detail/push_options.hpp"
#include <boost/throw_exception.hpp>
#include <pthread.h>
#include "asio/detail/pop_options.hpp"
#include "asio/system_exception.hpp"
#include "asio/detail/noncopyable.hpp"
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)
{
system_exception e("tss", error);
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
#endif // defined(BOOST_HAS_PTHREADS)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_POSIX_TSS_PTR_HPP

View File

@ -1,106 +0,0 @@
//
// push_options.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the 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:4244)
# pragma warning (disable:4355)
# pragma warning (disable:4675)
# 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

File diff suppressed because it is too large Load Diff

View File

@ -1,379 +0,0 @@
//
// reactor_op_queue.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_REACTOR_OP_QUEUE_HPP
#define ASIO_DETAIL_REACTOR_OP_QUEUE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <memory>
#include "asio/detail/pop_options.hpp"
#include "asio/error.hpp"
#include "asio/detail/hash_map.hpp"
#include "asio/detail/noncopyable.hpp"
namespace asio {
namespace detail {
template <typename Descriptor>
class reactor_op_queue
: private noncopyable
{
public:
// Constructor.
reactor_op_queue()
: operations_(),
cancelled_operations_(0),
cleanup_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 Handler>
bool enqueue_operation(Descriptor descriptor, Handler handler)
{
op_base* new_op = new op<Handler>(descriptor, handler);
typedef typename operation_map::iterator iterator;
typedef typename operation_map::value_type value_type;
std::pair<iterator, bool> entry =
operations_.insert(value_type(descriptor, new_op));
if (entry.second)
return true;
op_base* current_op = entry.first->second;
while (current_op->next_)
current_op = current_op->next_;
current_op->next_ = new_op;
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 dispatch_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();
}
// Dispatch the first operation corresponding to the descriptor. Returns true
// if there are more operations queued for the descriptor.
bool dispatch_operation(Descriptor descriptor, int 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_ = cleanup_operations_;
cleanup_operations_ = this_op;
bool done = this_op->invoke(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 cleanup list.
cleanup_operations_ = this_op->next_;
this_op->next_ = i->second;
i->second = this_op;
return true;
}
}
return false;
}
// Dispatch all operations corresponding to the descriptor.
void dispatch_all_operations(Descriptor descriptor, int 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_ = cleanup_operations_;
cleanup_operations_ = this_op;
bool done = this_op->invoke(result);
if (!done)
{
// Operation has not finished yet, so leave at front of queue, and
// remove from the cleanup list.
cleanup_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())
{
descriptors.set(i->first);
++i;
}
}
// Dispatch the operations corresponding to the ready file descriptors
// contained in the given descriptor set.
template <typename Descriptor_Set>
void dispatch_descriptors(const Descriptor_Set& descriptors, int 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_ = cleanup_operations_;
cleanup_operations_ = this_op;
bool done = this_op->invoke(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 cleanup list.
cleanup_operations_ = this_op->next_;
this_op->next_ = op_iter->second;
op_iter->second = this_op;
}
}
}
}
// Dispatch any pending cancels for operations.
void dispatch_cancellations()
{
while (cancelled_operations_)
{
op_base* this_op = cancelled_operations_;
cancelled_operations_ = this_op->next_;
this_op->next_ = cleanup_operations_;
cleanup_operations_ = this_op;
this_op->invoke(asio::error::operation_aborted);
}
}
// Destroy operations that are waiting to be cleaned up.
void cleanup_operations()
{
while (cleanup_operations_)
{
op_base* next_op = cleanup_operations_->next_;
cleanup_operations_->next_ = 0;
cleanup_operations_->destroy();
cleanup_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 (cleanup_operations_)
{
op_base* next_op = cleanup_operations_->next_;
cleanup_operations_->next_ = 0;
cleanup_operations_->destroy();
cleanup_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 invoke(int result)
{
return invoke_func_(this, result);
}
// Destroy the operation.
void destroy()
{
return destroy_func_(this);
}
protected:
typedef bool (*invoke_func_type)(op_base*, int);
typedef void (*destroy_func_type)(op_base*);
// Construct an operation for the given descriptor.
op_base(invoke_func_type invoke_func,
destroy_func_type destroy_func, Descriptor descriptor)
: invoke_func_(invoke_func),
destroy_func_(destroy_func),
descriptor_(descriptor),
next_(0)
{
}
// Prevent deletion through this type.
~op_base()
{
}
private:
friend class reactor_op_queue<Descriptor>;
// The function to be called to dispatch the handler.
invoke_func_type invoke_func_;
// The function to be called to delete the handler.
destroy_func_type destroy_func_;
// The descriptor associated with the operation.
Descriptor descriptor_;
// The next operation for the same file descriptor.
op_base* next_;
};
// Adaptor class template for using handlers in operations.
template <typename Handler>
class op
: public op_base
{
public:
// Constructor.
op(Descriptor descriptor, Handler handler)
: op_base(&op<Handler>::invoke_handler,
&op<Handler>::destroy_handler, descriptor),
handler_(handler)
{
}
// Invoke the handler.
static bool invoke_handler(op_base* base, int result)
{
return static_cast<op<Handler>*>(base)->handler_(result);
}
// Delete the handler.
static void destroy_handler(op_base* base)
{
delete static_cast<op<Handler>*>(base);
}
private:
Handler handler_;
};
// 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 to be destroyed.
op_base* cleanup_operations_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_REACTOR_OP_QUEUE_HPP

View File

@ -1,361 +0,0 @@
//
// resolver_service.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_RESOLVER_SERVICE_HPP
#define ASIO_DETAIL_RESOLVER_SERVICE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstring>
#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/error.hpp"
#include "asio/io_service.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/mutex.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_ops.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/thread.hpp"
namespace asio {
namespace detail {
template <typename Protocol>
class resolver_service
: public asio::io_service::service
{
private:
// Helper class to perform exception-safe cleanup of addrinfo objects.
class auto_addrinfo
: private asio::detail::noncopyable
{
public:
explicit auto_addrinfo(asio::detail::addrinfo_type* ai)
: ai_(ai)
{
}
~auto_addrinfo()
{
if (ai_)
socket_ops::freeaddrinfo(ai_);
}
operator asio::detail::addrinfo_type*()
{
return ai_;
}
private:
asio::detail::addrinfo_type* ai_;
};
public:
// The implementation type of the resolver. The shared pointer is used as a
// cancellation token to indicate to the background thread that the operation
// has been cancelled.
typedef boost::shared_ptr<void> implementation_type;
struct noop_deleter { void operator()(void*) {} };
// The 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(asio::io_service& io_service)
: asio::io_service::service(io_service),
mutex_(),
work_io_service_(new asio::io_service),
work_(new 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_->interrupt();
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.
template <typename Error_Handler>
iterator_type resolve(implementation_type&, const query_type& query,
Error_Handler error_handler)
{
asio::detail::addrinfo_type* address_info = 0;
std::string host_name = query.host_name();
std::string service_name = query.service_name();
asio::detail::addrinfo_type hints = query.hints();
int result = socket_ops::getaddrinfo(
host_name.length() ? host_name.c_str() : 0,
service_name.c_str(), &hints, &address_info);
auto_addrinfo auto_address_info(address_info);
error_handler(asio::error(result));
if (result != 0)
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,
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(asio::detail::bind_handler(handler_,
asio::error(asio::error::operation_aborted),
iterator));
return;
}
// Perform the blocking host resolution operation.
asio::detail::addrinfo_type* address_info = 0;
std::string host_name = query_.host_name();
std::string service_name = query_.service_name();
asio::detail::addrinfo_type hints = query_.hints();
int result = socket_ops::getaddrinfo(
host_name.length() ? host_name.c_str() : 0,
service_name.c_str(), &hints, &address_info);
auto_addrinfo auto_address_info(address_info);
// Invoke the handler and pass the result.
asio::error e(result);
iterator_type iterator;
if (result == 0)
iterator = iterator_type::create(address_info, host_name, service_name);
io_service_.post(asio::detail::bind_handler(
handler_, e, iterator));
}
private:
boost::weak_ptr<void> impl_;
query_type query_;
asio::io_service& io_service_;
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, io_service(), handler));
}
}
// Resolve an endpoint to a list of entries.
template <typename Error_Handler>
iterator_type resolve(implementation_type&,
const endpoint_type& endpoint, Error_Handler error_handler)
{
// 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;
int result = socket_ops::getnameinfo(endpoint.data(), endpoint.size(),
host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags);
if (result)
{
flags |= NI_NUMERICSERV;
result = socket_ops::getnameinfo(endpoint.data(), endpoint.size(),
host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags);
}
error_handler(asio::error(result));
if (result != 0)
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, 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(asio::detail::bind_handler(handler_,
asio::error(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;
int result = socket_ops::getnameinfo(endpoint_.data(), endpoint_.size(),
host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags);
if (result)
{
flags |= NI_NUMERICSERV;
result = socket_ops::getnameinfo(endpoint_.data(), endpoint_.size(),
host_name, NI_MAXHOST, service_name, NI_MAXSERV, flags);
}
// Invoke the handler and pass the result.
asio::error e(result);
iterator_type iterator;
if (result == 0)
iterator = iterator_type::create(endpoint_, host_name, service_name);
io_service_.post(asio::detail::bind_handler(
handler_, e, iterator));
}
private:
boost::weak_ptr<void> impl_;
endpoint_type endpoint_;
asio::io_service& io_service_;
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, 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(asio::io_service& io_service)
: io_service_(io_service) {}
void operator()() { io_service_.run(); }
private:
asio::io_service& io_service_;
};
// Start the work thread if it's not already running.
void start_work_thread()
{
asio::detail::mutex::scoped_lock lock(mutex_);
if (work_thread_ == 0)
{
work_thread_.reset(new asio::detail::thread(
work_io_service_runner(*work_io_service_)));
}
}
// Mutex to protect access to internal data.
asio::detail::mutex mutex_;
// Private io_service used for performing asynchronous host resolution.
boost::scoped_ptr<asio::io_service> work_io_service_;
// Work for the private io_service to perform.
boost::scoped_ptr<asio::io_service::work> work_;
// Thread used for running the work io_service's run loop.
boost::scoped_ptr<asio::detail::thread> work_thread_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_RESOLVER_SERVICE_HPP

View File

@ -1,79 +0,0 @@
//
// scoped_lock.hpp
// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_SCOPED_LOCK_HPP
#define ASIO_DETAIL_SCOPED_LOCK_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/noncopyable.hpp"
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;
}
}
private:
// The underlying mutex.
Mutex& mutex_;
// Whether the mutex is currently locked or unlocked.
bool locked_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_SCOPED_LOCK_HPP

View File

@ -1,41 +0,0 @@
//
// select_interrupter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_SELECT_INTERRUPTER_HPP
#define ASIO_DETAIL_SELECT_INTERRUPTER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/detail/pipe_select_interrupter.hpp"
#include "asio/detail/socket_select_interrupter.hpp"
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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_SELECT_INTERRUPTER_HPP

View File

@ -1,435 +0,0 @@
//
// select_reactor.hpp
// ~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_SELECT_REACTOR_HPP
#define ASIO_DETAIL_SELECT_REACTOR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/socket_types.hpp" // Must come before posix_time.
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <vector>
#include "asio/detail/pop_options.hpp"
#include "asio/io_service.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/fd_set_adapter.hpp"
#include "asio/detail/mutex.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/task_io_service.hpp"
#include "asio/detail/thread.hpp"
#include "asio/detail/reactor_op_queue.hpp"
#include "asio/detail/select_interrupter.hpp"
#include "asio/detail/select_reactor_fwd.hpp"
#include "asio/detail/signal_blocker.hpp"
#include "asio/detail/socket_ops.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/timer_queue.hpp"
namespace asio {
namespace detail {
template <bool Own_Thread>
class select_reactor
: public asio::io_service::service
{
public:
// Constructor.
select_reactor(asio::io_service& io_service)
: asio::io_service::service(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)
{
asio::detail::signal_blocker sb;
thread_ = new 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()
{
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)
{
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, Handler handler)
{
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, Handler handler)
{
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, Handler handler)
{
asio::detail::mutex::scoped_lock lock(mutex_);
if (!shutdown_)
if (except_op_queue_.enqueue_operation(descriptor, handler))
interrupter_.interrupt();
}
// 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.
template <typename Handler>
void start_write_and_except_ops(socket_type descriptor, Handler handler)
{
asio::detail::mutex::scoped_lock lock(mutex_);
if (!shutdown_)
{
bool interrupt = write_op_queue_.enqueue_operation(descriptor, handler);
interrupt = except_op_queue_.enqueue_operation(descriptor, 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)
{
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 from within a reactor
// handler.
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)
{
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)
{
asio::detail::mutex::scoped_lock lock(mutex_);
timer_queues_.push_back(&timer_queue);
}
// 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)
{
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)
{
asio::detail::mutex::scoped_lock lock(mutex_);
return timer_queue.cancel_timer(token);
}
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)
{
asio::detail::mutex::scoped_lock lock(mutex_);
// Dispatch any operation cancellations that were made while the select
// loop was not running.
read_op_queue_.dispatch_cancellations();
write_op_queue_.dispatch_cancellations();
except_op_queue_.dispatch_cancellations();
// Check if the thread is supposed to stop.
if (stop_thread_)
{
// Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
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())
{
// Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
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();
int retval = socket_ops::select(static_cast<int>(max_fd + 1),
read_fds, write_fds, except_fds, tv);
lock.lock();
select_in_progress_ = false;
// Block signals while dispatching operations.
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_.dispatch_descriptors(except_fds, 0);
read_op_queue_.dispatch_descriptors(read_fds, 0);
write_op_queue_.dispatch_descriptors(write_fds, 0);
except_op_queue_.dispatch_cancellations();
read_op_queue_.dispatch_cancellations();
write_op_queue_.dispatch_cancellations();
}
for (std::size_t i = 0; i < timer_queues_.size(); ++i)
timer_queues_[i]->dispatch_timers();
// Issue any pending cancellations.
for (size_t i = 0; i < pending_cancellations_.size(); ++i)
cancel_ops_unlocked(pending_cancellations_[i]);
pending_cancellations_.clear();
// Clean up operations. We must not hold the lock since the operations may
// make calls back into this reactor.
lock.unlock();
read_op_queue_.cleanup_operations();
write_op_queue_.cleanup_operations();
except_op_queue_.cleanup_operations();
}
// Run the select loop in the thread.
void run_thread()
{
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();
}
// Mutex to protect access to internal data.
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_;
// 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.
asio::detail::thread* thread_;
// Whether the service has been shut down.
bool shutdown_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_SELECT_REACTOR_HPP

View File

@ -1,31 +0,0 @@
//
// select_reactor_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_SELECT_REACTOR_FWD_HPP
#define ASIO_DETAIL_SELECT_REACTOR_FWD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
template <bool Own_Thread>
class select_reactor;
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_SELECT_REACTOR_FWD_HPP

View File

@ -1,163 +0,0 @@
//
// service_registry.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_SERVICE_REGISTRY_HPP
#define ASIO_DETAIL_SERVICE_REGISTRY_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <memory>
#include <typeinfo>
#include "asio/detail/pop_options.hpp"
#include "asio/detail/mutex.hpp"
#include "asio/detail/noncopyable.hpp"
namespace asio {
namespace detail {
template <typename Owner>
class service_registry
: private noncopyable
{
public:
// Constructor.
service_registry(Owner& 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.
typename Owner::service* service = first_service_;
while (service)
{
service->shutdown_service();
service = service->next_;
}
// Destroy all services.
while (first_service_)
{
typename Owner::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()
{
asio::detail::mutex::scoped_lock lock(mutex_);
// First see if there is an existing service object for the given type.
typename Owner::service* service = first_service_;
while (service)
{
if (*service->type_info_ == typeid(Service))
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_));
new_service->type_info_ = &typeid(Service);
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->type_info_ == typeid(Service))
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)
{
asio::detail::mutex::scoped_lock lock(mutex_);
// Check if there is an existing service object for the given type.
typename Owner::service* service = first_service_;
while (service)
{
if (*service->type_info_ == typeid(Service))
return false;
service = service->next_;
}
// Take ownership of the service object.
new_service->type_info_ = &typeid(Service);
new_service->next_ = first_service_;
first_service_ = new_service;
}
// Check whether a service object of the specified type already exists.
template <typename Service>
bool has_service() const
{
asio::detail::mutex::scoped_lock lock(mutex_);
typename Owner::service* service = first_service_;
while (service)
{
if (*service->type_info_ == typeid(Service))
return true;
service = service->next_;
}
return false;
}
private:
// Mutex to protect access to internal data.
mutable asio::detail::mutex mutex_;
// The owner of this service registry and the services it contains.
Owner& owner_;
// The first service in the list of contained services.
typename Owner::service* first_service_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_SERVICE_REGISTRY_HPP

View File

@ -1,50 +0,0 @@
//
// signal_blocker.hpp
// ~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_SIGNAL_BLOCKER_HPP
#define ASIO_DETAIL_SIGNAL_BLOCKER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if !defined(BOOST_HAS_THREADS)
# include "asio/detail/null_signal_blocker.hpp"
#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
# include "asio/detail/win_signal_blocker.hpp"
#elif defined(BOOST_HAS_PTHREADS)
# include "asio/detail/posix_signal_blocker.hpp"
#else
# error Only Windows and POSIX are supported!
#endif
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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_SIGNAL_BLOCKER_HPP

View File

@ -1,51 +0,0 @@
//
// signal_init.hpp
// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_SIGNAL_INIT_HPP
#define ASIO_DETAIL_SIGNAL_INIT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
#include "asio/detail/push_options.hpp"
#include <csignal>
#include "asio/detail/pop_options.hpp"
namespace asio {
namespace detail {
template <int Signal = SIGPIPE>
class signal_init
{
public:
// Constructor.
signal_init()
{
std::signal(Signal, SIG_IGN);
}
};
} // namespace detail
} // namespace asio
#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_SIGNAL_INIT_HPP

View File

@ -1,91 +0,0 @@
//
// socket_holder.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_SOCKET_HOLDER_HPP
#define ASIO_DETAIL_SOCKET_HOLDER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_ops.hpp"
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)
socket_ops::close(socket_);
}
// Get the underlying socket.
socket_type get() const
{
return socket_;
}
// Reset to an uninitialised socket.
void reset()
{
if (socket_ != invalid_socket)
{
socket_ops::close(socket_);
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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_SOCKET_HOLDER_HPP

File diff suppressed because it is too large Load Diff

View File

@ -1,323 +0,0 @@
//
// socket_option.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_SOCKET_OPTION_HPP
#define ASIO_DETAIL_SOCKET_OPTION_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/detail/socket_types.hpp"
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.
boolean(bool value)
: value_(value ? 1 : 0)
{
}
// Set the value of the boolean.
void set(bool value)
{
value_ = value ? 1 : 0;
}
// Get the current value of the boolean.
bool get() 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_);
}
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.
integer(int value)
: value_(value)
{
}
// Set the value of the int option.
void set(int value)
{
value_ = value;
}
// Get the current value of the int option.
int get() 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_);
}
private:
int value_;
};
// Helper template for implementing unsigned integer options.
template <int Level, int Name>
class unsigned_integer
{
public:
// Default constructor.
unsigned_integer()
: value_(0)
{
}
// Construct with a specific option value.
unsigned_integer(unsigned int value)
: value_(value)
{
}
// Set the value of the int option.
void set(unsigned int value)
{
value_ = value;
}
// Get the current value of the int option.
unsigned int get() 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>
unsigned int* data(const Protocol&)
{
return &value_;
}
// Get the address of the int data.
template <typename Protocol>
const unsigned 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_);
}
private:
unsigned 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 value, unsigned short timeout)
{
value_.l_onoff = value ? 1 : 0;
value_.l_linger = timeout;
}
// 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(unsigned short value)
{
value_.l_linger = value;
}
// Get the value for the linger timeout.
unsigned short timeout() const
{
return 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_);
}
private:
::linger value_;
};
} // namespace socket_option
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_SOCKET_OPTION_HPP

View File

@ -1,177 +0,0 @@
//
// socket_select_interrupter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP
#define ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/throw_exception.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/error.hpp"
#include "asio/detail/socket_holder.hpp"
#include "asio/detail/socket_ops.hpp"
#include "asio/detail/socket_types.hpp"
namespace asio {
namespace detail {
class socket_select_interrupter
{
public:
// Constructor.
socket_select_interrupter()
{
socket_holder acceptor(socket_ops::socket(AF_INET, SOCK_STREAM,
IPPROTO_TCP));
if (acceptor.get() == invalid_socket)
{
asio::error e(socket_ops::get_error());
boost::throw_exception(e);
}
int opt = 1;
socket_ops::setsockopt(acceptor.get(),
SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
sockaddr_in4_type addr;
socket_addr_len_type addr_len = 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) == socket_error_retval)
{
asio::error e(socket_ops::get_error());
boost::throw_exception(e);
}
if (getsockname(acceptor.get(), (socket_addr_type*)&addr, &addr_len)
== socket_error_retval)
{
asio::error e(socket_ops::get_error());
boost::throw_exception(e);
}
if (socket_ops::listen(acceptor.get(), SOMAXCONN) == socket_error_retval)
{
asio::error e(socket_ops::get_error());
boost::throw_exception(e);
}
socket_holder client(socket_ops::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
if (client.get() == invalid_socket)
{
asio::error e(socket_ops::get_error());
boost::throw_exception(e);
}
if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr,
addr_len) == socket_error_retval)
{
asio::error e(socket_ops::get_error());
boost::throw_exception(e);
}
socket_holder server(socket_ops::accept(acceptor.get(), 0, 0));
if (server.get() == invalid_socket)
{
asio::error e(socket_ops::get_error());
boost::throw_exception(e);
}
ioctl_arg_type non_blocking = 1;
if (socket_ops::ioctl(client.get(), FIONBIO, &non_blocking))
{
asio::error e(socket_ops::get_error());
boost::throw_exception(e);
}
opt = 1;
socket_ops::setsockopt(client.get(),
IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
non_blocking = 1;
if (socket_ops::ioctl(server.get(), FIONBIO, &non_blocking))
{
asio::error e(socket_ops::get_error());
boost::throw_exception(e);
}
opt = 1;
socket_ops::setsockopt(server.get(),
IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
read_descriptor_ = server.release();
write_descriptor_ = client.release();
}
// Destructor.
~socket_select_interrupter()
{
if (read_descriptor_ != invalid_socket)
socket_ops::close(read_descriptor_);
if (write_descriptor_ != invalid_socket)
socket_ops::close(write_descriptor_);
}
// Interrupt the select call.
void interrupt()
{
char byte = 0;
socket_ops::buf b;
socket_ops::init_buf(b, &byte, 1);
socket_ops::send(write_descriptor_, &b, 1, 0);
}
// 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));
int bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0);
bool was_interrupted = (bytes_read > 0);
while (bytes_read == sizeof(data))
bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0);
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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP

View File

@ -1,184 +0,0 @@
//
// socket_types.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_SOCKET_TYPES_HPP
#define ASIO_DETAIL_SOCKET_TYPES_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/detail/push_options.hpp"
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
# if defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)
# error WinSock.h has already been included
# endif // defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)
# if !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
# if defined(_MSC_VER) || defined(__BORLANDC__)
# pragma message("Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately")
# pragma message("Assuming _WIN32_WINNT=0x0500 (i.e. Windows 2000 target)")
# else // defined(_MSC_VER) || defined(__BORLANDC__)
# warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately
# warning Assuming _WIN32_WINNT=0x0500 (i.e. Windows 2000 target)
# endif // defined(_MSC_VER) || defined(__BORLANDC__)
# define _WIN32_WINNT 0x0500
# endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
# if defined(_MSC_VER)
# if defined(_WIN32) && !defined(WIN32)
# if !defined(_WINSOCK2API_)
# define WIN32 // Needed for correct types in winsock2.h
# else // !defined(_WINSOCK2API_)
# error Please define the macro WIN32 in your compiler options
# endif // !defined(_WINSOCK2API_)
# endif // defined(_WIN32) && !defined(WIN32)
# endif // defined(_MSC_VER)
# if defined(__BORLANDC__)
# include <stdlib.h> // Needed for __errno
# if defined(__WIN32__) && !defined(WIN32)
# if !defined(_WINSOCK2API_)
# define WIN32 // Needed for correct types in winsock2.h
# else // !defined(_WINSOCK2API_)
# error Please define the macro WIN32 in your compiler options
# endif // !defined(_WINSOCK2API_)
# endif // defined(__WIN32__) && !defined(WIN32)
# if !defined(_WSPIAPI_H_)
# define _WSPIAPI_H_
# define ASIO_WSPIAPI_H_DEFINED
# endif // !defined(_WSPIAPI_H_)
# endif // defined(__BORLANDC__)
# if !defined(ASIO_NO_WIN32_LEAN_AND_MEAN)
# if !defined(WIN32_LEAN_AND_MEAN)
# define WIN32_LEAN_AND_MEAN
# endif // !defined(WIN32_LEAN_AND_MEAN)
# endif // !defined(ASIO_NO_WIN32_LEAN_AND_MEAN)
# if defined(__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(ASIO_WSPIAPI_H_DEFINED)
# undef _WSPIAPI_H_
# undef ASIO_WSPIAPI_H_DEFINED
# endif // defined(ASIO_WSPIAPI_H_DEFINED)
# if !defined(ASIO_NO_DEFAULT_LINKED_LIBS)
# if defined(_MSC_VER) || defined(__BORLANDC__)
# pragma comment(lib, "ws2_32.lib")
# pragma comment(lib, "mswsock.lib")
# endif // defined(_MSC_VER) || defined(__BORLANDC__)
# endif // !defined(ASIO_NO_DEFAULT_LINKED_LIBS)
# include "asio/detail/old_win_sdk_compat.hpp"
#else
# include <sys/ioctl.h>
# include <sys/poll.h>
# include <sys/types.h>
# include <sys/select.h>
# include <sys/socket.h>
# include <sys/uio.h>
# include <netinet/in.h>
# include <netinet/tcp.h>
# include <arpa/inet.h>
# include <netdb.h>
# include <net/if.h>
# if defined(__sun)
# include <sys/filio.h>
# endif
#endif
#include "asio/detail/pop_options.hpp"
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 int socket_addr_len_type;
typedef in_addr in4_addr_type;
typedef ip_mreq in4_mreq_type;
typedef sockaddr_in sockaddr_in4_type;
# if defined(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;
#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 socklen_t socket_addr_len_type;
typedef in_addr in4_addr_type;
typedef ip_mreq in4_mreq_type;
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 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;
#endif
const int custom_socket_option_level = 0xA5100000;
const int enable_connection_aborted_option = 1;
#if defined(_WIN64)
std::size_t hash_value(SOCKET s)
{
return static_cast<std::size_t>(s);
}
#endif // defined(_WIN64)
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_SOCKET_TYPES_HPP

View File

@ -1,528 +0,0 @@
//
// strand_service.hpp
// ~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_STRAND_SERVICE_HPP
#define ASIO_DETAIL_STRAND_SERVICE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/aligned_storage.hpp>
#include <boost/assert.hpp>
#include <boost/intrusive_ptr.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/io_service.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/call_stack.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/mutex.hpp"
#include "asio/detail/noncopyable.hpp"
namespace asio {
namespace detail {
// Default service implementation for a strand.
class strand_service
: public asio::io_service::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()
{
asio::detail::mutex::scoped_lock lock(mutex_);
++ref_count_;
}
void release()
{
asio::detail::mutex::scoped_lock lock(mutex_);
--ref_count_;
if (ref_count_ == 0)
{
lock.unlock();
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.
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.
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.
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<64> handler_storage_type;
#if defined(__BORLANDC__)
boost::aligned_storage<64> 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.
size_t 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<64>::size);
#else
BOOST_ASSERT(size <= strand_impl::handler_storage_type::size);
#endif
return impl_->handler_storage_.address();
}
template <typename Function>
friend void asio_handler_invoke(Function function,
invoke_current_handler*)
{
function();
}
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_)
{
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_.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.
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);
}
private:
Handler handler_;
};
// Construct a new strand service for the specified io_service.
explicit strand_service(asio::io_service& io_service)
: asio::io_service::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.
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()))
{
asio_handler_invoke_helpers::invoke(handler, &handler);
}
else
{
asio::detail::mutex::scoped_lock lock(impl->mutex_);
// 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);
if (impl->current_handler_ == 0)
{
// This handler now has the lock, so can be dispatched immediately.
impl->current_handler_ = ptr.get();
lock.unlock();
io_service().dispatch(invoke_current_handler(*this, impl));
ptr.release();
}
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)
{
asio::detail::mutex::scoped_lock lock(impl->mutex_);
// 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);
if (impl->current_handler_ == 0)
{
// This handler now has the lock, so can be dispatched immediately.
impl->current_handler_ = ptr.get();
lock.unlock();
io_service().post(invoke_current_handler(*this, impl));
ptr.release();
}
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.
asio::detail::mutex mutex_;
// The head of a linked list of all implementations.
strand_impl* impl_list_;
};
} // namespace detail
} // namespace asio
#if defined(__BORLANDC__)
namespace boost {
inline void intrusive_ptr_add_ref(
asio::detail::strand_service::strand_impl* p)
{
p->add_ref();
}
inline void intrusive_ptr_release(
asio::detail::strand_service::strand_impl* p)
{
p->release();
}
} // namespace boost
#endif // defined(__BORLANDC__)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_STRAND_SERVICE_HPP

View File

@ -1,526 +0,0 @@
//
// task_io_service.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_TASK_IO_SERVICE_HPP
#define ASIO_DETAIL_TASK_IO_SERVICE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/io_service.hpp"
#include "asio/detail/call_stack.hpp"
#include "asio/detail/event.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/mutex.hpp"
#include "asio/detail/task_io_service_fwd.hpp"
namespace asio {
namespace detail {
template <typename Task>
class task_io_service
: public asio::io_service::service
{
public:
// Constructor.
task_io_service(asio::io_service& io_service)
: asio::io_service::service(io_service),
mutex_(),
task_(use_service<Task>(io_service)),
outstanding_work_(0),
handler_queue_(&task_handler_),
handler_queue_end_(&task_handler_),
interrupted_(false),
shutdown_(false),
first_idle_thread_(0)
{
}
// Destroy all user-defined handler objects owned by the service.
void shutdown_service()
{
asio::detail::mutex::scoped_lock lock(mutex_);
shutdown_ = true;
lock.unlock();
// Destroy handler objects.
while (handler_queue_)
{
handler_base* h = handler_queue_;
handler_queue_ = h->next_;
if (h != &task_handler_)
h->destroy();
}
// Reset handler queue to initial state.
handler_queue_ = &task_handler_;
handler_queue_end_ = &task_handler_;
}
// Run the event loop until interrupted or no more work.
size_t run()
{
typename call_stack<task_io_service>::context ctx(this);
idle_thread_info this_idle_thread;
this_idle_thread.prev = &this_idle_thread;
this_idle_thread.next = &this_idle_thread;
asio::detail::mutex::scoped_lock lock(mutex_);
size_t n = 0;
while (do_one(lock, &this_idle_thread))
if (n != (std::numeric_limits<size_t>::max)())
++n;
return n;
}
// Run until interrupted or one operation is performed.
size_t run_one()
{
typename call_stack<task_io_service>::context ctx(this);
idle_thread_info this_idle_thread;
this_idle_thread.prev = &this_idle_thread;
this_idle_thread.next = &this_idle_thread;
asio::detail::mutex::scoped_lock lock(mutex_);
return do_one(lock, &this_idle_thread);
}
// Poll for operations without blocking.
size_t poll()
{
typename call_stack<task_io_service>::context ctx(this);
asio::detail::mutex::scoped_lock lock(mutex_);
size_t n = 0;
while (do_one(lock, 0))
if (n != (std::numeric_limits<size_t>::max)())
++n;
return n;
}
// Poll for one operation without blocking.
size_t poll_one()
{
typename call_stack<task_io_service>::context ctx(this);
asio::detail::mutex::scoped_lock lock(mutex_);
return do_one(lock, 0);
}
// Interrupt the event processing loop.
void interrupt()
{
asio::detail::mutex::scoped_lock lock(mutex_);
interrupt_all_threads();
}
// Reset in preparation for a subsequent run invocation.
void reset()
{
asio::detail::mutex::scoped_lock lock(mutex_);
interrupted_ = false;
}
// Notify that some work has started.
void work_started()
{
asio::detail::mutex::scoped_lock lock(mutex_);
++outstanding_work_;
}
// Notify that some work has finished.
void work_finished()
{
asio::detail::mutex::scoped_lock lock(mutex_);
if (--outstanding_work_ == 0)
interrupt_all_threads();
}
// Request invocation of the given handler.
template <typename Handler>
void dispatch(Handler handler)
{
if (call_stack<task_io_service>::contains(this))
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.
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);
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.
if (handler_queue_end_)
{
handler_queue_end_->next_ = ptr.get();
handler_queue_end_ = ptr.get();
}
else
{
handler_queue_ = handler_queue_end_ = 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())
if (task_handler_.next_ == 0 && handler_queue_end_ != &task_handler_)
task_.interrupt();
}
private:
struct idle_thread_info;
size_t do_one(asio::detail::mutex::scoped_lock& lock,
idle_thread_info* this_idle_thread)
{
if (outstanding_work_ == 0 && !interrupted_)
{
interrupt_all_threads();
return 0;
}
bool polling = !this_idle_thread;
bool task_has_run = false;
while (!interrupted_)
{
if (handler_queue_)
{
// Prepare to execute first handler from queue.
handler_base* h = handler_queue_;
handler_queue_ = h->next_;
if (handler_queue_ == 0)
handler_queue_end_ = 0;
bool more_handlers = (handler_queue_ != 0);
lock.unlock();
if (h == &task_handler_)
{
// If the task has already run and we're polling then we're done.
if (task_has_run && polling)
return 0;
task_has_run = true;
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
{
handler_cleanup c(lock, *this);
// Invoke the handler. May throw an exception.
h->call(); // call() deletes the handler object
return 1;
}
}
else if (this_idle_thread)
{
// Nothing to run right now, so just wait for work to do.
if (first_idle_thread_)
{
this_idle_thread->next = first_idle_thread_;
this_idle_thread->prev = first_idle_thread_->prev;
first_idle_thread_->prev->next = this_idle_thread;
first_idle_thread_->prev = this_idle_thread;
}
first_idle_thread_ = this_idle_thread;
this_idle_thread->wakeup_event.clear();
lock.unlock();
this_idle_thread->wakeup_event.wait();
lock.lock();
if (this_idle_thread->next == this_idle_thread)
{
first_idle_thread_ = 0;
}
else
{
if (first_idle_thread_ == this_idle_thread)
first_idle_thread_ = this_idle_thread->next;
this_idle_thread->next->prev = this_idle_thread->prev;
this_idle_thread->prev->next = this_idle_thread->next;
this_idle_thread->next = this_idle_thread;
this_idle_thread->prev = this_idle_thread;
}
}
else
{
return 0;
}
}
return 0;
}
// Interrupt the task and all idle threads.
void interrupt_all_threads()
{
interrupted_ = true;
interrupt_all_idle_threads();
if (task_handler_.next_ == 0 && handler_queue_end_ != &task_handler_)
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()
{
if (first_idle_thread_)
{
first_idle_thread_->wakeup_event.signal();
first_idle_thread_ = first_idle_thread_->next;
return true;
}
return false;
}
// Interrupt all idle threads.
void interrupt_all_idle_threads()
{
if (first_idle_thread_)
{
first_idle_thread_->wakeup_event.signal();
idle_thread_info* current_idle_thread = first_idle_thread_->next;
while (current_idle_thread != first_idle_thread_)
{
current_idle_thread->wakeup_event.signal();
current_idle_thread = current_idle_thread->next;
}
}
}
class task_cleanup;
// The base class for all handler wrappers. A function pointer is used
// instead of virtual functions to avoid the associated overhead.
class handler_base
{
public:
typedef void (*call_func_type)(handler_base*);
typedef void (*destroy_func_type)(handler_base*);
handler_base(call_func_type call_func, destroy_func_type destroy_func)
: next_(0),
call_func_(call_func),
destroy_func_(destroy_func)
{
}
void call()
{
call_func_(this);
}
void destroy()
{
destroy_func_(this);
}
protected:
// Prevent deletion through this type.
~handler_base()
{
}
private:
friend class task_io_service<Task>;
friend class task_cleanup;
handler_base* next_;
call_func_type call_func_;
destroy_func_type destroy_func_;
};
// Template wrapper for handlers.
template <typename Handler>
class handler_wrapper
: public handler_base
{
public:
handler_wrapper(Handler handler)
: handler_base(&handler_wrapper<Handler>::do_call,
&handler_wrapper<Handler>::do_destroy),
handler_(handler)
{
}
static void do_call(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);
// 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.
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);
}
private:
Handler handler_;
};
// Helper class to perform task-related operations on block exit.
class task_cleanup;
friend class task_cleanup;
class task_cleanup
{
public:
task_cleanup(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_handler_.next_ = 0;
if (task_io_service_.handler_queue_end_)
{
task_io_service_.handler_queue_end_->next_
= &task_io_service_.task_handler_;
task_io_service_.handler_queue_end_
= &task_io_service_.task_handler_;
}
else
{
task_io_service_.handler_queue_
= task_io_service_.handler_queue_end_
= &task_io_service_.task_handler_;
}
}
private:
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(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_.interrupt_all_threads();
}
private:
asio::detail::mutex::scoped_lock& lock_;
task_io_service& task_io_service_;
};
// Mutex to protect access to internal data.
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_base
{
public:
task_handler()
: handler_base(0, 0)
{
}
} task_handler_;
// The count of unfinished work.
int outstanding_work_;
// The start of a linked list of handlers that are ready to be delivered.
handler_base* handler_queue_;
// The end of a linked list of handlers that are ready to be delivered.
handler_base* handler_queue_end_;
// Flag to indicate that the dispatcher has been interrupted.
bool interrupted_;
// 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* prev;
idle_thread_info* next;
};
// The number of threads that are currently idle.
idle_thread_info* first_idle_thread_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_TASK_IO_SERVICE_HPP

View File

@ -1,31 +0,0 @@
//
// task_io_service_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP
#define ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
namespace asio {
namespace detail {
template <typename Task>
class task_io_service;
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_TASK_IO_SERVICE_FWD_HPP

View File

@ -1,50 +0,0 @@
//
// thread.hpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_THREAD_HPP
#define ASIO_DETAIL_THREAD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if !defined(BOOST_HAS_THREADS)
# include "asio/detail/null_thread.hpp"
#elif defined(BOOST_WINDOWS)
# include "asio/detail/win_thread.hpp"
#elif defined(BOOST_HAS_PTHREADS)
# include "asio/detail/posix_thread.hpp"
#else
# error Only Windows and POSIX are supported!
#endif
namespace asio {
namespace detail {
#if !defined(BOOST_HAS_THREADS)
typedef null_thread thread;
#elif defined(BOOST_WINDOWS)
typedef win_thread thread;
#elif defined(BOOST_HAS_PTHREADS)
typedef posix_thread thread;
#endif
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_THREAD_HPP

View File

@ -1,345 +0,0 @@
//
// timer_queue.hpp
// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_TIMER_QUEUE_HPP
#define ASIO_DETAIL_TIMER_QUEUE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <functional>
#include <limits>
#include <memory>
#include <vector>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/error.hpp"
#include "asio/detail/hash_map.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/timer_queue_base.hpp"
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_()
{
}
// 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
{
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->invoke(0);
}
}
// Cancel the timer with the given token. The handler will be invoked
// immediately with the result operation_aborted.
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->invoke(asio::error::operation_aborted);
t = next;
++num_cancelled;
}
}
return num_cancelled;
}
// 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);
t->destroy();
}
heap_.clear();
timers_.clear();
}
private:
// Base class for timer operations. Function pointers are used instead of
// virtual functions to avoid the associated overhead.
class timer_base
{
public:
// Perform the timer operation and then destroy.
void invoke(int result)
{
invoke_func_(this, result);
}
// Destroy the timer operation.
void destroy()
{
destroy_func_(this);
}
protected:
typedef void (*invoke_func_type)(timer_base*, int);
typedef void (*destroy_func_type)(timer_base*);
// Constructor.
timer_base(invoke_func_type invoke_func, destroy_func_type destroy_func,
const time_type& time, void* token)
: invoke_func_(invoke_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 dispatch the handler.
invoke_func_type invoke_func_;
// The function to be called to destroy the handler.
destroy_func_type destroy_func_;
// The time when the operation 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>::invoke_handler,
&timer<Handler>::destroy_handler, time, token),
handler_(handler)
{
}
// Invoke the handler and then destroy it.
static void invoke_handler(timer_base* base, int result)
{
std::auto_ptr<timer<Handler> > t(static_cast<timer<Handler>*>(base));
t->handler_(result);
}
// Destroy the handler.
static void destroy_handler(timer_base* base)
{
delete static_cast<timer<Handler>*>(base);
}
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(t->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);
}
}
// 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_;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_TIMER_QUEUE_HPP

View File

@ -1,56 +0,0 @@
//
// timer_queue_base.hpp
// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_TIMER_QUEUE_BASE_HPP
#define ASIO_DETAIL_TIMER_QUEUE_BASE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/socket_types.hpp" // Must come before posix_time.
#include "asio/detail/push_options.hpp"
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/detail/noncopyable.hpp"
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;
// Destroy all timers.
virtual void destroy_timers() = 0;
};
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_TIMER_QUEUE_BASE_HPP

View File

@ -1,65 +0,0 @@
//
// tss_ptr.hpp
// ~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_TSS_PTR_HPP
#define ASIO_DETAIL_TSS_PTR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if !defined(BOOST_HAS_THREADS)
# include "asio/detail/null_tss_ptr.hpp"
#elif defined(BOOST_WINDOWS)
# include "asio/detail/win_tss_ptr.hpp"
#elif defined(BOOST_HAS_PTHREADS)
# include "asio/detail/posix_tss_ptr.hpp"
#else
# error Only Windows and POSIX are supported!
#endif
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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_TSS_PTR_HPP

View File

@ -1,88 +0,0 @@
//
// win_event.hpp
// ~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_WIN_EVENT_HPP
#define ASIO_DETAIL_WIN_EVENT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if defined(BOOST_WINDOWS)
#include "asio/system_exception.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/throw_exception.hpp>
#include "asio/detail/pop_options.hpp"
namespace asio {
namespace detail {
class win_event
: private noncopyable
{
public:
// Constructor.
win_event()
: event_(::CreateEvent(0, true, false, 0))
{
if (!event_)
{
DWORD last_error = ::GetLastError();
system_exception e("event", last_error);
boost::throw_exception(e);
}
}
// Destructor.
~win_event()
{
::CloseHandle(event_);
}
// Signal the event.
void signal()
{
::SetEvent(event_);
}
// Reset the event.
void clear()
{
::ResetEvent(event_);
}
// Wait for the event to become signalled.
void wait()
{
::WaitForSingleObject(event_, INFINITE);
}
private:
HANDLE event_;
};
} // namespace detail
} // namespace asio
#endif // defined(BOOST_WINDOWS)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_WIN_EVENT_HPP

View File

@ -1,83 +0,0 @@
//
// win_fd_set_adapter.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP
#define ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/socket_types.hpp"
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
namespace asio {
namespace detail {
// Adapts the FD_SET type to meet the Descriptor_Set concept's requirements.
class win_fd_set_adapter
{
public:
win_fd_set_adapter()
: max_descriptor_(invalid_socket)
{
fd_set_.fd_count = 0;
}
void set(socket_type descriptor)
{
for (u_int i = 0; i < fd_set_.fd_count; ++i)
if (fd_set_.fd_array[i] == descriptor)
return;
if (fd_set_.fd_count < win_fd_set_size)
fd_set_.fd_array[fd_set_.fd_count++] = descriptor;
}
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.
enum { win_fd_set_size = 1024 };
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
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP

View File

@ -1,389 +0,0 @@
//
// win_iocp_io_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_WIN_IOCP_IO_SERVICE_HPP
#define ASIO_DETAIL_WIN_IOCP_IO_SERVICE_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/win_iocp_io_service_fwd.hpp"
#if defined(ASIO_HAS_IOCP)
#include "asio/detail/push_options.hpp"
#include <limits>
#include <boost/throw_exception.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/io_service.hpp"
#include "asio/system_exception.hpp"
#include "asio/detail/call_stack.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/win_iocp_operation.hpp"
namespace asio {
namespace detail {
class win_iocp_io_service
: public asio::io_service::service
{
public:
// Base class for all operations.
typedef win_iocp_operation operation;
// Constructor.
win_iocp_io_service(asio::io_service& io_service)
: asio::io_service::service(io_service),
iocp_(::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0)),
outstanding_work_(0),
interrupted_(0),
shutdown_(0)
{
if (!iocp_.handle)
{
DWORD last_error = ::GetLastError();
system_exception e("iocp", last_error);
boost::throw_exception(e);
}
}
// Destroy all user-defined handler objects owned by the service.
void shutdown_service()
{
::InterlockedExchange(&shutdown_, 1);
for (;;)
{
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, 0);
DWORD last_error = ::GetLastError();
if (last_error == WAIT_TIMEOUT)
break;
if (overlapped)
static_cast<operation*>(overlapped)->destroy();
}
}
// Register a socket with the IO completion port.
void register_socket(socket_type sock)
{
HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock);
::CreateIoCompletionPort(sock_as_handle, iocp_.handle, 0, 0);
}
// Run the event loop until interrupted or no more work.
size_t run()
{
if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
return 0;
call_stack<win_iocp_io_service>::context ctx(this);
size_t n = 0;
while (do_one(true))
if (n != (std::numeric_limits<size_t>::max)())
++n;
return n;
}
// Run until interrupted or one operation is performed.
size_t run_one()
{
if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
return 0;
call_stack<win_iocp_io_service>::context ctx(this);
return do_one(true);
}
// Poll for operations without blocking.
size_t poll()
{
if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
return 0;
call_stack<win_iocp_io_service>::context ctx(this);
size_t n = 0;
while (do_one(false))
if (n != (std::numeric_limits<size_t>::max)())
++n;
return n;
}
// Poll for one operation without blocking.
size_t poll_one()
{
if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
return 0;
call_stack<win_iocp_io_service>::context ctx(this);
return do_one(false);
}
// Interrupt the event processing loop.
void interrupt()
{
if (::InterlockedExchange(&interrupted_, 1) == 0)
{
if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
{
DWORD last_error = ::GetLastError();
system_exception e("pqcs", last_error);
boost::throw_exception(e);
}
}
}
// Reset in preparation for a subsequent run invocation.
void reset()
{
::InterlockedExchange(&interrupted_, 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)
interrupt();
}
// Request invocation of the given handler.
template <typename Handler>
void dispatch(Handler handler)
{
if (call_stack<win_iocp_io_service>::contains(this))
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();
system_exception e("pqcs", last_error);
boost::throw_exception(e);
}
// Operation has been successfully posted.
ptr.release();
}
// Request invocation of the given OVERLAPPED-derived operation.
void post_completion(win_iocp_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();
system_exception e("pqcs", last_error);
boost::throw_exception(e);
}
}
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)
{
for (;;)
{
// 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 ? INFINITE : 0);
DWORD last_error = ::GetLastError();
if (!ok && overlapped == 0)
return 0;
if (overlapped)
{
// We may have been passed a last_error value in the completion_key.
if (last_error == 0)
{
last_error = completion_key;
}
// 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);
return 1;
}
else
{
// The interrupted_ flag is always checked to ensure that any leftover
// interrupts from a previous run invocation are ignored.
if (::InterlockedExchangeAdd(&interrupted_, 0) != 0)
{
// Wake up next thread that is blocked on GetQueuedCompletionStatus.
if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
{
DWORD last_error = ::GetLastError();
system_exception e("pqcs", last_error);
boost::throw_exception(e);
}
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(&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.
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);
}
win_iocp_io_service& io_service_;
Handler handler_;
};
// The IO completion port used for queueing operations.
struct iocp_holder
{
HANDLE handle;
iocp_holder(HANDLE h) : handle(h) {}
~iocp_holder() { ::CloseHandle(handle); }
} iocp_;
// The count of unfinished work.
long outstanding_work_;
// Flag to indicate whether the event loop has been interrupted.
long interrupted_;
// Flag to indicate whether the service has been shut down.
long shutdown_;
};
} // namespace detail
} // namespace asio
#endif // defined(ASIO_HAS_IOCP)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_WIN_IOCP_IO_SERVICE_HPP

View File

@ -1,46 +0,0 @@
//
// win_iocp_io_service_fwd.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_WIN_IOCP_IO_SERVICE_FWD_HPP
#define 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 "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
// This service is only supported on Win32 (NT4 and later).
#if !defined(ASIO_DISABLE_IOCP)
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
// Define this to indicate that IOCP is supported on the target platform.
#define ASIO_HAS_IOCP 1
namespace asio {
namespace detail {
class win_iocp_io_service;
} // namespace detail
} // namespace asio
#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
#endif // !defined(ASIO_DISABLE_IOCP)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_WIN_IOCP_IO_SERVICE_FWD_HPP

View File

@ -1,81 +0,0 @@
//
// win_iocp_operation.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_WIN_IOCP_OPERATION_HPP
#define ASIO_DETAIL_WIN_IOCP_OPERATION_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/win_iocp_io_service_fwd.hpp"
#if defined(ASIO_HAS_IOCP)
#include "asio/detail/socket_types.hpp"
namespace asio {
namespace detail {
// Base class for all IOCP 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 win_iocp_operation pointer from the LPOVERLAPPED out parameter of
// GetQueuedCompletionStatus.
struct win_iocp_operation
: public OVERLAPPED
{
typedef void (*invoke_func_type)(win_iocp_operation*, DWORD, size_t);
typedef void (*destroy_func_type)(win_iocp_operation*);
win_iocp_operation(invoke_func_type invoke_func,
destroy_func_type destroy_func)
: invoke_func_(invoke_func),
destroy_func_(destroy_func)
{
Internal = 0;
InternalHigh = 0;
Offset = 0;
OffsetHigh = 0;
hEvent = 0;
}
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.
~win_iocp_operation()
{
}
private:
invoke_func_type invoke_func_;
destroy_func_type destroy_func_;
};
} // namespace detail
} // namespace asio
#endif // defined(ASIO_HAS_IOCP)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_WIN_IOCP_OPERATION_HPP

File diff suppressed because it is too large Load Diff

View File

@ -1,59 +0,0 @@
//
// win_local_free_on_block_exit.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_WIN_LOCAL_FREE_ON_BLOCK_EXIT_HPP
#define ASIO_DETAIL_WIN_LOCAL_FREE_ON_BLOCK_EXIT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_types.hpp"
namespace asio {
namespace detail {
class win_local_free_on_block_exit
: private noncopyable
{
public:
// Constructor blocks all signals for the calling thread.
explicit win_local_free_on_block_exit(void* p)
: p_(p)
{
}
// Destructor restores the previous signal mask.
~win_local_free_on_block_exit()
{
::LocalFree(p_);
}
private:
void* p_;
};
} // namespace detail
} // namespace asio
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_WIN_LOCAL_FREE_ON_BLOCK_EXIT_HPP

View File

@ -1,142 +0,0 @@
//
// win_mutex.hpp
// ~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_WIN_MUTEX_HPP
#define ASIO_DETAIL_WIN_MUTEX_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if defined(BOOST_WINDOWS)
#include "asio/system_exception.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/scoped_lock.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/throw_exception.hpp>
#include "asio/detail/pop_options.hpp"
namespace asio {
namespace detail {
class win_mutex
: private noncopyable
{
public:
typedef asio::detail::scoped_lock<win_mutex> scoped_lock;
// Constructor.
win_mutex()
{
int error = do_init();
if (error != 0)
{
system_exception e("mutex", error);
boost::throw_exception(e);
}
}
// Destructor.
~win_mutex()
{
::DeleteCriticalSection(&crit_section_);
}
// Lock the mutex.
void lock()
{
int error = do_lock();
if (error != 0)
{
system_exception e("mutex", error);
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
#endif // defined(BOOST_WINDOWS)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_WIN_MUTEX_HPP

View File

@ -1,67 +0,0 @@
//
// win_signal_blocker.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_WIN_SIGNAL_BLOCKER_HPP
#define ASIO_DETAIL_WIN_SIGNAL_BLOCKER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
#include "asio/detail/noncopyable.hpp"
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
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_WIN_SIGNAL_BLOCKER_HPP

View File

@ -1,121 +0,0 @@
//
// win_thread.hpp
// ~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_WIN_THREAD_HPP
#define ASIO_DETAIL_WIN_THREAD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if defined(BOOST_WINDOWS)
#include "asio/system_exception.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/throw_exception.hpp>
#include <memory>
#include <process.h>
#include "asio/detail/pop_options.hpp"
namespace asio {
namespace detail {
unsigned int __stdcall win_thread_function(void* arg);
class win_thread
: private noncopyable
{
public:
// Constructor.
template <typename Function>
win_thread(Function f)
{
std::auto_ptr<func_base> arg(new func<Function>(f));
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();
system_exception e("thread", last_error);
boost::throw_exception(e);
}
arg.release();
}
// Destructor.
~win_thread()
{
::CloseHandle(thread_);
}
// Wait for the thread to exit.
void join()
{
::WaitForSingleObject(thread_, INFINITE);
}
private:
friend unsigned int __stdcall win_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_;
};
::HANDLE thread_;
};
inline unsigned int __stdcall win_thread_function(void* arg)
{
std::auto_ptr<win_thread::func_base> func(
static_cast<win_thread::func_base*>(arg));
func->run();
return 0;
}
} // namespace detail
} // namespace asio
#endif // defined(BOOST_WINDOWS)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_WIN_THREAD_HPP

View File

@ -1,85 +0,0 @@
//
// win_tss_ptr.hpp
// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_WIN_TSS_PTR_HPP
#define ASIO_DETAIL_WIN_TSS_PTR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if defined(BOOST_WINDOWS)
#include "asio/system_exception.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/throw_exception.hpp>
#include "asio/detail/pop_options.hpp"
namespace asio {
namespace detail {
template <typename T>
class win_tss_ptr
: private noncopyable
{
public:
// Constructor.
win_tss_ptr()
{
tss_key_ = ::TlsAlloc();
if (tss_key_ == TLS_OUT_OF_INDEXES)
{
DWORD last_error = ::GetLastError();
system_exception e("tss", last_error);
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
#endif // defined(BOOST_WINDOWS)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_WIN_TSS_PTR_HPP

View File

@ -1,116 +0,0 @@
//
// winsock_init.hpp
// ~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_WINSOCK_INIT_HPP
#define ASIO_DETAIL_WINSOCK_INIT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
#include "asio/detail/push_options.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/throw_exception.hpp>
#include "asio/detail/pop_options.hpp"
#include "asio/system_exception.hpp"
#include "asio/detail/noncopyable.hpp"
#include "asio/detail/socket_types.hpp"
namespace asio {
namespace detail {
template <int Major = 2, int Minor = 0>
class winsock_init
: private noncopyable
{
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)
{
system_exception e("winsock", ref_->result());
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
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_WINSOCK_INIT_HPP

View File

@ -1,187 +0,0 @@
//
// wrapped_handler.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_DETAIL_WRAPPED_HANDLER_HPP
#define ASIO_DETAIL_WRAPPED_HANDLER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp"
namespace asio {
namespace detail {
template <typename Dispatcher, typename Handler>
class wrapped_handler
{
public:
typedef void result_type;
wrapped_handler(Dispatcher& 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 Dispatcher, typename Handler>
inline void* asio_handler_allocate(std::size_t size,
wrapped_handler<Dispatcher, Handler>* this_handler)
{
return 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)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, &this_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 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 Function, typename Dispatcher, typename Handler>
inline void asio_handler_invoke(const Function& function,
rewrapped_handler<Dispatcher, Handler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, &this_handler->context_);
}
} // namespace detail
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_DETAIL_WRAPPED_HANDLER_HPP

View File

@ -1,387 +0,0 @@
//
// error.hpp
// ~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_ERROR_HPP
#define ASIO_ERROR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/config.hpp>
#include <boost/scoped_ptr.hpp>
#include <cerrno>
#include <cstring>
#include <exception>
#include <string>
#include <boost/detail/workaround.hpp>
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
# include <iostream>
#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
#include "asio/detail/pop_options.hpp"
#include "asio/detail/socket_types.hpp"
#include "asio/detail/win_local_free_on_block_exit.hpp"
namespace asio {
#if defined(GENERATING_DOCUMENTATION)
/// INTERNAL ONLY.
# define ASIO_SOCKET_ERROR(e) implementation_defined
/// INTERNAL ONLY.
# define ASIO_NETDB_ERROR(e) implementation_defined
/// INTERNAL ONLY.
# define ASIO_GETADDRINFO_ERROR(e) implementation_defined
/// INTERNAL ONLY.
# define ASIO_OS_ERROR(e_win, e_posix) implementation_defined
#elif defined(BOOST_WINDOWS) || defined(__CYGWIN__)
# define ASIO_SOCKET_ERROR(e) WSA ## e
# define ASIO_NETDB_ERROR(e) WSA ## e
# define ASIO_GETADDRINFO_ERROR(e) e
# define ASIO_OS_ERROR(e_win, e_posix) e_win
#else
# define ASIO_SOCKET_ERROR(e) e
# define ASIO_NETDB_ERROR(e) 16384 + e
# define ASIO_GETADDRINFO_ERROR(e) 32768 + e
# define ASIO_OS_ERROR(e_win, e_posix) e_posix
#endif
/// The error class is used to encapsulate system error codes.
class error
: public std::exception
{
public:
/// Error codes.
enum code_type
{
/// Permission denied.
access_denied = ASIO_SOCKET_ERROR(EACCES),
/// Address family not supported by protocol.
address_family_not_supported = ASIO_SOCKET_ERROR(EAFNOSUPPORT),
/// Address already in use.
address_in_use = ASIO_SOCKET_ERROR(EADDRINUSE),
/// Transport endpoint is already connected.
already_connected = ASIO_SOCKET_ERROR(EISCONN),
/// Operation already in progress.
already_started = ASIO_SOCKET_ERROR(EALREADY),
/// A connection has been aborted.
connection_aborted = ASIO_SOCKET_ERROR(ECONNABORTED),
/// Connection refused.
connection_refused = ASIO_SOCKET_ERROR(ECONNREFUSED),
/// Connection reset by peer.
connection_reset = ASIO_SOCKET_ERROR(ECONNRESET),
/// Bad file descriptor.
bad_descriptor = ASIO_SOCKET_ERROR(EBADF),
/// End of file or stream.
eof = ASIO_OS_ERROR(ERROR_HANDLE_EOF, -1),
/// Bad address.
fault = ASIO_SOCKET_ERROR(EFAULT),
/// Host not found (authoritative).
host_not_found = ASIO_NETDB_ERROR(HOST_NOT_FOUND),
/// Host not found (non-authoritative).
host_not_found_try_again = ASIO_NETDB_ERROR(TRY_AGAIN),
/// No route to host.
host_unreachable = ASIO_SOCKET_ERROR(EHOSTUNREACH),
/// Operation now in progress.
in_progress = ASIO_SOCKET_ERROR(EINPROGRESS),
/// Interrupted system call.
interrupted = ASIO_SOCKET_ERROR(EINTR),
/// Invalid argument.
invalid_argument = ASIO_SOCKET_ERROR(EINVAL),
/// Message too long.
message_size = ASIO_SOCKET_ERROR(EMSGSIZE),
/// Network is down.
network_down = ASIO_SOCKET_ERROR(ENETDOWN),
/// Network dropped connection on reset.
network_reset = ASIO_SOCKET_ERROR(ENETRESET),
/// Network is unreachable.
network_unreachable = ASIO_SOCKET_ERROR(ENETUNREACH),
/// Too many open files.
no_descriptors = ASIO_SOCKET_ERROR(EMFILE),
/// No buffer space available.
no_buffer_space = ASIO_SOCKET_ERROR(ENOBUFS),
/// The query is valid but does not have associated address data.
no_data = ASIO_NETDB_ERROR(NO_DATA),
/// Cannot allocate memory.
no_memory = ASIO_OS_ERROR(ERROR_OUTOFMEMORY, ENOMEM),
/// Operation not permitted.
no_permission = ASIO_OS_ERROR(ERROR_ACCESS_DENIED, EPERM),
/// Protocol not available.
no_protocol_option = ASIO_SOCKET_ERROR(ENOPROTOOPT),
/// A non-recoverable error occurred.
no_recovery = ASIO_NETDB_ERROR(NO_RECOVERY),
/// Transport endpoint is not connected.
not_connected = ASIO_SOCKET_ERROR(ENOTCONN),
/// Socket operation on non-socket.
not_socket = ASIO_SOCKET_ERROR(ENOTSOCK),
/// Operation not supported.
not_supported = ASIO_SOCKET_ERROR(EOPNOTSUPP),
/// Operation cancelled.
operation_aborted = ASIO_OS_ERROR(ERROR_OPERATION_ABORTED, ECANCELED),
/// The service is not supported for the given socket type.
service_not_found = ASIO_OS_ERROR(
WSATYPE_NOT_FOUND,
ASIO_GETADDRINFO_ERROR(EAI_SERVICE)),
/// The socket type is not supported.
socket_type_not_supported = ASIO_OS_ERROR(
WSAESOCKTNOSUPPORT,
ASIO_GETADDRINFO_ERROR(EAI_SOCKTYPE)),
/// Cannot send after transport endpoint shutdown.
shut_down = ASIO_SOCKET_ERROR(ESHUTDOWN),
/// Success.
success = 0,
/// Connection timed out.
timed_out = ASIO_SOCKET_ERROR(ETIMEDOUT),
/// Resource temporarily unavailable.
try_again = ASIO_OS_ERROR(ERROR_RETRY, EAGAIN),
/// The socket is marked non-blocking and the requested operation would
/// block.
would_block = ASIO_SOCKET_ERROR(EWOULDBLOCK)
};
/// Default constructor.
error()
: code_(success)
{
}
/// Construct with a specific error code.
error(int code)
: code_(code)
{
}
/// Copy constructor.
error(const error& e)
: std::exception(e),
code_(e.code_)
{
}
/// Destructor.
virtual ~error() throw ()
{
}
/// Assignment operator.
error& operator=(const error& e)
{
code_ = e.code_;
what_.reset();
return *this;
}
/// Get a string representation of the exception.
virtual const char* what() const throw ()
{
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
try
{
if (!what_)
{
char* msg = 0;
DWORD length = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS, 0, code_,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0);
detail::win_local_free_on_block_exit local_free_obj(msg);
if (length && msg[length - 1] == '\n')
msg[--length] = '\0';
if (length && msg[length - 1] == '\r')
msg[--length] = '\0';
if (length)
what_.reset(new std::string(msg));
else
return "asio error";
}
return what_->c_str();
}
catch (std::exception&)
{
return "asio error";
}
#else // defined(BOOST_WINDOWS)
switch (code_)
{
case error::eof:
return "End of file.";
case error::host_not_found:
return "Host not found (authoritative).";
case error::host_not_found_try_again:
return "Host not found (non-authoritative), try again later.";
case error::no_recovery:
return "A non-recoverable error occurred during database lookup.";
case error::no_data:
return "The query is valid, but it does not have associated data.";
#if !defined(__sun)
case error::operation_aborted:
return "Operation aborted.";
#endif // !defined(__sun)
case error::service_not_found:
return "Service not found.";
case error::socket_type_not_supported:
return "Socket type not supported.";
default:
#if defined(__sun) || defined(__QNX__)
return strerror(code_);
#elif defined(__MACH__) && defined(__APPLE__) \
|| defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
try
{
char buf[256] = "";
strerror_r(code_, buf, sizeof(buf));
what_.reset(new std::string(buf));
return what_->c_str();
}
catch (std::exception&)
{
return "asio error";
}
#else
try
{
char buf[256] = "";
what_.reset(new std::string(strerror_r(code_, buf, sizeof(buf))));
return what_->c_str();
}
catch (std::exception&)
{
return "asio error";
}
#endif
}
#endif // defined(BOOST_WINDOWS)
}
/// Get the code associated with the error.
int code() const
{
return code_;
}
struct unspecified_bool_type_t
{
};
typedef unspecified_bool_type_t* unspecified_bool_type;
/// Operator returns non-null if there is a non-success error code.
operator unspecified_bool_type() const
{
if (code_ == success)
return 0;
else
return reinterpret_cast<unspecified_bool_type>(1);
}
/// Operator to test if the error represents success.
bool operator!() const
{
return code_ == success;
}
/// Equality operator to compare two error objects.
friend bool operator==(const error& e1, const error& e2)
{
return e1.code_ == e2.code_;
}
/// Inequality operator to compare two error objects.
friend bool operator!=(const error& e1, const error& e2)
{
return e1.code_ != e2.code_;
}
private:
// The code associated with the error.
int code_;
// The string representation of the error.
mutable boost::scoped_ptr<std::string> what_;
};
/// Output the string associated with an error.
/**
* Used to output a human-readable string that is associated with an error.
*
* @param os The output stream to which the string will be written.
*
* @param e The error to be written.
*
* @return The output stream.
*
* @relates asio::error
*/
#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
std::ostream& operator<<(std::ostream& os, const error& e)
{
os << e.what();
return os;
}
#else // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
template <typename Ostream>
Ostream& operator<<(Ostream& os, const error& e)
{
os << e.what();
return os;
}
#endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
} // namespace asio
#undef ASIO_SOCKET_ERROR
#undef ASIO_NETDB_ERROR
#undef ASIO_GETADDRINFO_ERROR
#undef ASIO_OS_ERROR
#include "asio/detail/pop_options.hpp"
#endif // ASIO_ERROR_HPP

View File

@ -1,120 +0,0 @@
//
// error_handler.hpp
// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_ERROR_HANDLER_HPP
#define ASIO_ERROR_HANDLER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <boost/throw_exception.hpp>
#include "asio/detail/pop_options.hpp"
namespace asio {
namespace detail {
class ignore_error_t
{
public:
typedef void result_type;
template <typename Error>
void operator()(const Error&) const
{
}
};
class throw_error_t
{
public:
typedef void result_type;
template <typename Error>
void operator()(const Error& err) const
{
if (err)
boost::throw_exception(err);
}
};
template <typename Target>
class assign_error_t
{
public:
typedef void result_type;
assign_error_t(Target& target)
: target_(&target)
{
}
template <typename Error>
void operator()(const Error& err) const
{
*target_ = err;
}
private:
Target* target_;
};
} // namespace detail
/**
* @defgroup error_handler Error Handler Function Objects
*
* Function objects for custom error handling.
*/
/*@{*/
/// Return a function object that always ignores the error.
#if defined(GENERATING_DOCUMENTATION)
unspecified ignore_error();
#else
inline detail::ignore_error_t ignore_error()
{
return detail::ignore_error_t();
}
#endif
/// Return a function object that always throws the error.
#if defined(GENERATING_DOCUMENTATION)
unspecified throw_error();
#else
inline detail::throw_error_t throw_error()
{
return detail::throw_error_t();
}
#endif
/// Return a function object that assigns the error to a variable.
#if defined(GENERATING_DOCUMENTATION)
template <typename Target>
unspecified assign_error(Target& target);
#else
template <typename Target>
inline detail::assign_error_t<Target> assign_error(Target& target)
{
return detail::assign_error_t<Target>(target);
}
#endif
/*@}*/
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_ERROR_HANDLER_HPP

View File

@ -1,88 +0,0 @@
//
// handler_alloc_hook.hpp
// ~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_HANDLER_ALLOC_HOOK_HPP
#define ASIO_HANDLER_ALLOC_HOOK_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/push_options.hpp"
#include <cstddef>
#include <boost/config.hpp>
#include "asio/detail/pop_options.hpp"
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);
return ::operator delete(pointer);
}
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_HANDLER_ALLOC_HOOK_HPP

View File

@ -1,69 +0,0 @@
//
// handler_invoke_hook.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_HANDLER_INVOKE_HOOK_HPP
#define ASIO_HANDLER_INVOKE_HOOK_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
namespace asio {
/// 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 asio::io_service::run() on the corresponding
* io_service object. Handlers may subsequently be invoked through other
* objects (such as 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
#include "asio/detail/pop_options.hpp"
#endif // ASIO_HANDLER_INVOKE_HOOK_HPP

View File

@ -1,150 +0,0 @@
//
// io_service.ipp
// ~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IO_SERVICE_IPP
#define ASIO_IO_SERVICE_IPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/detail/epoll_reactor.hpp"
#include "asio/detail/kqueue_reactor.hpp"
#include "asio/detail/select_reactor.hpp"
#include "asio/detail/task_io_service.hpp"
#include "asio/detail/win_iocp_io_service.hpp"
namespace asio {
inline io_service::io_service()
: service_registry_(*this),
impl_(service_registry_.use_service<impl_type>())
{
}
inline size_t io_service::run()
{
return impl_.run();
}
inline size_t io_service::run_one()
{
return impl_.run_one();
}
inline size_t io_service::poll()
{
return impl_.poll();
}
inline size_t io_service::poll_one()
{
return impl_.poll_one();
}
inline void io_service::interrupt()
{
impl_.interrupt();
}
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(asio::io_service& io_service)
: io_service_(io_service)
{
io_service_.impl_.work_started();
}
inline io_service::work::work(const work& other)
: io_service_(other.io_service_)
{
io_service_.impl_.work_started();
}
inline io_service::work::~work()
{
io_service_.impl_.work_finished();
}
inline asio::io_service& io_service::work::io_service()
{
return io_service_;
}
inline io_service::service::service(asio::io_service& owner)
: owner_(owner),
type_info_(0),
next_(0)
{
}
inline io_service::service::~service()
{
}
inline asio::io_service& io_service::service::io_service()
{
return owner_;
}
template <typename Service>
inline Service& use_service(io_service& ios)
{
return ios.service_registry_.template use_service<Service>();
}
template <typename Service>
void add_service(io_service& ios, Service* svc)
{
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)
{
return ios.service_registry_.template has_service<Service>();
}
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_IO_SERVICE_IPP

View File

@ -1,294 +0,0 @@
//
// read.ipp
// ~~~~~~~~
//
// Copyright (c) 2003-2006 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_READ_IPP
#define ASIO_READ_IPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include "asio/detail/push_options.hpp"
#include "asio/buffer.hpp"
#include "asio/completion_condition.hpp"
#include "asio/error_handler.hpp"
#include "asio/detail/bind_handler.hpp"
#include "asio/detail/consuming_buffers.hpp"
#include "asio/detail/handler_alloc_helpers.hpp"
#include "asio/detail/handler_invoke_helpers.hpp"
namespace asio {
template <typename Sync_Read_Stream, typename Mutable_Buffers,
typename Completion_Condition, typename Error_Handler>
std::size_t read(Sync_Read_Stream& s, const Mutable_Buffers& buffers,
Completion_Condition completion_condition, Error_Handler error_handler)
{
asio::detail::consuming_buffers<
mutable_buffer, Mutable_Buffers> tmp(buffers);
std::size_t total_transferred = 0;
while (tmp.begin() != tmp.end())
{
typename Sync_Read_Stream::error_type e;
std::size_t bytes_transferred = s.read_some(tmp, assign_error(e));
tmp.consume(bytes_transferred);
total_transferred += bytes_transferred;
if (completion_condition(e, total_transferred))
{
error_handler(e);
return total_transferred;
}
}
typename Sync_Read_Stream::error_type e;
error_handler(e);
return total_transferred;
}
template <typename Sync_Read_Stream, typename Mutable_Buffers>
inline std::size_t read(Sync_Read_Stream& s, const Mutable_Buffers& buffers)
{
return read(s, buffers, transfer_all(), throw_error());
}
template <typename Sync_Read_Stream, typename Mutable_Buffers,
typename Completion_Condition>
inline std::size_t read(Sync_Read_Stream& s, const Mutable_Buffers& buffers,
Completion_Condition completion_condition)
{
return read(s, buffers, completion_condition, throw_error());
}
template <typename Sync_Read_Stream, typename Allocator,
typename Completion_Condition, typename Error_Handler>
std::size_t read(Sync_Read_Stream& s,
asio::basic_streambuf<Allocator>& b,
Completion_Condition completion_condition, Error_Handler error_handler)
{
std::size_t total_transferred = 0;
for (;;)
{
typename Sync_Read_Stream::error_type e;
std::size_t bytes_transferred = s.read_some(
b.prepare(512), assign_error(e));
b.commit(bytes_transferred);
total_transferred += bytes_transferred;
if (completion_condition(e, total_transferred))
{
error_handler(e);
return total_transferred;
}
}
}
template <typename Sync_Read_Stream, typename Allocator>
inline std::size_t read(Sync_Read_Stream& s,
asio::basic_streambuf<Allocator>& b)
{
return read(s, b, transfer_all(), throw_error());
}
template <typename Sync_Read_Stream, typename Allocator,
typename Completion_Condition>
inline std::size_t read(Sync_Read_Stream& s,
asio::basic_streambuf<Allocator>& b,
Completion_Condition completion_condition)
{
return read(s, b, completion_condition, throw_error());
}
namespace detail
{
template <typename Async_Read_Stream, typename Mutable_Buffers,
typename Completion_Condition, typename Handler>
class read_handler
{
public:
read_handler(Async_Read_Stream& stream, const Mutable_Buffers& buffers,
Completion_Condition completion_condition, Handler handler)
: stream_(stream),
buffers_(buffers),
total_transferred_(0),
completion_condition_(completion_condition),
handler_(handler)
{
}
void operator()(const typename Async_Read_Stream::error_type& e,
std::size_t bytes_transferred)
{
total_transferred_ += bytes_transferred;
buffers_.consume(bytes_transferred);
if (completion_condition_(e, total_transferred_)
|| buffers_.begin() == buffers_.end())
{
handler_(e, total_transferred_);
}
else
{
stream_.async_read_some(buffers_, *this);
}
}
//private:
Async_Read_Stream& stream_;
asio::detail::consuming_buffers<
mutable_buffer, Mutable_Buffers> buffers_;
std::size_t total_transferred_;
Completion_Condition completion_condition_;
Handler handler_;
};
template <typename Async_Read_Stream, typename Mutable_Buffers,
typename Completion_Condition, typename Handler>
inline void* asio_handler_allocate(std::size_t size,
read_handler<Async_Read_Stream, Mutable_Buffers,
Completion_Condition, Handler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, &this_handler->handler_);
}
template <typename Async_Read_Stream, typename Mutable_Buffers,
typename Completion_Condition, typename Handler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
read_handler<Async_Read_Stream, Mutable_Buffers,
Completion_Condition, Handler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, &this_handler->handler_);
}
template <typename Function, typename Async_Read_Stream,
typename Mutable_Buffers, typename Completion_Condition, typename Handler>
inline void asio_handler_invoke(const Function& function,
read_handler<Async_Read_Stream, Mutable_Buffers,
Completion_Condition, Handler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, &this_handler->handler_);
}
} // namespace detail
template <typename Async_Read_Stream, typename Mutable_Buffers,
typename Completion_Condition, typename Handler>
inline void async_read(Async_Read_Stream& s, const Mutable_Buffers& buffers,
Completion_Condition completion_condition, Handler handler)
{
s.async_read_some(buffers,
detail::read_handler<Async_Read_Stream, Mutable_Buffers,
Completion_Condition, Handler>(
s, buffers, completion_condition, handler));
}
template <typename Async_Read_Stream, typename Mutable_Buffers,
typename Handler>
inline void async_read(Async_Read_Stream& s, const Mutable_Buffers& buffers,
Handler handler)
{
async_read(s, buffers, transfer_all(), handler);
}
namespace detail
{
template <typename Async_Read_Stream, typename Allocator,
typename Completion_Condition, typename Handler>
class read_streambuf_handler
{
public:
read_streambuf_handler(Async_Read_Stream& stream,
basic_streambuf<Allocator>& streambuf,
Completion_Condition completion_condition, Handler handler)
: stream_(stream),
streambuf_(streambuf),
total_transferred_(0),
completion_condition_(completion_condition),
handler_(handler)
{
}
void operator()(const typename Async_Read_Stream::error_type& e,
std::size_t bytes_transferred)
{
total_transferred_ += bytes_transferred;
streambuf_.commit(bytes_transferred);
if (completion_condition_(e, total_transferred_))
{
handler_(e, total_transferred_);
}
else
{
stream_.async_read_some(streambuf_.prepare(512), *this);
}
}
//private:
Async_Read_Stream& stream_;
asio::basic_streambuf<Allocator>& streambuf_;
std::size_t total_transferred_;
Completion_Condition completion_condition_;
Handler handler_;
};
template <typename Async_Read_Stream, typename Allocator,
typename Completion_Condition, typename Handler>
inline void* asio_handler_allocate(std::size_t size,
read_streambuf_handler<Async_Read_Stream, Allocator,
Completion_Condition, Handler>* this_handler)
{
return asio_handler_alloc_helpers::allocate(
size, &this_handler->handler_);
}
template <typename Async_Read_Stream, typename Allocator,
typename Completion_Condition, typename Handler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
read_streambuf_handler<Async_Read_Stream, Allocator,
Completion_Condition, Handler>* this_handler)
{
asio_handler_alloc_helpers::deallocate(
pointer, size, &this_handler->handler_);
}
template <typename Function, typename Async_Read_Stream,
typename Allocator, typename Completion_Condition, typename Handler>
inline void asio_handler_invoke(const Function& function,
read_streambuf_handler<Async_Read_Stream, Allocator,
Completion_Condition, Handler>* this_handler)
{
asio_handler_invoke_helpers::invoke(
function, &this_handler->handler_);
}
} // namespace detail
template <typename Async_Read_Stream, typename Allocator,
typename Completion_Condition, typename Handler>
inline void async_read(Async_Read_Stream& s,
asio::basic_streambuf<Allocator>& b,
Completion_Condition completion_condition, Handler handler)
{
s.async_read_some(b.prepare(512),
detail::read_streambuf_handler<Async_Read_Stream, Allocator,
Completion_Condition, Handler>(
s, b, completion_condition, handler));
}
template <typename Async_Read_Stream, typename Allocator, typename Handler>
inline void async_read(Async_Read_Stream& s,
asio::basic_streambuf<Allocator>& b, Handler handler)
{
async_read(s, b, transfer_all(), handler);
}
} // namespace asio
#include "asio/detail/pop_options.hpp"
#endif // ASIO_READ_IPP

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