mirror of
https://github.com/codex-storage/deluge.git
synced 2025-02-25 09:35:16 +00:00
Update to asio 1.4.1
This commit is contained in:
parent
73e58c20c8
commit
e08c51e10c
@ -142,6 +142,20 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Get a const reference to the lowest layer.
|
||||
/**
|
||||
* This function returns a const reference to the lowest layer in a stack of
|
||||
* layers. Since a basic_serial_port cannot contain any further layers, it
|
||||
* simply returns a reference to itself.
|
||||
*
|
||||
* @return A const reference to the lowest layer in the stack of layers.
|
||||
* Ownership is not transferred to the caller.
|
||||
*/
|
||||
const lowest_layer_type& lowest_layer() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Open the serial port using the specified device name.
|
||||
/**
|
||||
* This function opens the serial port for the specified device name.
|
||||
|
@ -149,6 +149,20 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Get a const reference to the lowest layer.
|
||||
/**
|
||||
* This function returns a const 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 const reference to the lowest layer in the stack of layers.
|
||||
* Ownership is not transferred to the caller.
|
||||
*/
|
||||
const lowest_layer_type& lowest_layer() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Open the socket using the specified protocol.
|
||||
/**
|
||||
* This function opens the socket so that it will use the specified protocol.
|
||||
|
@ -247,7 +247,8 @@ private:
|
||||
setp(put_buffer_.begin(), put_buffer_.end());
|
||||
}
|
||||
|
||||
void resolve_and_connect(const typename Protocol::resolver_query& query,
|
||||
template <typename ResolverQuery>
|
||||
void resolve_and_connect(const ResolverQuery& query,
|
||||
asio::error_code& ec)
|
||||
{
|
||||
typedef typename Protocol::resolver resolver_type;
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
@ -32,6 +33,73 @@
|
||||
namespace asio {
|
||||
|
||||
/// Automatically resizable buffer class based on std::streambuf.
|
||||
/**
|
||||
* The @c basic_streambuf class is derived from @c std::streambuf to associate
|
||||
* the streambuf's input and output sequences with one or more character
|
||||
* arrays. These character arrays are internal to the @c basic_streambuf
|
||||
* object, but direct access to the array elements is provided to permit them
|
||||
* to be used efficiently with I/O operations. Characters written to the output
|
||||
* sequence of a @c basic_streambuf object are appended to the input sequence
|
||||
* of the same object.
|
||||
*
|
||||
* The @c basic_streambuf class's public interface is intended to permit the
|
||||
* following implementation strategies:
|
||||
*
|
||||
* @li A single contiguous character array, which is reallocated as necessary
|
||||
* to accommodate changes in the size of the character sequence. This is the
|
||||
* implementation approach currently used in Asio.
|
||||
*
|
||||
* @li A sequence of one or more character arrays, where each array is of the
|
||||
* same size. Additional character array objects are appended to the sequence
|
||||
* to accommodate changes in the size of the character sequence.
|
||||
*
|
||||
* @li A sequence of one or more character arrays of varying sizes. Additional
|
||||
* character array objects are appended to the sequence to accommodate changes
|
||||
* in the size of the character sequence.
|
||||
*
|
||||
* The constructor for basic_streambuf accepts a @c size_t argument specifying
|
||||
* the maximum of the sum of the sizes of the input sequence and output
|
||||
* sequence. During the lifetime of the @c basic_streambuf object, the following
|
||||
* invariant holds:
|
||||
* @code size() <= max_size()@endcode
|
||||
* Any member function that would, if successful, cause the invariant to be
|
||||
* violated shall throw an exception of class @c std::length_error.
|
||||
*
|
||||
* The constructor for @c basic_streambuf takes an Allocator argument. A copy
|
||||
* of this argument is used for any memory allocation performed, by the
|
||||
* constructor and by all member functions, during the lifetime of each @c
|
||||
* basic_streambuf object.
|
||||
*
|
||||
* @par Examples
|
||||
* Writing directly from an streambuf to a socket:
|
||||
* @code
|
||||
* asio::streambuf b;
|
||||
* std::ostream os(&b);
|
||||
* os << "Hello, World!\n";
|
||||
*
|
||||
* // try sending some data in input sequence
|
||||
* size_t n = sock.send(b.data());
|
||||
*
|
||||
* b.consume(n); // sent data is removed from input sequence
|
||||
* @endcode
|
||||
*
|
||||
* Reading from a socket directly into a streambuf:
|
||||
* @code
|
||||
* asio::streambuf b;
|
||||
*
|
||||
* // reserve 512 bytes in output sequence
|
||||
* asio::streambuf::const_buffers_type bufs = b.prepare(512);
|
||||
*
|
||||
* size_t n = sock.receive(bufs);
|
||||
*
|
||||
* // received data is "committed" from output sequence to input sequence
|
||||
* b.commit(n);
|
||||
*
|
||||
* std::istream is(&b);
|
||||
* std::string s;
|
||||
* is >> s;
|
||||
* @endcode
|
||||
*/
|
||||
template <typename Allocator = std::allocator<char> >
|
||||
class basic_streambuf
|
||||
: public std::streambuf,
|
||||
@ -39,17 +107,21 @@ class basic_streambuf
|
||||
{
|
||||
public:
|
||||
#if defined(GENERATING_DOCUMENTATION)
|
||||
/// The type used to represent the get area as a list of buffers.
|
||||
/// The type used to represent the input sequence as a list of buffers.
|
||||
typedef implementation_defined const_buffers_type;
|
||||
|
||||
/// The type used to represent the put area as a list of buffers.
|
||||
/// The type used to represent the output sequence as a list of buffers.
|
||||
typedef implementation_defined mutable_buffers_type;
|
||||
#else
|
||||
typedef asio::const_buffers_1 const_buffers_type;
|
||||
typedef asio::mutable_buffers_1 mutable_buffers_type;
|
||||
#endif
|
||||
|
||||
/// Construct a buffer with a specified maximum size.
|
||||
/// Construct a basic_streambuf object.
|
||||
/**
|
||||
* Constructs a streambuf with the specified maximum size. The initial size
|
||||
* of the streambuf's input sequence is 0.
|
||||
*/
|
||||
explicit basic_streambuf(
|
||||
std::size_t max_size = (std::numeric_limits<std::size_t>::max)(),
|
||||
const Allocator& allocator = Allocator())
|
||||
@ -62,42 +134,100 @@ public:
|
||||
setp(&buffer_[0], &buffer_[0] + pend);
|
||||
}
|
||||
|
||||
/// Return the size of the get area in characters.
|
||||
/// Get the size of the input sequence.
|
||||
/**
|
||||
* @returns The size of the input sequence. The value is equal to that
|
||||
* calculated for @c s in the following code:
|
||||
* @code
|
||||
* size_t s = 0;
|
||||
* const_buffers_type bufs = data();
|
||||
* const_buffers_type::const_iterator i = bufs.begin();
|
||||
* while (i != bufs.end())
|
||||
* {
|
||||
* const_buffer buf(*i++);
|
||||
* s += buffer_size(buf);
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
std::size_t size() const
|
||||
{
|
||||
return pptr() - gptr();
|
||||
}
|
||||
|
||||
/// Return the maximum size of the buffer.
|
||||
/// Get the maximum size of the basic_streambuf.
|
||||
/**
|
||||
* @returns The allowed maximum of the sum of the sizes of the input sequence
|
||||
* and output sequence.
|
||||
*/
|
||||
std::size_t max_size() const
|
||||
{
|
||||
return max_size_;
|
||||
}
|
||||
|
||||
/// Get a list of buffers that represents the get area.
|
||||
/// Get a list of buffers that represents the input sequence.
|
||||
/**
|
||||
* @returns An object of type @c const_buffers_type that satisfies
|
||||
* ConstBufferSequence requirements, representing all character arrays in the
|
||||
* input sequence.
|
||||
*
|
||||
* @note The returned object is invalidated by any @c basic_streambuf member
|
||||
* function that modifies the input sequence or output sequence.
|
||||
*/
|
||||
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)
|
||||
/// Get a list of buffers that represents the output sequence, with the given
|
||||
/// size.
|
||||
/**
|
||||
* Ensures that the output sequence can accommodate @c n characters,
|
||||
* reallocating character array objects as necessary.
|
||||
*
|
||||
* @returns An object of type @c mutable_buffers_type that satisfies
|
||||
* MutableBufferSequence requirements, representing character array objects
|
||||
* at the start of the output sequence such that the sum of the buffer sizes
|
||||
* is @c n.
|
||||
*
|
||||
* @throws std::length_error If <tt>size() + n > max_size()</tt>.
|
||||
*
|
||||
* @note The returned object is invalidated by any @c basic_streambuf member
|
||||
* function that modifies the input sequence or output sequence.
|
||||
*/
|
||||
mutable_buffers_type prepare(std::size_t n)
|
||||
{
|
||||
reserve(size);
|
||||
reserve(n);
|
||||
return asio::buffer(asio::mutable_buffer(
|
||||
pptr(), size * sizeof(char_type)));
|
||||
pptr(), n * sizeof(char_type)));
|
||||
}
|
||||
|
||||
/// Move the start of the put area by the specified number of characters.
|
||||
/// Move characters from the output sequence to the input sequence.
|
||||
/**
|
||||
* Appends @c n characters from the start of the output sequence to the input
|
||||
* sequence. The beginning of the output sequence is advanced by @c n
|
||||
* characters.
|
||||
*
|
||||
* Requires a preceding call <tt>prepare(x)</tt> where <tt>x >= n</tt>, and
|
||||
* no intervening operations that modify the input or output sequence.
|
||||
*
|
||||
* @throws std::length_error If @c n is greater than the size of the output
|
||||
* sequence.
|
||||
*/
|
||||
void commit(std::size_t n)
|
||||
{
|
||||
if (pptr() + n > epptr())
|
||||
n = epptr() - pptr();
|
||||
pbump(static_cast<int>(n));
|
||||
setg(eback(), gptr(), pptr());
|
||||
}
|
||||
|
||||
/// Move the start of the get area by the specified number of characters.
|
||||
/// Remove characters from the input sequence.
|
||||
/**
|
||||
* Removes @c n characters from the beginning of the input sequence.
|
||||
*
|
||||
* @throws std::length_error If <tt>n > size()</tt>.
|
||||
*/
|
||||
void consume(std::size_t n)
|
||||
{
|
||||
if (gptr() + n > pptr())
|
||||
@ -108,6 +238,10 @@ public:
|
||||
protected:
|
||||
enum { buffer_delta = 128 };
|
||||
|
||||
/// Override std::streambuf behaviour.
|
||||
/**
|
||||
* Behaves according to the specification of @c std::streambuf::underflow().
|
||||
*/
|
||||
int_type underflow()
|
||||
{
|
||||
if (gptr() < pptr())
|
||||
@ -121,6 +255,13 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
/// Override std::streambuf behaviour.
|
||||
/**
|
||||
* Behaves according to the specification of @c std::streambuf::overflow(),
|
||||
* with the specialisation that @c std::length_error is thrown if appending
|
||||
* the character to the input sequence would require the condition
|
||||
* <tt>size() > max_size()</tt> to be true.
|
||||
*/
|
||||
int_type overflow(int_type c)
|
||||
{
|
||||
if (!traits_type::eq_int_type(c, traits_type::eof()))
|
||||
@ -150,7 +291,6 @@ protected:
|
||||
{
|
||||
// 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];
|
||||
|
||||
@ -163,9 +303,8 @@ protected:
|
||||
// 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;
|
||||
std::memmove(&buffer_[0], &buffer_[0] + gnext, pnext);
|
||||
}
|
||||
|
||||
// Ensure buffer is large enough to hold at least the specified size.
|
||||
@ -173,7 +312,8 @@ protected:
|
||||
{
|
||||
if (n <= max_size_ && pnext <= max_size_ - n)
|
||||
{
|
||||
buffer_.resize((std::max<std::size_t>)(pnext + n, 1));
|
||||
pend = pnext + n;
|
||||
buffer_.resize((std::max<std::size_t>)(pend, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -182,8 +322,8 @@ protected:
|
||||
}
|
||||
|
||||
// Update stream positions.
|
||||
setg(&buffer_[0], &buffer_[0], &buffer_[0] + gend);
|
||||
setp(&buffer_[0] + pnext, &buffer_[0] + pnext + n);
|
||||
setg(&buffer_[0], &buffer_[0], &buffer_[0] + pnext);
|
||||
setp(&buffer_[0] + pnext, &buffer_[0] + pend);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -93,6 +93,12 @@ public:
|
||||
return next_layer_.lowest_layer();
|
||||
}
|
||||
|
||||
/// Get a const reference to the lowest layer.
|
||||
const lowest_layer_type& lowest_layer() const
|
||||
{
|
||||
return next_layer_.lowest_layer();
|
||||
}
|
||||
|
||||
/// (Deprecated: use get_io_service().) Get the io_service associated with
|
||||
/// the object.
|
||||
asio::io_service& io_service()
|
||||
|
@ -83,6 +83,12 @@ public:
|
||||
return stream_impl_.lowest_layer();
|
||||
}
|
||||
|
||||
/// Get a const reference to the lowest layer.
|
||||
const lowest_layer_type& lowest_layer() const
|
||||
{
|
||||
return stream_impl_.lowest_layer();
|
||||
}
|
||||
|
||||
/// (Deprecated: use get_io_service().) Get the io_service associated with
|
||||
/// the object.
|
||||
asio::io_service& io_service()
|
||||
|
@ -94,6 +94,12 @@ public:
|
||||
return next_layer_.lowest_layer();
|
||||
}
|
||||
|
||||
/// Get a const reference to the lowest layer.
|
||||
const lowest_layer_type& lowest_layer() const
|
||||
{
|
||||
return next_layer_.lowest_layer();
|
||||
}
|
||||
|
||||
/// (Deprecated: use get_io_service().) Get the io_service associated with
|
||||
/// the object.
|
||||
asio::io_service& io_service()
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <cstddef>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/type_traits/add_const.hpp>
|
||||
@ -100,6 +101,9 @@ public:
|
||||
|
||||
/// Construct an iterator representing the beginning of the buffers' data.
|
||||
static buffers_iterator begin(const BufferSequence& buffers)
|
||||
#if BOOST_WORKAROUND(__GNUC__, == 4) && BOOST_WORKAROUND(__GNUC_MINOR__, == 3)
|
||||
__attribute__ ((noinline))
|
||||
#endif
|
||||
{
|
||||
buffers_iterator new_iter;
|
||||
new_iter.begin_ = buffers.begin();
|
||||
@ -117,6 +121,9 @@ public:
|
||||
|
||||
/// Construct an iterator representing the end of the buffers' data.
|
||||
static buffers_iterator end(const BufferSequence& buffers)
|
||||
#if BOOST_WORKAROUND(__GNUC__, == 4) && BOOST_WORKAROUND(__GNUC_MINOR__, == 3)
|
||||
__attribute__ ((noinline))
|
||||
#endif
|
||||
{
|
||||
buffers_iterator new_iter;
|
||||
new_iter.begin_ = buffers.begin();
|
||||
|
@ -26,22 +26,40 @@ namespace asio {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// The default maximum number of bytes to transfer in a single operation.
|
||||
enum { default_max_transfer_size = 65536 };
|
||||
|
||||
// Adapt result of old-style completion conditions (which had a bool result
|
||||
// where true indicated that the operation was complete).
|
||||
inline std::size_t adapt_completion_condition_result(bool result)
|
||||
{
|
||||
return result ? 0 : default_max_transfer_size;
|
||||
}
|
||||
|
||||
// Adapt result of current completion conditions (which have a size_t result
|
||||
// where 0 means the operation is complete, and otherwise the result is the
|
||||
// maximum number of bytes to transfer on the next underlying operation).
|
||||
inline std::size_t adapt_completion_condition_result(std::size_t result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
class transfer_all_t
|
||||
{
|
||||
public:
|
||||
typedef bool result_type;
|
||||
typedef std::size_t result_type;
|
||||
|
||||
template <typename Error>
|
||||
bool operator()(const Error& err, std::size_t)
|
||||
std::size_t operator()(const Error& err, std::size_t)
|
||||
{
|
||||
return !!err;
|
||||
return !!err ? 0 : default_max_transfer_size;
|
||||
}
|
||||
};
|
||||
|
||||
class transfer_at_least_t
|
||||
{
|
||||
public:
|
||||
typedef bool result_type;
|
||||
typedef std::size_t result_type;
|
||||
|
||||
explicit transfer_at_least_t(std::size_t minimum)
|
||||
: minimum_(minimum)
|
||||
@ -49,9 +67,10 @@ public:
|
||||
}
|
||||
|
||||
template <typename Error>
|
||||
bool operator()(const Error& err, std::size_t bytes_transferred)
|
||||
std::size_t operator()(const Error& err, std::size_t bytes_transferred)
|
||||
{
|
||||
return !!err || bytes_transferred >= minimum_;
|
||||
return (!!err || bytes_transferred >= minimum_)
|
||||
? 0 : default_max_transfer_size;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -20,11 +20,13 @@
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <limits>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/buffer.hpp"
|
||||
#include "asio/completion_condition.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
@ -46,33 +48,33 @@ public:
|
||||
// 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),
|
||||
Buffer_Iterator begin_remainder, Buffer_Iterator end_remainder,
|
||||
std::size_t max_size)
|
||||
: at_end_(max_size > 0 ? at_end : true),
|
||||
first_(buffer(first, max_size)),
|
||||
begin_remainder_(begin_remainder),
|
||||
end_remainder_(end_remainder),
|
||||
offset_(0)
|
||||
offset_(0),
|
||||
max_size_(max_size)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
enum { max_size = 65536 };
|
||||
|
||||
void increment()
|
||||
{
|
||||
if (!at_end_)
|
||||
{
|
||||
if (begin_remainder_ == end_remainder_
|
||||
|| offset_ + buffer_size(first_) >= max_size)
|
||||
|| offset_ + buffer_size(first_) >= max_size_)
|
||||
{
|
||||
at_end_ = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset_ += buffer_size(first_);
|
||||
first_ = buffer(*begin_remainder_++, max_size - offset_);
|
||||
first_ = buffer(*begin_remainder_++, max_size_ - offset_);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -99,6 +101,7 @@ private:
|
||||
Buffer_Iterator begin_remainder_;
|
||||
Buffer_Iterator end_remainder_;
|
||||
std::size_t offset_;
|
||||
std::size_t max_size_;
|
||||
};
|
||||
|
||||
// A proxy for a sub-range in a list of buffers.
|
||||
@ -118,7 +121,8 @@ public:
|
||||
: buffers_(buffers),
|
||||
at_end_(buffers_.begin() == buffers_.end()),
|
||||
first_(*buffers_.begin()),
|
||||
begin_remainder_(buffers_.begin())
|
||||
begin_remainder_(buffers_.begin()),
|
||||
max_size_((std::numeric_limits<std::size_t>::max)())
|
||||
{
|
||||
if (!at_end_)
|
||||
++begin_remainder_;
|
||||
@ -129,7 +133,8 @@ public:
|
||||
: buffers_(other.buffers_),
|
||||
at_end_(other.at_end_),
|
||||
first_(other.first_),
|
||||
begin_remainder_(buffers_.begin())
|
||||
begin_remainder_(buffers_.begin()),
|
||||
max_size_(other.max_size_)
|
||||
{
|
||||
typename Buffers::const_iterator first = other.buffers_.begin();
|
||||
typename Buffers::const_iterator second = other.begin_remainder_;
|
||||
@ -146,13 +151,15 @@ public:
|
||||
typename Buffers::const_iterator first = other.buffers_.begin();
|
||||
typename Buffers::const_iterator second = other.begin_remainder_;
|
||||
std::advance(begin_remainder_, std::distance(first, second));
|
||||
max_size_ = other.max_size_;
|
||||
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());
|
||||
return const_iterator(at_end_, first_,
|
||||
begin_remainder_, buffers_.end(), max_size_);
|
||||
}
|
||||
|
||||
// Get a forward-only iterator for one past the last element.
|
||||
@ -161,6 +168,12 @@ public:
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
// Set the maximum size for a single transfer.
|
||||
void set_max_size(std::size_t max_size)
|
||||
{
|
||||
max_size_ = max_size;
|
||||
}
|
||||
|
||||
// Consume the specified number of bytes from the buffers.
|
||||
void consume(std::size_t size)
|
||||
{
|
||||
@ -197,6 +210,7 @@ private:
|
||||
bool at_end_;
|
||||
Buffer first_;
|
||||
typename Buffers::const_iterator begin_remainder_;
|
||||
std::size_t max_size_;
|
||||
};
|
||||
|
||||
// Specialisation for null_buffers to ensure that the null_buffers type is
|
||||
@ -211,6 +225,11 @@ public:
|
||||
// No-op.
|
||||
}
|
||||
|
||||
void set_max_size(std::size_t)
|
||||
{
|
||||
// No-op.
|
||||
}
|
||||
|
||||
void consume(std::size_t)
|
||||
{
|
||||
// No-op.
|
||||
|
@ -63,6 +63,7 @@ public:
|
||||
deadline_timer_service<Time_Traits, Timer_Scheduler> >(io_service),
|
||||
scheduler_(asio::use_service<Timer_Scheduler>(io_service))
|
||||
{
|
||||
scheduler_.init_task();
|
||||
scheduler_.add_timer_queue(timer_queue_);
|
||||
}
|
||||
|
||||
|
@ -58,17 +58,28 @@ inline int close(int d, asio::error_code& ec)
|
||||
return error_wrapper(::close(d), ec);
|
||||
}
|
||||
|
||||
inline void init_buf_iov_base(void*& base, void* addr)
|
||||
{
|
||||
base = addr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void init_buf_iov_base(T& base, void* addr)
|
||||
{
|
||||
base = static_cast<T>(addr);
|
||||
}
|
||||
|
||||
typedef iovec buf;
|
||||
|
||||
inline void init_buf(buf& b, void* data, size_t size)
|
||||
{
|
||||
b.iov_base = data;
|
||||
init_buf_iov_base(b.iov_base, data);
|
||||
b.iov_len = size;
|
||||
}
|
||||
|
||||
inline void init_buf(buf& b, const void* data, size_t size)
|
||||
{
|
||||
b.iov_base = const_cast<void*>(data);
|
||||
init_buf_iov_base(b.iov_base, const_cast<void*>(data));
|
||||
b.iov_len = size;
|
||||
}
|
||||
|
||||
|
@ -122,6 +122,17 @@ public:
|
||||
timer_queues_.clear();
|
||||
}
|
||||
|
||||
// Initialise the task, but only if the reactor is not in its own thread.
|
||||
void init_task()
|
||||
{
|
||||
if (!Own_Thread)
|
||||
{
|
||||
typedef task_io_service<dev_poll_reactor<Own_Thread> >
|
||||
task_io_service_type;
|
||||
use_service<task_io_service_type>(this->get_io_service()).init_task();
|
||||
}
|
||||
}
|
||||
|
||||
// Register a socket with the reactor. Returns 0 on success, system error
|
||||
// code on failure.
|
||||
int register_descriptor(socket_type, per_descriptor_data&)
|
||||
@ -421,6 +432,7 @@ private:
|
||||
more_writes = write_op_queue_.perform_operation(descriptor, ec);
|
||||
else
|
||||
more_writes = write_op_queue_.has_operation(descriptor);
|
||||
|
||||
if ((events[i].events & (POLLERR | POLLHUP)) != 0
|
||||
&& (events[i].events & ~(POLLERR | POLLHUP)) == 0
|
||||
&& !more_except && !more_reads && !more_writes)
|
||||
|
@ -123,6 +123,16 @@ public:
|
||||
timer_queues_.clear();
|
||||
}
|
||||
|
||||
// Initialise the task, but only if the reactor is not in its own thread.
|
||||
void init_task()
|
||||
{
|
||||
if (!Own_Thread)
|
||||
{
|
||||
typedef task_io_service<epoll_reactor<Own_Thread> > task_io_service_type;
|
||||
use_service<task_io_service_type>(this->get_io_service()).init_task();
|
||||
}
|
||||
}
|
||||
|
||||
// Register a socket with the reactor. Returns 0 on success, system error
|
||||
// code on failure.
|
||||
int register_descriptor(socket_type descriptor,
|
||||
@ -495,6 +505,7 @@ private:
|
||||
more_writes = write_op_queue_.perform_operation(descriptor, ec);
|
||||
else
|
||||
more_writes = write_op_queue_.has_operation(descriptor);
|
||||
|
||||
if ((events[i].events & (EPOLLERR | EPOLLHUP)) != 0
|
||||
&& (events[i].events & ~(EPOLLERR | EPOLLHUP)) == 0
|
||||
&& !more_except && !more_reads && !more_writes)
|
||||
|
@ -131,6 +131,16 @@ public:
|
||||
timer_queues_.clear();
|
||||
}
|
||||
|
||||
// Initialise the task, but only if the reactor is not in its own thread.
|
||||
void init_task()
|
||||
{
|
||||
if (!Own_Thread)
|
||||
{
|
||||
typedef task_io_service<kqueue_reactor<Own_Thread> > task_io_service_type;
|
||||
use_service<task_io_service_type>(this->get_io_service()).init_task();
|
||||
}
|
||||
}
|
||||
|
||||
// Register a socket with the reactor. Returns 0 on success, system error
|
||||
// code on failure.
|
||||
int register_descriptor(socket_type, per_descriptor_data& descriptor_data)
|
||||
|
@ -38,12 +38,9 @@ class null_thread
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
// The purpose of the thread.
|
||||
enum purpose { internal, external };
|
||||
|
||||
// Constructor.
|
||||
template <typename Function>
|
||||
null_thread(Function f, purpose = internal)
|
||||
null_thread(Function f)
|
||||
{
|
||||
asio::system_error e(
|
||||
asio::error::operation_not_supported, "thread");
|
||||
|
@ -71,7 +71,8 @@ public:
|
||||
void interrupt()
|
||||
{
|
||||
char byte = 0;
|
||||
::write(write_descriptor_, &byte, 1);
|
||||
int result = ::write(write_descriptor_, &byte, 1);
|
||||
(void)result;
|
||||
}
|
||||
|
||||
// Reset the select interrupt. Returns true if the call was interrupted.
|
||||
|
@ -17,6 +17,10 @@
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <cstring>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/detail/socket_types.hpp"
|
||||
|
||||
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
|
@ -42,12 +42,9 @@ class posix_thread
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
// The purpose of the thread.
|
||||
enum purpose { internal, external };
|
||||
|
||||
// Constructor.
|
||||
template <typename Function>
|
||||
posix_thread(Function f, purpose = internal)
|
||||
posix_thread(Function f)
|
||||
: joined_(false)
|
||||
{
|
||||
std::auto_ptr<func_base> arg(new func<Function>(f));
|
||||
|
@ -81,6 +81,7 @@ public:
|
||||
reactive_descriptor_service<Reactor> >(io_service),
|
||||
reactor_(asio::use_service<Reactor>(io_service))
|
||||
{
|
||||
reactor_.init_task();
|
||||
}
|
||||
|
||||
// Destroy all user-defined handler objects owned by the service.
|
||||
|
@ -119,6 +119,7 @@ public:
|
||||
ios.c_cflag |= CS8;
|
||||
#endif
|
||||
ios.c_iflag |= IGNPAR;
|
||||
ios.c_cflag |= CREAD | CLOCAL;
|
||||
descriptor_ops::clear_error(ec);
|
||||
s = descriptor_ops::error_wrapper(::tcsetattr(fd, TCSANOW, &ios), ec);
|
||||
}
|
||||
|
@ -73,10 +73,21 @@ public:
|
||||
|
||||
enum
|
||||
{
|
||||
user_set_non_blocking = 1, // The user wants a non-blocking socket.
|
||||
internal_non_blocking = 2, // The socket has been set non-blocking.
|
||||
enable_connection_aborted = 4, // User wants connection_aborted errors.
|
||||
user_set_linger = 8 // The user set the linger option.
|
||||
// The user wants a non-blocking socket.
|
||||
user_set_non_blocking = 1,
|
||||
|
||||
// The implementation wants a non-blocking socket (in order to be able to
|
||||
// perform asynchronous read and write operations).
|
||||
internal_non_blocking = 2,
|
||||
|
||||
// Helper "flag" used to determine whether the socket is non-blocking.
|
||||
non_blocking = user_set_non_blocking | internal_non_blocking,
|
||||
|
||||
// User wants connection_aborted errors, which are disabled by default.
|
||||
enable_connection_aborted = 4,
|
||||
|
||||
// The user set the linger option. Needs to be checked when closing.
|
||||
user_set_linger = 8
|
||||
};
|
||||
|
||||
// Flags indicating the current state of the socket.
|
||||
@ -98,6 +109,7 @@ public:
|
||||
reactive_socket_service<Protocol, Reactor> >(io_service),
|
||||
reactor_(asio::use_service<Reactor>(io_service))
|
||||
{
|
||||
reactor_.init_task();
|
||||
}
|
||||
|
||||
// Destroy all user-defined handler objects owned by the service.
|
||||
@ -119,12 +131,12 @@ public:
|
||||
{
|
||||
reactor_.close_descriptor(impl.socket_, impl.reactor_data_);
|
||||
|
||||
if (impl.flags_ & implementation_type::internal_non_blocking)
|
||||
if (impl.flags_ & implementation_type::non_blocking)
|
||||
{
|
||||
ioctl_arg_type non_blocking = 0;
|
||||
asio::error_code ignored_ec;
|
||||
socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec);
|
||||
impl.flags_ &= ~implementation_type::internal_non_blocking;
|
||||
impl.flags_ &= ~implementation_type::non_blocking;
|
||||
}
|
||||
|
||||
if (impl.flags_ & implementation_type::user_set_linger)
|
||||
@ -213,12 +225,12 @@ public:
|
||||
{
|
||||
reactor_.close_descriptor(impl.socket_, impl.reactor_data_);
|
||||
|
||||
if (impl.flags_ & implementation_type::internal_non_blocking)
|
||||
if (impl.flags_ & implementation_type::non_blocking)
|
||||
{
|
||||
ioctl_arg_type non_blocking = 0;
|
||||
asio::error_code ignored_ec;
|
||||
socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ignored_ec);
|
||||
impl.flags_ &= ~implementation_type::internal_non_blocking;
|
||||
impl.flags_ &= ~implementation_type::non_blocking;
|
||||
}
|
||||
|
||||
if (socket_ops::close(impl.socket_, ec) == socket_error_retval)
|
||||
@ -432,11 +444,35 @@ public:
|
||||
|
||||
if (command.name() == static_cast<int>(FIONBIO))
|
||||
{
|
||||
// Flags are manipulated in a temporary variable so that the socket
|
||||
// implementation is not updated unless the ioctl operation succeeds.
|
||||
unsigned char new_flags = impl.flags_;
|
||||
if (command.get())
|
||||
impl.flags_ |= implementation_type::user_set_non_blocking;
|
||||
new_flags |= implementation_type::user_set_non_blocking;
|
||||
else
|
||||
impl.flags_ &= ~implementation_type::user_set_non_blocking;
|
||||
ec = asio::error_code();
|
||||
new_flags &= ~implementation_type::user_set_non_blocking;
|
||||
|
||||
// Perform ioctl on socket if the non-blocking state has changed.
|
||||
if (!(impl.flags_ & implementation_type::non_blocking)
|
||||
&& (new_flags & implementation_type::non_blocking))
|
||||
{
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec);
|
||||
}
|
||||
else if ((impl.flags_ & implementation_type::non_blocking)
|
||||
&& !(new_flags & implementation_type::non_blocking))
|
||||
{
|
||||
ioctl_arg_type non_blocking = 0;
|
||||
socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec);
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = asio::error_code();
|
||||
}
|
||||
|
||||
// Update socket implementation's flags only if successful.
|
||||
if (!ec)
|
||||
impl.flags_ = new_flags;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -529,18 +565,6 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Make socket non-blocking if user wants non-blocking.
|
||||
if (impl.flags_ & implementation_type::user_set_non_blocking)
|
||||
{
|
||||
if (!(impl.flags_ & implementation_type::internal_non_blocking))
|
||||
{
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
return 0;
|
||||
impl.flags_ |= implementation_type::internal_non_blocking;
|
||||
}
|
||||
}
|
||||
|
||||
// Send the data.
|
||||
for (;;)
|
||||
{
|
||||
@ -683,12 +707,15 @@ public:
|
||||
// Make socket non-blocking.
|
||||
if (!(impl.flags_ & implementation_type::internal_non_blocking))
|
||||
{
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
if (!(impl.flags_ & implementation_type::non_blocking))
|
||||
{
|
||||
this->get_io_service().post(bind_handler(handler, ec, 0));
|
||||
return;
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
{
|
||||
this->get_io_service().post(bind_handler(handler, ec, 0));
|
||||
return;
|
||||
}
|
||||
}
|
||||
impl.flags_ |= implementation_type::internal_non_blocking;
|
||||
}
|
||||
@ -772,18 +799,6 @@ public:
|
||||
asio::buffer_size(buffer));
|
||||
}
|
||||
|
||||
// Make socket non-blocking if user wants non-blocking.
|
||||
if (impl.flags_ & implementation_type::user_set_non_blocking)
|
||||
{
|
||||
if (!(impl.flags_ & implementation_type::internal_non_blocking))
|
||||
{
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
return 0;
|
||||
impl.flags_ |= implementation_type::internal_non_blocking;
|
||||
}
|
||||
}
|
||||
|
||||
// Send the data.
|
||||
for (;;)
|
||||
{
|
||||
@ -911,12 +926,15 @@ public:
|
||||
// Make socket non-blocking.
|
||||
if (!(impl.flags_ & implementation_type::internal_non_blocking))
|
||||
{
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
if (!(impl.flags_ & implementation_type::non_blocking))
|
||||
{
|
||||
this->get_io_service().post(bind_handler(handler, ec, 0));
|
||||
return;
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
{
|
||||
this->get_io_service().post(bind_handler(handler, ec, 0));
|
||||
return;
|
||||
}
|
||||
}
|
||||
impl.flags_ |= implementation_type::internal_non_blocking;
|
||||
}
|
||||
@ -980,18 +998,6 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Make socket non-blocking if user wants non-blocking.
|
||||
if (impl.flags_ & implementation_type::user_set_non_blocking)
|
||||
{
|
||||
if (!(impl.flags_ & implementation_type::internal_non_blocking))
|
||||
{
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
return 0;
|
||||
impl.flags_ |= implementation_type::internal_non_blocking;
|
||||
}
|
||||
}
|
||||
|
||||
// Receive some data.
|
||||
for (;;)
|
||||
{
|
||||
@ -1147,12 +1153,15 @@ public:
|
||||
// Make socket non-blocking.
|
||||
if (!(impl.flags_ & implementation_type::internal_non_blocking))
|
||||
{
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
if (!(impl.flags_ & implementation_type::non_blocking))
|
||||
{
|
||||
this->get_io_service().post(bind_handler(handler, ec, 0));
|
||||
return;
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
{
|
||||
this->get_io_service().post(bind_handler(handler, ec, 0));
|
||||
return;
|
||||
}
|
||||
}
|
||||
impl.flags_ |= implementation_type::internal_non_blocking;
|
||||
}
|
||||
@ -1224,18 +1233,6 @@ public:
|
||||
asio::buffer_size(buffer));
|
||||
}
|
||||
|
||||
// Make socket non-blocking if user wants non-blocking.
|
||||
if (impl.flags_ & implementation_type::user_set_non_blocking)
|
||||
{
|
||||
if (!(impl.flags_ & implementation_type::internal_non_blocking))
|
||||
{
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
return 0;
|
||||
impl.flags_ |= implementation_type::internal_non_blocking;
|
||||
}
|
||||
}
|
||||
|
||||
// Receive some data.
|
||||
for (;;)
|
||||
{
|
||||
@ -1384,12 +1381,15 @@ public:
|
||||
// Make socket non-blocking.
|
||||
if (!(impl.flags_ & implementation_type::internal_non_blocking))
|
||||
{
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
if (!(impl.flags_ & implementation_type::non_blocking))
|
||||
{
|
||||
this->get_io_service().post(bind_handler(handler, ec, 0));
|
||||
return;
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
{
|
||||
this->get_io_service().post(bind_handler(handler, ec, 0));
|
||||
return;
|
||||
}
|
||||
}
|
||||
impl.flags_ |= implementation_type::internal_non_blocking;
|
||||
}
|
||||
@ -1449,18 +1449,6 @@ public:
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Make socket non-blocking if user wants non-blocking.
|
||||
if (impl.flags_ & implementation_type::user_set_non_blocking)
|
||||
{
|
||||
if (!(impl.flags_ & implementation_type::internal_non_blocking))
|
||||
{
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
return ec;
|
||||
impl.flags_ |= implementation_type::internal_non_blocking;
|
||||
}
|
||||
}
|
||||
|
||||
// Accept a socket.
|
||||
for (;;)
|
||||
{
|
||||
@ -1622,12 +1610,15 @@ public:
|
||||
// Make socket non-blocking.
|
||||
if (!(impl.flags_ & implementation_type::internal_non_blocking))
|
||||
{
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
if (!(impl.flags_ & implementation_type::non_blocking))
|
||||
{
|
||||
this->get_io_service().post(bind_handler(handler, ec));
|
||||
return;
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
{
|
||||
this->get_io_service().post(bind_handler(handler, ec));
|
||||
return;
|
||||
}
|
||||
}
|
||||
impl.flags_ |= implementation_type::internal_non_blocking;
|
||||
}
|
||||
@ -1651,18 +1642,30 @@ public:
|
||||
return ec;
|
||||
}
|
||||
|
||||
if (impl.flags_ & implementation_type::internal_non_blocking)
|
||||
{
|
||||
// Mark the socket as blocking while we perform the connect.
|
||||
ioctl_arg_type non_blocking = 0;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
return ec;
|
||||
impl.flags_ &= ~implementation_type::internal_non_blocking;
|
||||
}
|
||||
|
||||
// Perform the connect operation.
|
||||
socket_ops::connect(impl.socket_,
|
||||
peer_endpoint.data(), peer_endpoint.size(), ec);
|
||||
if (ec != asio::error::in_progress
|
||||
&& ec != asio::error::would_block)
|
||||
{
|
||||
// The connect operation finished immediately.
|
||||
return ec;
|
||||
}
|
||||
|
||||
// Wait for socket to become ready.
|
||||
if (socket_ops::poll_connect(impl.socket_, ec) < 0)
|
||||
return ec;
|
||||
|
||||
// Get the error code from the connect operation.
|
||||
int connect_error = 0;
|
||||
size_t connect_error_len = sizeof(connect_error);
|
||||
if (socket_ops::getsockopt(impl.socket_, SOL_SOCKET, SO_ERROR,
|
||||
&connect_error, &connect_error_len, ec) == socket_error_retval)
|
||||
return ec;
|
||||
|
||||
// Return the result of the connect operation.
|
||||
ec = asio::error_code(connect_error,
|
||||
asio::error::get_system_category());
|
||||
return ec;
|
||||
}
|
||||
|
||||
@ -1730,12 +1733,15 @@ public:
|
||||
// Make socket non-blocking.
|
||||
if (!(impl.flags_ & implementation_type::internal_non_blocking))
|
||||
{
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
if (!(impl.flags_ & implementation_type::non_blocking))
|
||||
{
|
||||
this->get_io_service().post(bind_handler(handler, ec));
|
||||
return;
|
||||
ioctl_arg_type non_blocking = 1;
|
||||
asio::error_code ec;
|
||||
if (socket_ops::ioctl(impl.socket_, FIONBIO, &non_blocking, ec))
|
||||
{
|
||||
this->get_io_service().post(bind_handler(handler, ec));
|
||||
return;
|
||||
}
|
||||
}
|
||||
impl.flags_ |= implementation_type::internal_non_blocking;
|
||||
}
|
||||
|
@ -329,7 +329,7 @@ private:
|
||||
void start_work_thread()
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
if (work_thread_ == 0)
|
||||
if (!work_thread_)
|
||||
{
|
||||
work_thread_.reset(new asio::detail::thread(
|
||||
work_io_service_runner(*work_io_service_)));
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <boost/config.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#include "asio/detail/eventfd_select_interrupter.hpp"
|
||||
#include "asio/detail/pipe_select_interrupter.hpp"
|
||||
#include "asio/detail/socket_select_interrupter.hpp"
|
||||
|
||||
@ -29,6 +30,8 @@ namespace detail {
|
||||
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
typedef socket_select_interrupter select_interrupter;
|
||||
#elif defined(ASIO_HAS_EVENTFD)
|
||||
typedef eventfd_select_interrupter select_interrupter;
|
||||
#else
|
||||
typedef pipe_select_interrupter select_interrupter;
|
||||
#endif
|
||||
|
@ -110,6 +110,16 @@ public:
|
||||
timer_queues_.clear();
|
||||
}
|
||||
|
||||
// Initialise the task, but only if the reactor is not in its own thread.
|
||||
void init_task()
|
||||
{
|
||||
if (!Own_Thread)
|
||||
{
|
||||
typedef task_io_service<select_reactor<Own_Thread> > task_io_service_type;
|
||||
use_service<task_io_service_type>(this->get_io_service()).init_task();
|
||||
}
|
||||
}
|
||||
|
||||
// Register a socket with the reactor. Returns 0 on success, system error
|
||||
// code on failure.
|
||||
int register_descriptor(socket_type, per_descriptor_data&)
|
||||
|
@ -36,6 +36,21 @@
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
|
||||
# pragma GCC visibility push (default)
|
||||
# endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
|
||||
#endif // defined(__GNUC__)
|
||||
|
||||
template <typename T>
|
||||
class typeid_wrapper {};
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
|
||||
# pragma GCC visibility pop
|
||||
# endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
|
||||
#endif // defined(__GNUC__)
|
||||
|
||||
class service_registry
|
||||
: private noncopyable
|
||||
{
|
||||
@ -168,7 +183,7 @@ private:
|
||||
void init_service_id(asio::io_service::service& service,
|
||||
const asio::detail::service_id<Service>& /*id*/)
|
||||
{
|
||||
service.type_info_ = &typeid(Service);
|
||||
service.type_info_ = &typeid(typeid_wrapper<Service>);
|
||||
service.id_ = 0;
|
||||
}
|
||||
#endif // !defined(ASIO_NO_TYPEID)
|
||||
@ -188,7 +203,8 @@ private:
|
||||
const asio::io_service::service& service,
|
||||
const asio::detail::service_id<Service>& /*id*/)
|
||||
{
|
||||
return service.type_info_ != 0 && *service.type_info_ == typeid(Service);
|
||||
return service.type_info_ != 0
|
||||
&& *service.type_info_ == typeid(typeid_wrapper<Service>);
|
||||
}
|
||||
#endif // !defined(ASIO_NO_TYPEID)
|
||||
|
||||
|
@ -102,7 +102,7 @@ inline socket_type accept(socket_type s, socket_addr_type* addr,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
#if defined(BOOST_WINDOWS)
|
||||
clear_error(ec);
|
||||
#endif
|
||||
|
||||
@ -122,7 +122,7 @@ inline int bind(socket_type s, const socket_addr_type* addr,
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(call_bind(
|
||||
&msghdr::msg_namelen, s, addr, addrlen), ec);
|
||||
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
#if defined(BOOST_WINDOWS)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
#endif
|
||||
@ -134,10 +134,8 @@ inline int close(socket_type s, asio::error_code& ec)
|
||||
clear_error(ec);
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
int result = error_wrapper(::closesocket(s), ec);
|
||||
# if defined(UNDER_CE)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return result;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
return error_wrapper(::close(s), ec);
|
||||
@ -148,7 +146,7 @@ inline int shutdown(socket_type s, int what, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(::shutdown(s, what), ec);
|
||||
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
#if defined(BOOST_WINDOWS)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
#endif
|
||||
@ -168,7 +166,7 @@ inline int connect(socket_type s, const socket_addr_type* addr,
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(call_connect(
|
||||
&msghdr::msg_namelen, s, addr, addrlen), ec);
|
||||
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
#if defined(BOOST_WINDOWS)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
#endif
|
||||
@ -195,13 +193,24 @@ inline int listen(socket_type s, int backlog, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(::listen(s, backlog), ec);
|
||||
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
#if defined(BOOST_WINDOWS)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void init_buf_iov_base(void*& base, void* addr)
|
||||
{
|
||||
base = addr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void init_buf_iov_base(T& base, void* addr)
|
||||
{
|
||||
base = static_cast<T>(addr);
|
||||
}
|
||||
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
typedef WSABUF buf;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
@ -214,7 +223,7 @@ inline void init_buf(buf& b, void* data, size_t size)
|
||||
b.buf = static_cast<char*>(data);
|
||||
b.len = static_cast<u_long>(size);
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
b.iov_base = data;
|
||||
init_buf_iov_base(b.iov_base, data);
|
||||
b.iov_len = size;
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
}
|
||||
@ -225,7 +234,7 @@ inline void init_buf(buf& b, const void* data, size_t size)
|
||||
b.buf = static_cast<char*>(const_cast<void*>(data));
|
||||
b.len = static_cast<u_long>(size);
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
b.iov_base = const_cast<void*>(data);
|
||||
init_buf_iov_base(b.iov_base, const_cast<void*>(data));
|
||||
b.iov_len = size;
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
}
|
||||
@ -265,9 +274,7 @@ inline int recv(socket_type s, buf* bufs, size_t count, int flags,
|
||||
recv_buf_count, &bytes_transferred, &recv_flags, 0, 0), ec);
|
||||
if (result != 0)
|
||||
return -1;
|
||||
# if defined(UNDER_CE)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return bytes_transferred;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
msghdr msg = msghdr();
|
||||
@ -293,9 +300,7 @@ inline int recvfrom(socket_type s, buf* bufs, size_t count, int flags,
|
||||
*addrlen = (std::size_t)tmp_addrlen;
|
||||
if (result != 0)
|
||||
return -1;
|
||||
# if defined(UNDER_CE)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return bytes_transferred;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
msghdr msg = msghdr();
|
||||
@ -322,9 +327,7 @@ inline int send(socket_type s, const buf* bufs, size_t count, int flags,
|
||||
send_buf_count, &bytes_transferred, send_flags, 0, 0), ec);
|
||||
if (result != 0)
|
||||
return -1;
|
||||
# if defined(UNDER_CE)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return bytes_transferred;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
msghdr msg = msghdr();
|
||||
@ -351,9 +354,7 @@ inline int sendto(socket_type s, const buf* bufs, size_t count, int flags,
|
||||
static_cast<int>(addrlen), 0, 0), ec);
|
||||
if (result != 0)
|
||||
return -1;
|
||||
# if defined(UNDER_CE)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return bytes_transferred;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
msghdr msg = msghdr();
|
||||
@ -388,9 +389,7 @@ inline socket_type socket(int af, int type, int protocol,
|
||||
reinterpret_cast<const char*>(&optval), sizeof(optval));
|
||||
}
|
||||
|
||||
# if defined(UNDER_CE)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
|
||||
return s;
|
||||
#elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
|
||||
@ -452,7 +451,7 @@ inline int setsockopt(socket_type s, int level, int optname,
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(call_setsockopt(&msghdr::msg_namelen,
|
||||
s, level, optname, optval, optlen), ec);
|
||||
# if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
# if defined(BOOST_WINDOWS)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
@ -525,10 +524,8 @@ inline int getsockopt(socket_type s, int level, int optname, void* optval,
|
||||
*static_cast<DWORD*>(optval) = 1;
|
||||
clear_error(ec);
|
||||
}
|
||||
# if defined(UNDER_CE)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return result;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
clear_error(ec);
|
||||
@ -566,7 +563,7 @@ inline int getpeername(socket_type s, socket_addr_type* addr,
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(call_getpeername(
|
||||
&msghdr::msg_namelen, s, addr, addrlen), ec);
|
||||
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
#if defined(BOOST_WINDOWS)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
#endif
|
||||
@ -589,7 +586,7 @@ inline int getsockname(socket_type s, socket_addr_type* addr,
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(call_getsockname(
|
||||
&msghdr::msg_namelen, s, addr, addrlen), ec);
|
||||
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
#if defined(BOOST_WINDOWS)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
#endif
|
||||
@ -602,10 +599,8 @@ inline int ioctl(socket_type s, long cmd, ioctl_arg_type* arg,
|
||||
clear_error(ec);
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
int result = error_wrapper(::ioctlsocket(s, cmd, arg), ec);
|
||||
# if defined(UNDER_CE)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return result;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
return error_wrapper(::ioctl(s, cmd, arg), ec);
|
||||
@ -647,7 +642,7 @@ inline int select(int nfds, fd_set* readfds, fd_set* writefds,
|
||||
#else
|
||||
int result = error_wrapper(::select(nfds, readfds,
|
||||
writefds, exceptfds, timeout), ec);
|
||||
# if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
# if defined(BOOST_WINDOWS)
|
||||
if (result >= 0)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
@ -663,10 +658,8 @@ inline int poll_read(socket_type s, asio::error_code& ec)
|
||||
FD_SET(s, &fds);
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(::select(s, &fds, 0, 0, 0), ec);
|
||||
# if defined(UNDER_CE)
|
||||
if (result >= 0)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return result;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
pollfd fds;
|
||||
@ -686,10 +679,32 @@ inline int poll_write(socket_type s, asio::error_code& ec)
|
||||
FD_SET(s, &fds);
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(::select(s, 0, &fds, 0, 0), ec);
|
||||
# if defined(UNDER_CE)
|
||||
if (result >= 0)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
return result;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
pollfd fds;
|
||||
fds.fd = s;
|
||||
fds.events = POLLOUT;
|
||||
fds.revents = 0;
|
||||
clear_error(ec);
|
||||
return error_wrapper(::poll(&fds, 1, -1), ec);
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
}
|
||||
|
||||
inline int poll_connect(socket_type s, asio::error_code& ec)
|
||||
{
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
FD_SET write_fds;
|
||||
FD_ZERO(&write_fds);
|
||||
FD_SET(s, &write_fds);
|
||||
FD_SET except_fds;
|
||||
FD_ZERO(&except_fds);
|
||||
FD_SET(s, &except_fds);
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(::select(s, 0, &write_fds, &except_fds, 0), ec);
|
||||
if (result >= 0)
|
||||
clear_error(ec);
|
||||
return result;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
pollfd fds;
|
||||
@ -837,10 +852,8 @@ inline int inet_pton(int af, const char* src, void* dest,
|
||||
if (result == socket_error_retval && !ec)
|
||||
ec = asio::error::invalid_argument;
|
||||
|
||||
#if defined(UNDER_CE)
|
||||
if (result != socket_error_retval)
|
||||
clear_error(ec);
|
||||
#endif
|
||||
|
||||
return result == socket_error_retval ? -1 : 1;
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
@ -869,7 +882,7 @@ inline int gethostname(char* name, int namelen, asio::error_code& ec)
|
||||
{
|
||||
clear_error(ec);
|
||||
int result = error_wrapper(::gethostname(name, namelen), ec);
|
||||
#if defined(BOOST_WINDOWS) && defined(UNDER_CE)
|
||||
#if defined(BOOST_WINDOWS)
|
||||
if (result == 0)
|
||||
clear_error(ec);
|
||||
#endif
|
||||
@ -912,9 +925,7 @@ inline hostent* gethostbyaddr(const char* addr, int length, int af,
|
||||
hostent* retval = error_wrapper(::gethostbyaddr(addr, length, af), ec);
|
||||
if (!retval)
|
||||
return 0;
|
||||
# if defined(UNDER_CE)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
*result = *retval;
|
||||
return retval;
|
||||
#elif defined(__sun) || defined(__QNX__)
|
||||
@ -963,9 +974,7 @@ inline hostent* gethostbyname(const char* name, int af, struct hostent* result,
|
||||
hostent* retval = error_wrapper(::gethostbyname(name), ec);
|
||||
if (!retval)
|
||||
return 0;
|
||||
# if defined(UNDER_CE)
|
||||
clear_error(ec);
|
||||
# endif
|
||||
*result = *retval;
|
||||
return result;
|
||||
#elif defined(__sun) || defined(__QNX__)
|
||||
|
@ -28,11 +28,15 @@
|
||||
# endif // defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)
|
||||
# if !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
|
||||
# if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
# pragma message("Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately")
|
||||
# pragma message("Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target)")
|
||||
# pragma message( \
|
||||
"Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:\n"\
|
||||
"- add -D_WIN32_WINNT=0x0501 to the compiler command line; or\n"\
|
||||
"- add _WIN32_WINNT=0x0501 to your project's Preprocessor Definitions.\n"\
|
||||
"Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target).")
|
||||
# else // defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
# warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately
|
||||
# warning Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target)
|
||||
# warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately.
|
||||
# warning For example, add -D_WIN32_WINNT=0x0501 to the compiler command line.
|
||||
# warning Assuming _WIN32_WINNT=0x0501 (i.e. Windows XP target).
|
||||
# endif // defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
# define _WIN32_WINNT 0x0501
|
||||
# endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)
|
||||
@ -187,7 +191,12 @@ 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;
|
||||
# if defined(IOV_MAX)
|
||||
const int max_iov_len = IOV_MAX;
|
||||
# else
|
||||
// POSIX platforms are not required to define IOV_MAX.
|
||||
const int max_iov_len = 16;
|
||||
# endif
|
||||
#endif
|
||||
const int custom_socket_option_level = 0xA5100000;
|
||||
const int enable_connection_aborted_option = 1;
|
||||
|
@ -44,14 +44,13 @@ public:
|
||||
task_io_service(asio::io_service& io_service)
|
||||
: asio::detail::service_base<task_io_service<Task> >(io_service),
|
||||
mutex_(),
|
||||
task_(use_service<Task>(io_service)),
|
||||
task_(0),
|
||||
task_interrupted_(true),
|
||||
outstanding_work_(0),
|
||||
stopped_(false),
|
||||
shutdown_(false),
|
||||
first_idle_thread_(0)
|
||||
{
|
||||
handler_queue_.push(&task_handler_);
|
||||
}
|
||||
|
||||
void init(size_t /*concurrency_hint*/)
|
||||
@ -74,8 +73,20 @@ public:
|
||||
h->destroy();
|
||||
}
|
||||
|
||||
// Reset handler queue to initial state.
|
||||
handler_queue_.push(&task_handler_);
|
||||
// Reset to initial state.
|
||||
task_ = 0;
|
||||
}
|
||||
|
||||
// Initialise the task, if required.
|
||||
void init_task()
|
||||
{
|
||||
asio::detail::mutex::scoped_lock lock(mutex_);
|
||||
if (!shutdown_ && !task_)
|
||||
{
|
||||
task_ = &use_service<Task>(this->get_io_service());
|
||||
handler_queue_.push(&task_handler_);
|
||||
interrupt_one_idle_thread(lock);
|
||||
}
|
||||
}
|
||||
|
||||
// Run the event loop until interrupted or no more work.
|
||||
@ -194,10 +205,10 @@ public:
|
||||
// Wake up a thread to execute the handler.
|
||||
if (!interrupt_one_idle_thread(lock))
|
||||
{
|
||||
if (!task_interrupted_)
|
||||
if (!task_interrupted_ && task_)
|
||||
{
|
||||
task_interrupted_ = true;
|
||||
task_.interrupt();
|
||||
task_->interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -246,7 +257,7 @@ private:
|
||||
// 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);
|
||||
task_->run(!more_handlers && !polling);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -285,10 +296,10 @@ private:
|
||||
{
|
||||
stopped_ = true;
|
||||
interrupt_all_idle_threads(lock);
|
||||
if (!task_interrupted_)
|
||||
if (!task_interrupted_ && task_)
|
||||
{
|
||||
task_interrupted_ = true;
|
||||
task_.interrupt();
|
||||
task_->interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,7 +387,7 @@ private:
|
||||
asio::detail::mutex mutex_;
|
||||
|
||||
// The task to be run by this service.
|
||||
Task& task_;
|
||||
Task* task_;
|
||||
|
||||
// Handler object to represent the position of the task in the queue.
|
||||
class task_handler
|
||||
|
@ -49,7 +49,7 @@ public:
|
||||
: asio::detail::service_base<task_io_service<Task> >(io_service),
|
||||
front_mutex_(),
|
||||
back_mutex_(),
|
||||
task_(use_service<Task>(io_service)),
|
||||
task_(&use_service<Task>(io_service)),
|
||||
outstanding_work_(0),
|
||||
front_stopped_(false),
|
||||
back_stopped_(false),
|
||||
@ -57,7 +57,6 @@ public:
|
||||
back_first_idle_thread_(0),
|
||||
back_task_thread_(0)
|
||||
{
|
||||
handler_queue_.push(&task_handler_);
|
||||
}
|
||||
|
||||
void init(size_t /*concurrency_hint*/)
|
||||
@ -76,8 +75,20 @@ public:
|
||||
if (h != &task_handler_)
|
||||
h->destroy();
|
||||
|
||||
// Reset handler queue to initial state.
|
||||
handler_queue_.push(&task_handler_);
|
||||
// Reset to initial state.
|
||||
task_ = 0;
|
||||
}
|
||||
|
||||
// Initialise the task, if required.
|
||||
void init_task()
|
||||
{
|
||||
asio::detail::mutex::scoped_lock back_lock(back_mutex_);
|
||||
if (!back_shutdown_ && !task_)
|
||||
{
|
||||
task_ = &use_service<Task>(this->get_io_service());
|
||||
handler_queue_.push(&task_handler_);
|
||||
interrupt_one_idle_thread(back_lock);
|
||||
}
|
||||
}
|
||||
|
||||
// Run the event loop until interrupted or no more work.
|
||||
@ -286,7 +297,7 @@ private:
|
||||
// queue is empty and we're not polling, otherwise we want to return
|
||||
// as soon as possible.
|
||||
task_has_run = true;
|
||||
task_.run(!more_handlers && !polling);
|
||||
task_->run(!more_handlers && !polling);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -341,10 +352,10 @@ private:
|
||||
idle_thread->next = 0;
|
||||
idle_thread->wakeup_event.signal(back_lock);
|
||||
}
|
||||
else if (back_task_thread_)
|
||||
else if (back_task_thread_ && task_)
|
||||
{
|
||||
back_task_thread_ = 0;
|
||||
task_.interrupt();
|
||||
task_->interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
@ -360,10 +371,10 @@ private:
|
||||
idle_thread->wakeup_event.signal(back_lock);
|
||||
}
|
||||
|
||||
if (back_task_thread_)
|
||||
if (back_task_thread_ && task_)
|
||||
{
|
||||
back_task_thread_ = 0;
|
||||
task_.interrupt();
|
||||
task_->interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
@ -414,7 +425,7 @@ private:
|
||||
asio::detail::mutex back_mutex_;
|
||||
|
||||
// The task to be run by this service.
|
||||
Task& task_;
|
||||
Task* task_;
|
||||
|
||||
// Handler object to represent the position of the task in the queue.
|
||||
class task_handler
|
||||
|
@ -148,6 +148,11 @@ public:
|
||||
timer_queues_.clear();
|
||||
}
|
||||
|
||||
// Initialise the task. Nothing to do here.
|
||||
void init_task()
|
||||
{
|
||||
}
|
||||
|
||||
// Register a handle with the IO completion port.
|
||||
asio::error_code register_handle(
|
||||
HANDLE handle, asio::error_code& ec)
|
||||
@ -530,7 +535,7 @@ private:
|
||||
// Wake up next thread that is blocked on GetQueuedCompletionStatus.
|
||||
if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
last_error = ::GetLastError();
|
||||
ec = asio::error_code(last_error,
|
||||
asio::error::get_system_category());
|
||||
return 0;
|
||||
|
@ -36,6 +36,7 @@ namespace asio {
|
||||
namespace detail {
|
||||
|
||||
class win_iocp_io_service;
|
||||
class win_iocp_overlapped_ptr;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
@ -39,45 +39,67 @@ namespace detail {
|
||||
|
||||
unsigned int __stdcall win_thread_function(void* arg);
|
||||
|
||||
class win_thread
|
||||
: private noncopyable
|
||||
#if (WINVER < 0x0500)
|
||||
void __stdcall apc_function(ULONG data);
|
||||
#else
|
||||
void __stdcall apc_function(ULONG_PTR data);
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
class win_thread_base
|
||||
{
|
||||
public:
|
||||
// The purpose of the thread.
|
||||
enum purpose { internal, external };
|
||||
static bool terminate_threads()
|
||||
{
|
||||
return ::InterlockedExchangeAdd(&terminate_threads_, 0) != 0;
|
||||
}
|
||||
|
||||
static void set_terminate_threads(bool b)
|
||||
{
|
||||
::InterlockedExchange(&terminate_threads_, b ? 1 : 0);
|
||||
}
|
||||
|
||||
private:
|
||||
static long terminate_threads_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
long win_thread_base<T>::terminate_threads_ = 0;
|
||||
|
||||
class win_thread
|
||||
: private noncopyable,
|
||||
public win_thread_base<win_thread>
|
||||
{
|
||||
public:
|
||||
// Constructor.
|
||||
template <typename Function>
|
||||
win_thread(Function f, purpose p = internal)
|
||||
win_thread(Function f)
|
||||
: exit_event_(0)
|
||||
{
|
||||
std::auto_ptr<func_base> arg(new func<Function>(f));
|
||||
|
||||
::HANDLE entry_event = 0;
|
||||
if (p == internal)
|
||||
arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0);
|
||||
if (!entry_event)
|
||||
{
|
||||
arg->entry_event_ = entry_event = ::CreateEvent(0, true, false, 0);
|
||||
if (!entry_event)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
asio::system_error e(
|
||||
asio::error_code(last_error,
|
||||
asio::error::get_system_category()),
|
||||
"thread.entry_event");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
DWORD last_error = ::GetLastError();
|
||||
asio::system_error e(
|
||||
asio::error_code(last_error,
|
||||
asio::error::get_system_category()),
|
||||
"thread.entry_event");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
||||
arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0);
|
||||
if (!exit_event_)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
::CloseHandle(entry_event);
|
||||
asio::system_error e(
|
||||
asio::error_code(last_error,
|
||||
asio::error::get_system_category()),
|
||||
"thread.exit_event");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
arg->exit_event_ = exit_event_ = ::CreateEvent(0, true, false, 0);
|
||||
if (!exit_event_)
|
||||
{
|
||||
DWORD last_error = ::GetLastError();
|
||||
::CloseHandle(entry_event);
|
||||
asio::system_error e(
|
||||
asio::error_code(last_error,
|
||||
asio::error::get_system_category()),
|
||||
"thread.exit_event");
|
||||
boost::throw_exception(e);
|
||||
}
|
||||
|
||||
unsigned int thread_id = 0;
|
||||
@ -117,14 +139,15 @@ public:
|
||||
// Wait for the thread to exit.
|
||||
void join()
|
||||
{
|
||||
if (exit_event_)
|
||||
::WaitForSingleObject(exit_event_, INFINITE);
|
||||
::CloseHandle(exit_event_);
|
||||
if (terminate_threads())
|
||||
{
|
||||
::WaitForSingleObject(exit_event_, INFINITE);
|
||||
::CloseHandle(exit_event_);
|
||||
::TerminateThread(thread_, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
::QueueUserAPC(apc_function, thread_, 0);
|
||||
::WaitForSingleObject(thread_, INFINITE);
|
||||
}
|
||||
}
|
||||
@ -132,6 +155,12 @@ public:
|
||||
private:
|
||||
friend unsigned int __stdcall win_thread_function(void* arg);
|
||||
|
||||
#if (WINVER < 0x0500)
|
||||
friend void __stdcall apc_function(ULONG);
|
||||
#else
|
||||
friend void __stdcall apc_function(ULONG_PTR);
|
||||
#endif
|
||||
|
||||
class func_base
|
||||
{
|
||||
public:
|
||||
@ -169,21 +198,30 @@ inline unsigned int __stdcall win_thread_function(void* arg)
|
||||
std::auto_ptr<win_thread::func_base> func(
|
||||
static_cast<win_thread::func_base*>(arg));
|
||||
|
||||
if (func->entry_event_)
|
||||
::SetEvent(func->entry_event_);
|
||||
::SetEvent(func->entry_event_);
|
||||
|
||||
func->run();
|
||||
|
||||
if (HANDLE exit_event = func->exit_event_)
|
||||
{
|
||||
func.reset();
|
||||
::SetEvent(exit_event);
|
||||
::Sleep(INFINITE);
|
||||
}
|
||||
// Signal that the thread has finished its work, but rather than returning go
|
||||
// to sleep to put the thread into a well known state. If the thread is being
|
||||
// joined during global object destruction then it may be killed using
|
||||
// TerminateThread (to avoid a deadlock in DllMain). Otherwise, the SleepEx
|
||||
// call will be interrupted using QueueUserAPC and the thread will shut down
|
||||
// cleanly.
|
||||
HANDLE exit_event = func->exit_event_;
|
||||
func.reset();
|
||||
::SetEvent(exit_event);
|
||||
::SleepEx(INFINITE, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (WINVER < 0x0500)
|
||||
inline void __stdcall apc_function(ULONG) {}
|
||||
#else
|
||||
inline void __stdcall apc_function(ULONG_PTR) {}
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
|
@ -42,12 +42,9 @@ class wince_thread
|
||||
: private noncopyable
|
||||
{
|
||||
public:
|
||||
// The purpose of the thread.
|
||||
enum purpose { internal, external };
|
||||
|
||||
// Constructor.
|
||||
template <typename Function>
|
||||
wince_thread(Function f, purpose = internal)
|
||||
wince_thread(Function f)
|
||||
{
|
||||
std::auto_ptr<func_base> arg(new func<Function>(f));
|
||||
DWORD thread_id = 0;
|
||||
|
@ -83,6 +83,7 @@ inline std::string error_code::message() const
|
||||
if (category() != error::get_system_category())
|
||||
return "asio error";
|
||||
#if defined(__sun) || defined(__QNX__)
|
||||
using namespace std;
|
||||
return strerror(value_);
|
||||
#elif defined(__MACH__) && defined(__APPLE__) \
|
||||
|| defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) \
|
||||
|
@ -37,18 +37,20 @@ template <typename SyncReadStream, typename MutableBufferSequence,
|
||||
std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
|
||||
CompletionCondition completion_condition, asio::error_code& ec)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
asio::detail::consuming_buffers<
|
||||
mutable_buffer, MutableBufferSequence> tmp(buffers);
|
||||
std::size_t total_transferred = 0;
|
||||
tmp.set_max_size(detail::adapt_completion_condition_result(
|
||||
completion_condition(ec, total_transferred)));
|
||||
while (tmp.begin() != tmp.end())
|
||||
{
|
||||
std::size_t bytes_transferred = s.read_some(tmp, ec);
|
||||
tmp.consume(bytes_transferred);
|
||||
total_transferred += bytes_transferred;
|
||||
if (completion_condition(ec, total_transferred))
|
||||
return total_transferred;
|
||||
tmp.set_max_size(detail::adapt_completion_condition_result(
|
||||
completion_condition(ec, total_transferred)));
|
||||
}
|
||||
ec = asio::error_code();
|
||||
return total_transferred;
|
||||
}
|
||||
|
||||
@ -78,18 +80,23 @@ std::size_t read(SyncReadStream& s,
|
||||
asio::basic_streambuf<Allocator>& b,
|
||||
CompletionCondition completion_condition, asio::error_code& ec)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
std::size_t total_transferred = 0;
|
||||
for (;;)
|
||||
std::size_t max_size = detail::adapt_completion_condition_result(
|
||||
completion_condition(ec, total_transferred));
|
||||
std::size_t bytes_available = std::min<std::size_t>(512,
|
||||
std::min<std::size_t>(max_size, b.max_size() - b.size()));
|
||||
while (bytes_available > 0)
|
||||
{
|
||||
std::size_t bytes_available =
|
||||
std::min<std::size_t>(512, b.max_size() - b.size());
|
||||
std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
|
||||
b.commit(bytes_transferred);
|
||||
total_transferred += bytes_transferred;
|
||||
if (b.size() == b.max_size()
|
||||
|| completion_condition(ec, total_transferred))
|
||||
return total_transferred;
|
||||
max_size = detail::adapt_completion_condition_result(
|
||||
completion_condition(ec, total_transferred));
|
||||
bytes_available = std::min<std::size_t>(512,
|
||||
std::min<std::size_t>(max_size, b.max_size() - b.size()));
|
||||
}
|
||||
return total_transferred;
|
||||
}
|
||||
|
||||
template <typename SyncReadStream, typename Allocator>
|
||||
@ -139,8 +146,9 @@ namespace detail
|
||||
{
|
||||
total_transferred_ += bytes_transferred;
|
||||
buffers_.consume(bytes_transferred);
|
||||
if (completion_condition_(ec, total_transferred_)
|
||||
|| buffers_.begin() == buffers_.end())
|
||||
buffers_.set_max_size(detail::adapt_completion_condition_result(
|
||||
completion_condition_(ec, total_transferred_)));
|
||||
if (buffers_.begin() == buffers_.end())
|
||||
{
|
||||
handler_(ec, total_transferred_);
|
||||
}
|
||||
@ -197,6 +205,18 @@ inline void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
|
||||
{
|
||||
asio::detail::consuming_buffers<
|
||||
mutable_buffer, MutableBufferSequence> tmp(buffers);
|
||||
|
||||
asio::error_code ec;
|
||||
std::size_t total_transferred = 0;
|
||||
tmp.set_max_size(detail::adapt_completion_condition_result(
|
||||
completion_condition(ec, total_transferred)));
|
||||
if (tmp.begin() == tmp.end())
|
||||
{
|
||||
s.get_io_service().post(detail::bind_handler(
|
||||
handler, ec, total_transferred));
|
||||
return;
|
||||
}
|
||||
|
||||
s.async_read_some(tmp,
|
||||
detail::read_handler<AsyncReadStream, MutableBufferSequence,
|
||||
CompletionCondition, ReadHandler>(
|
||||
@ -234,15 +254,17 @@ namespace detail
|
||||
{
|
||||
total_transferred_ += bytes_transferred;
|
||||
streambuf_.commit(bytes_transferred);
|
||||
if (streambuf_.size() == streambuf_.max_size()
|
||||
|| completion_condition_(ec, total_transferred_))
|
||||
std::size_t max_size = detail::adapt_completion_condition_result(
|
||||
completion_condition_(ec, total_transferred_));
|
||||
std::size_t bytes_available = std::min<std::size_t>(512,
|
||||
std::min<std::size_t>(max_size,
|
||||
streambuf_.max_size() - streambuf_.size()));
|
||||
if (bytes_available == 0)
|
||||
{
|
||||
handler_(ec, total_transferred_);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::size_t bytes_available =
|
||||
std::min<std::size_t>(512, streambuf_.max_size() - streambuf_.size());
|
||||
stream_.async_read_some(streambuf_.prepare(bytes_available), *this);
|
||||
}
|
||||
}
|
||||
@ -292,8 +314,19 @@ inline void async_read(AsyncReadStream& s,
|
||||
asio::basic_streambuf<Allocator>& b,
|
||||
CompletionCondition completion_condition, ReadHandler handler)
|
||||
{
|
||||
std::size_t bytes_available =
|
||||
std::min<std::size_t>(512, b.max_size() - b.size());
|
||||
asio::error_code ec;
|
||||
std::size_t total_transferred = 0;
|
||||
std::size_t max_size = detail::adapt_completion_condition_result(
|
||||
completion_condition(ec, total_transferred));
|
||||
std::size_t bytes_available = std::min<std::size_t>(512,
|
||||
std::min<std::size_t>(max_size, b.max_size() - b.size()));
|
||||
if (bytes_available == 0)
|
||||
{
|
||||
s.get_io_service().post(detail::bind_handler(
|
||||
handler, ec, total_transferred));
|
||||
return;
|
||||
}
|
||||
|
||||
s.async_read_some(b.prepare(bytes_available),
|
||||
detail::read_streambuf_handler<AsyncReadStream, Allocator,
|
||||
CompletionCondition, ReadHandler>(
|
||||
|
@ -38,19 +38,21 @@ std::size_t read_at(SyncRandomAccessReadDevice& d,
|
||||
boost::uint64_t offset, const MutableBufferSequence& buffers,
|
||||
CompletionCondition completion_condition, asio::error_code& ec)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
asio::detail::consuming_buffers<
|
||||
mutable_buffer, MutableBufferSequence> tmp(buffers);
|
||||
std::size_t total_transferred = 0;
|
||||
tmp.set_max_size(detail::adapt_completion_condition_result(
|
||||
completion_condition(ec, total_transferred)));
|
||||
while (tmp.begin() != tmp.end())
|
||||
{
|
||||
std::size_t bytes_transferred = d.read_some_at(
|
||||
offset + total_transferred, tmp, ec);
|
||||
tmp.consume(bytes_transferred);
|
||||
total_transferred += bytes_transferred;
|
||||
if (completion_condition(ec, total_transferred))
|
||||
return total_transferred;
|
||||
tmp.set_max_size(detail::adapt_completion_condition_result(
|
||||
completion_condition(ec, total_transferred)));
|
||||
}
|
||||
ec = asio::error_code();
|
||||
return total_transferred;
|
||||
}
|
||||
|
||||
@ -151,8 +153,9 @@ namespace detail
|
||||
{
|
||||
total_transferred_ += bytes_transferred;
|
||||
buffers_.consume(bytes_transferred);
|
||||
if (completion_condition_(ec, total_transferred_)
|
||||
|| buffers_.begin() == buffers_.end())
|
||||
buffers_.set_max_size(detail::adapt_completion_condition_result(
|
||||
completion_condition_(ec, total_transferred_)));
|
||||
if (buffers_.begin() == buffers_.end())
|
||||
{
|
||||
handler_(ec, total_transferred_);
|
||||
}
|
||||
@ -214,6 +217,18 @@ inline void async_read_at(AsyncRandomAccessReadDevice& d,
|
||||
{
|
||||
asio::detail::consuming_buffers<
|
||||
mutable_buffer, MutableBufferSequence> tmp(buffers);
|
||||
|
||||
asio::error_code ec;
|
||||
std::size_t total_transferred = 0;
|
||||
tmp.set_max_size(detail::adapt_completion_condition_result(
|
||||
completion_condition(ec, total_transferred)));
|
||||
if (tmp.begin() == tmp.end())
|
||||
{
|
||||
d.get_io_service().post(detail::bind_handler(
|
||||
handler, ec, total_transferred));
|
||||
return;
|
||||
}
|
||||
|
||||
d.async_read_some_at(offset, tmp,
|
||||
detail::read_at_handler<AsyncRandomAccessReadDevice,
|
||||
MutableBufferSequence, CompletionCondition, ReadHandler>(
|
||||
@ -253,15 +268,17 @@ namespace detail
|
||||
{
|
||||
total_transferred_ += bytes_transferred;
|
||||
streambuf_.commit(bytes_transferred);
|
||||
if (streambuf_.size() == streambuf_.max_size()
|
||||
|| completion_condition_(ec, total_transferred_))
|
||||
std::size_t max_size = detail::adapt_completion_condition_result(
|
||||
completion_condition_(ec, total_transferred_));
|
||||
std::size_t bytes_available = std::min<std::size_t>(512,
|
||||
std::min<std::size_t>(max_size,
|
||||
streambuf_.max_size() - streambuf_.size()));
|
||||
if (bytes_available == 0)
|
||||
{
|
||||
handler_(ec, total_transferred_);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::size_t bytes_available =
|
||||
std::min<std::size_t>(512, streambuf_.max_size() - streambuf_.size());
|
||||
stream_.async_read_some_at(offset_ + total_transferred_,
|
||||
streambuf_.prepare(bytes_available), *this);
|
||||
}
|
||||
@ -313,8 +330,19 @@ inline void async_read_at(AsyncRandomAccessReadDevice& d,
|
||||
boost::uint64_t offset, asio::basic_streambuf<Allocator>& b,
|
||||
CompletionCondition completion_condition, ReadHandler handler)
|
||||
{
|
||||
std::size_t bytes_available =
|
||||
std::min<std::size_t>(512, b.max_size() - b.size());
|
||||
asio::error_code ec;
|
||||
std::size_t total_transferred = 0;
|
||||
std::size_t max_size = detail::adapt_completion_condition_result(
|
||||
completion_condition(ec, total_transferred));
|
||||
std::size_t bytes_available = std::min<std::size_t>(512,
|
||||
std::min<std::size_t>(max_size, b.max_size() - b.size()));
|
||||
if (bytes_available == 0)
|
||||
{
|
||||
d.get_io_service().post(detail::bind_handler(
|
||||
handler, ec, total_transferred));
|
||||
return;
|
||||
}
|
||||
|
||||
d.async_read_some_at(offset, b.prepare(bytes_available),
|
||||
detail::read_at_streambuf_handler<AsyncRandomAccessReadDevice, Allocator,
|
||||
CompletionCondition, ReadHandler>(
|
||||
|
@ -277,19 +277,16 @@ std::size_t read_until(SyncReadStream& s,
|
||||
|
||||
// Look for a match.
|
||||
std::pair<iterator, bool> result = match_condition(start, end);
|
||||
if (result.first != end)
|
||||
if (result.second)
|
||||
{
|
||||
if (result.second)
|
||||
{
|
||||
// Full match. We're done.
|
||||
ec = asio::error_code();
|
||||
return result.first - begin;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Partial match. Next search needs to start from beginning of match.
|
||||
next_search_start = result.first - begin;
|
||||
}
|
||||
// Full match. We're done.
|
||||
ec = asio::error_code();
|
||||
return result.first - begin;
|
||||
}
|
||||
else if (result.first != end)
|
||||
{
|
||||
// Partial match. Next search needs to start from beginning of match.
|
||||
next_search_start = result.first - begin;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -448,7 +445,7 @@ void async_read_until(AsyncReadStream& s,
|
||||
// Found a match. We're done.
|
||||
asio::error_code ec;
|
||||
std::size_t bytes = iter - begin + 1;
|
||||
s.io_service().post(detail::bind_handler(handler, ec, bytes));
|
||||
s.get_io_service().post(detail::bind_handler(handler, ec, bytes));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -456,7 +453,7 @@ void async_read_until(AsyncReadStream& s,
|
||||
if (b.size() == b.max_size())
|
||||
{
|
||||
asio::error_code ec(error::not_found);
|
||||
s.io_service().post(detail::bind_handler(handler, ec, 0));
|
||||
s.get_io_service().post(detail::bind_handler(handler, ec, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -537,8 +534,8 @@ namespace detail
|
||||
if (streambuf_.size() == streambuf_.max_size())
|
||||
{
|
||||
std::size_t bytes = 0;
|
||||
asio::error_code ec(error::not_found);
|
||||
handler_(ec, bytes);
|
||||
asio::error_code ec2(error::not_found);
|
||||
handler_(ec2, bytes);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -609,7 +606,7 @@ void async_read_until(AsyncReadStream& s,
|
||||
// Full match. We're done.
|
||||
asio::error_code ec;
|
||||
std::size_t bytes = result.first - begin + delim.length();
|
||||
s.io_service().post(detail::bind_handler(handler, ec, bytes));
|
||||
s.get_io_service().post(detail::bind_handler(handler, ec, bytes));
|
||||
return;
|
||||
}
|
||||
else
|
||||
@ -628,7 +625,7 @@ void async_read_until(AsyncReadStream& s,
|
||||
if (b.size() == b.max_size())
|
||||
{
|
||||
asio::error_code ec(error::not_found);
|
||||
s.io_service().post(detail::bind_handler(handler, ec, 0));
|
||||
s.get_io_service().post(detail::bind_handler(handler, ec, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -782,7 +779,7 @@ void async_read_until(AsyncReadStream& s,
|
||||
// Full match. We're done.
|
||||
asio::error_code ec;
|
||||
std::size_t bytes = match_results[0].second - begin;
|
||||
s.io_service().post(detail::bind_handler(handler, ec, bytes));
|
||||
s.get_io_service().post(detail::bind_handler(handler, ec, bytes));
|
||||
return;
|
||||
}
|
||||
else
|
||||
@ -801,7 +798,7 @@ void async_read_until(AsyncReadStream& s,
|
||||
if (b.size() == b.max_size())
|
||||
{
|
||||
asio::error_code ec(error::not_found);
|
||||
s.io_service().post(detail::bind_handler(handler, ec, 0));
|
||||
s.get_io_service().post(detail::bind_handler(handler, ec, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -857,20 +854,17 @@ namespace detail
|
||||
|
||||
// Look for a match.
|
||||
std::pair<iterator, bool> result = match_condition_(start, end);
|
||||
if (result.first != end)
|
||||
if (result.second)
|
||||
{
|
||||
if (result.second)
|
||||
{
|
||||
// Full match. We're done.
|
||||
std::size_t bytes = result.first - begin;
|
||||
handler_(ec, bytes);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Partial match. Next search needs to start from beginning of match.
|
||||
next_search_start_ = result.first - begin;
|
||||
}
|
||||
// Full match. We're done.
|
||||
std::size_t bytes = result.first - begin;
|
||||
handler_(ec, bytes);
|
||||
return;
|
||||
}
|
||||
else if (result.first != end)
|
||||
{
|
||||
// Partial match. Next search needs to start from beginning of match.
|
||||
next_search_start_ = result.first - begin;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -950,21 +944,18 @@ void async_read_until(AsyncReadStream& s,
|
||||
// Look for a match.
|
||||
std::size_t next_search_start;
|
||||
std::pair<iterator, bool> result = match_condition(begin, end);
|
||||
if (result.first != end)
|
||||
if (result.second)
|
||||
{
|
||||
if (result.second)
|
||||
{
|
||||
// Full match. We're done.
|
||||
asio::error_code ec;
|
||||
std::size_t bytes = result.first - begin;
|
||||
s.io_service().post(detail::bind_handler(handler, ec, bytes));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Partial match. Next search needs to start from beginning of match.
|
||||
next_search_start = result.first - begin;
|
||||
}
|
||||
// Full match. We're done.
|
||||
asio::error_code ec;
|
||||
std::size_t bytes = result.first - begin;
|
||||
s.get_io_service().post(detail::bind_handler(handler, ec, bytes));
|
||||
return;
|
||||
}
|
||||
else if (result.first != end)
|
||||
{
|
||||
// Partial match. Next search needs to start from beginning of match.
|
||||
next_search_start = result.first - begin;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -976,7 +967,7 @@ void async_read_until(AsyncReadStream& s,
|
||||
if (b.size() == b.max_size())
|
||||
{
|
||||
asio::error_code ec(error::not_found);
|
||||
s.io_service().post(detail::bind_handler(handler, ec, 0));
|
||||
s.get_io_service().post(detail::bind_handler(handler, ec, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -32,18 +32,20 @@ template <typename SyncWriteStream, typename ConstBufferSequence,
|
||||
std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
|
||||
CompletionCondition completion_condition, asio::error_code& ec)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
asio::detail::consuming_buffers<
|
||||
const_buffer, ConstBufferSequence> tmp(buffers);
|
||||
std::size_t total_transferred = 0;
|
||||
tmp.set_max_size(detail::adapt_completion_condition_result(
|
||||
completion_condition(ec, total_transferred)));
|
||||
while (tmp.begin() != tmp.end())
|
||||
{
|
||||
std::size_t bytes_transferred = s.write_some(tmp, ec);
|
||||
tmp.consume(bytes_transferred);
|
||||
total_transferred += bytes_transferred;
|
||||
if (completion_condition(ec, total_transferred))
|
||||
return total_transferred;
|
||||
tmp.set_max_size(detail::adapt_completion_condition_result(
|
||||
completion_condition(ec, total_transferred)));
|
||||
}
|
||||
ec = asio::error_code();
|
||||
return total_transferred;
|
||||
}
|
||||
|
||||
@ -125,8 +127,9 @@ namespace detail
|
||||
{
|
||||
total_transferred_ += bytes_transferred;
|
||||
buffers_.consume(bytes_transferred);
|
||||
if (completion_condition_(ec, total_transferred_)
|
||||
|| buffers_.begin() == buffers_.end())
|
||||
buffers_.set_max_size(detail::adapt_completion_condition_result(
|
||||
completion_condition_(ec, total_transferred_)));
|
||||
if (buffers_.begin() == buffers_.end())
|
||||
{
|
||||
handler_(ec, total_transferred_);
|
||||
}
|
||||
@ -183,6 +186,18 @@ inline void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
|
||||
{
|
||||
asio::detail::consuming_buffers<
|
||||
const_buffer, ConstBufferSequence> tmp(buffers);
|
||||
|
||||
asio::error_code ec;
|
||||
std::size_t total_transferred = 0;
|
||||
tmp.set_max_size(detail::adapt_completion_condition_result(
|
||||
completion_condition(ec, total_transferred)));
|
||||
if (tmp.begin() == tmp.end())
|
||||
{
|
||||
s.get_io_service().post(detail::bind_handler(
|
||||
handler, ec, total_transferred));
|
||||
return;
|
||||
}
|
||||
|
||||
s.async_write_some(tmp,
|
||||
detail::write_handler<AsyncWriteStream, ConstBufferSequence,
|
||||
CompletionCondition, WriteHandler>(
|
||||
|
@ -33,19 +33,21 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d,
|
||||
boost::uint64_t offset, const ConstBufferSequence& buffers,
|
||||
CompletionCondition completion_condition, asio::error_code& ec)
|
||||
{
|
||||
ec = asio::error_code();
|
||||
asio::detail::consuming_buffers<
|
||||
const_buffer, ConstBufferSequence> tmp(buffers);
|
||||
std::size_t total_transferred = 0;
|
||||
tmp.set_max_size(detail::adapt_completion_condition_result(
|
||||
completion_condition(ec, total_transferred)));
|
||||
while (tmp.begin() != tmp.end())
|
||||
{
|
||||
std::size_t bytes_transferred = d.write_some_at(
|
||||
offset + total_transferred, tmp, ec);
|
||||
tmp.consume(bytes_transferred);
|
||||
total_transferred += bytes_transferred;
|
||||
if (completion_condition(ec, total_transferred))
|
||||
return total_transferred;
|
||||
tmp.set_max_size(detail::adapt_completion_condition_result(
|
||||
completion_condition(ec, total_transferred)));
|
||||
}
|
||||
ec = asio::error_code();
|
||||
return total_transferred;
|
||||
}
|
||||
|
||||
@ -135,8 +137,9 @@ namespace detail
|
||||
{
|
||||
total_transferred_ += bytes_transferred;
|
||||
buffers_.consume(bytes_transferred);
|
||||
if (completion_condition_(ec, total_transferred_)
|
||||
|| buffers_.begin() == buffers_.end())
|
||||
buffers_.set_max_size(detail::adapt_completion_condition_result(
|
||||
completion_condition_(ec, total_transferred_)));
|
||||
if (buffers_.begin() == buffers_.end())
|
||||
{
|
||||
handler_(ec, total_transferred_);
|
||||
}
|
||||
@ -196,6 +199,18 @@ inline void async_write_at(AsyncRandomAccessWriteDevice& d,
|
||||
{
|
||||
asio::detail::consuming_buffers<
|
||||
const_buffer, ConstBufferSequence> tmp(buffers);
|
||||
|
||||
asio::error_code ec;
|
||||
std::size_t total_transferred = 0;
|
||||
tmp.set_max_size(detail::adapt_completion_condition_result(
|
||||
completion_condition(ec, total_transferred)));
|
||||
if (tmp.begin() == tmp.end())
|
||||
{
|
||||
d.get_io_service().post(detail::bind_handler(
|
||||
handler, ec, total_transferred));
|
||||
return;
|
||||
}
|
||||
|
||||
d.async_write_some_at(offset, tmp,
|
||||
detail::write_at_handler<AsyncRandomAccessWriteDevice,
|
||||
ConstBufferSequence, CompletionCondition, WriteHandler>(
|
||||
|
@ -134,6 +134,7 @@ private:
|
||||
// The type of the platform-specific implementation.
|
||||
#if defined(ASIO_HAS_IOCP)
|
||||
typedef detail::win_iocp_io_service impl_type;
|
||||
friend class detail::win_iocp_overlapped_ptr;
|
||||
#elif defined(ASIO_HAS_EPOLL)
|
||||
typedef detail::task_io_service<detail::epoll_reactor<false> > impl_type;
|
||||
#elif defined(ASIO_HAS_KQUEUE)
|
||||
|
@ -18,7 +18,9 @@
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <climits>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
@ -55,6 +57,15 @@ public:
|
||||
/// Construct an address from raw bytes.
|
||||
explicit address_v4(const bytes_type& bytes)
|
||||
{
|
||||
#if UCHAR_MAX > 0xFF
|
||||
if (bytes[0] > 0xFF || bytes[1] > 0xFF
|
||||
|| bytes[2] > 0xFF || bytes[3] > 0xFF)
|
||||
{
|
||||
std::out_of_range ex("address_v4 from bytes_type");
|
||||
boost::throw_exception(ex);
|
||||
}
|
||||
#endif // UCHAR_MAX > 0xFF
|
||||
|
||||
using namespace std; // For memcpy.
|
||||
memcpy(&addr_.s_addr, bytes.elems, 4);
|
||||
}
|
||||
@ -62,6 +73,14 @@ public:
|
||||
/// Construct an address from a unsigned long in host byte order.
|
||||
explicit address_v4(unsigned long addr)
|
||||
{
|
||||
#if ULONG_MAX > 0xFFFFFFFF
|
||||
if (addr > 0xFFFFFFFF)
|
||||
{
|
||||
std::out_of_range ex("address_v4 from unsigned long");
|
||||
boost::throw_exception(ex);
|
||||
}
|
||||
#endif // ULONG_MAX > 0xFFFFFFFF
|
||||
|
||||
addr_.s_addr = asio::detail::socket_ops::host_to_network_long(addr);
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,17 @@ public:
|
||||
explicit address_v6(const bytes_type& bytes, unsigned long scope_id = 0)
|
||||
: scope_id_(scope_id)
|
||||
{
|
||||
#if UCHAR_MAX > 0xFF
|
||||
for (std::size_t i = 0; i < bytes.size(); ++i)
|
||||
{
|
||||
if (bytes[i] > 0xFF)
|
||||
{
|
||||
std::out_of_range ex("address_v6 from bytes_type");
|
||||
boost::throw_exception(ex);
|
||||
}
|
||||
}
|
||||
#endif // UCHAR_MAX > 0xFF
|
||||
|
||||
using namespace std; // For memcpy.
|
||||
memcpy(addr_.s6_addr, bytes.elems, 16);
|
||||
}
|
||||
@ -165,7 +176,11 @@ public:
|
||||
address_v4 to_v4() const
|
||||
{
|
||||
if (!is_v4_mapped() && !is_v4_compatible())
|
||||
throw std::bad_cast();
|
||||
{
|
||||
std::bad_cast ex;
|
||||
boost::throw_exception(ex);
|
||||
}
|
||||
|
||||
address_v4::bytes_type v4_bytes = { { addr_.s6_addr[12],
|
||||
addr_.s6_addr[13], addr_.s6_addr[14], addr_.s6_addr[15] } };
|
||||
return address_v4(v4_bytes);
|
||||
|
@ -75,7 +75,7 @@ public:
|
||||
return this->service.cancel(this->implementation);
|
||||
}
|
||||
|
||||
/// Resolve a query to a list of entries.
|
||||
/// Perform forward resolution of a query to a list of entries.
|
||||
/**
|
||||
* This function is used to resolve a query into a list of endpoint entries.
|
||||
*
|
||||
@ -99,7 +99,7 @@ public:
|
||||
return i;
|
||||
}
|
||||
|
||||
/// Resolve a query to a list of entries.
|
||||
/// Perform forward resolution of a query to a list of entries.
|
||||
/**
|
||||
* This function is used to resolve a query into a list of endpoint entries.
|
||||
*
|
||||
@ -121,7 +121,7 @@ public:
|
||||
return this->service.resolve(this->implementation, q, ec);
|
||||
}
|
||||
|
||||
/// Asynchronously resolve a query to a list of entries.
|
||||
/// Asynchronously perform forward resolution of a query to a list of entries.
|
||||
/**
|
||||
* This function is used to asynchronously resolve a query into a list of
|
||||
* endpoint entries.
|
||||
@ -153,7 +153,7 @@ public:
|
||||
return this->service.async_resolve(this->implementation, q, handler);
|
||||
}
|
||||
|
||||
/// Resolve an endpoint to a list of entries.
|
||||
/// Perform reverse resolution of an endpoint to a list of entries.
|
||||
/**
|
||||
* This function is used to resolve an endpoint into a list of endpoint
|
||||
* entries.
|
||||
@ -179,7 +179,7 @@ public:
|
||||
return i;
|
||||
}
|
||||
|
||||
/// Resolve an endpoint to a list of entries.
|
||||
/// Perform reverse resolution of an endpoint to a list of entries.
|
||||
/**
|
||||
* This function is used to resolve an endpoint into a list of endpoint
|
||||
* entries.
|
||||
@ -203,7 +203,8 @@ public:
|
||||
return this->service.resolve(this->implementation, e, ec);
|
||||
}
|
||||
|
||||
/// Asynchronously resolve an endpoint to a list of entries.
|
||||
/// Asynchronously perform reverse resolution of an endpoint to a list of
|
||||
/// entries.
|
||||
/**
|
||||
* This function is used to asynchronously resolve an endpoint into a list of
|
||||
* endpoint entries.
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
#if defined(__sun) || defined(__osf__)
|
||||
typedef unsigned char ipv4_value_type;
|
||||
typedef unsigned char ipv6_value_type;
|
||||
#elif defined(_AIX) || defined(__hpux)
|
||||
#elif defined(_AIX) || defined(__hpux) || defined(__QNXNTO__)
|
||||
typedef unsigned char ipv4_value_type;
|
||||
typedef unsigned int ipv6_value_type;
|
||||
#else
|
||||
|
@ -69,17 +69,19 @@ public:
|
||||
# else
|
||||
BOOST_STATIC_CONSTANT(int, numeric_service = 0);
|
||||
# endif
|
||||
# if defined(AI_V4MAPPED)
|
||||
// Note: QNX Neutrino 6.3 defines AI_V4MAPPED, AI_ALL and AI_ADDRCONFIG but
|
||||
// does not implement them. Therefore they are specifically excluded here.
|
||||
# if defined(AI_V4MAPPED) && !defined(__QNXNTO__)
|
||||
BOOST_STATIC_CONSTANT(int, v4_mapped = AI_V4MAPPED);
|
||||
# else
|
||||
BOOST_STATIC_CONSTANT(int, v4_mapped = 0);
|
||||
# endif
|
||||
# if defined(AI_ALL)
|
||||
# if defined(AI_ALL) && !defined(__QNXNTO__)
|
||||
BOOST_STATIC_CONSTANT(int, all_matching = AI_ALL);
|
||||
# else
|
||||
BOOST_STATIC_CONSTANT(int, all_matching = 0);
|
||||
# endif
|
||||
# if defined(AI_ADDRCONFIG)
|
||||
# if defined(AI_ADDRCONFIG) && !defined(__QNXNTO__)
|
||||
BOOST_STATIC_CONSTANT(int, address_configured = AI_ADDRCONFIG);
|
||||
# else
|
||||
BOOST_STATIC_CONSTANT(int, address_configured = 0);
|
||||
|
@ -148,7 +148,7 @@ public:
|
||||
- offsetof(asio::detail::sockaddr_un_type, sun_path);
|
||||
|
||||
// The path returned by the operating system may be NUL-terminated.
|
||||
if (path_length_ > 0 && data_.local.sun_path[path_length_] == 0)
|
||||
if (path_length_ > 0 && data_.local.sun_path[path_length_ - 1] == 0)
|
||||
--path_length_;
|
||||
}
|
||||
}
|
||||
|
@ -99,6 +99,20 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Get a const reference to the lowest layer.
|
||||
/**
|
||||
* This function returns a const reference to the lowest layer in a stack of
|
||||
* layers. Since a basic_descriptor cannot contain any further layers, it
|
||||
* simply returns a reference to itself.
|
||||
*
|
||||
* @return A const reference to the lowest layer in the stack of layers.
|
||||
* Ownership is not transferred to the caller.
|
||||
*/
|
||||
const lowest_layer_type& lowest_layer() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Assign an existing native descriptor to the descriptor.
|
||||
/*
|
||||
* This function opens the descriptor to hold an existing native descriptor.
|
||||
|
@ -45,7 +45,7 @@ namespace asio {
|
||||
*
|
||||
* @li An error occurred.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* read_some function.
|
||||
*
|
||||
* @param s The stream from which the data is to be read. The type must support
|
||||
@ -84,7 +84,7 @@ std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers);
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* read_some function.
|
||||
*
|
||||
* @param s The stream from which the data is to be read. The type must support
|
||||
@ -97,15 +97,16 @@ std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers);
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the read operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* const asio::error_code& error, // Result of latest read_some
|
||||
* // operation.
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest read_some operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* std::size_t bytes_transferred // Number of bytes transferred
|
||||
* // so far.
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the read operation is complete. False
|
||||
* indicates that further calls to the stream's read_some function are required.
|
||||
* A return value of 0 indicates that the read operation is complete. A non-zero
|
||||
* return value indicates the maximum number of bytes to be read on the next
|
||||
* call to the stream's read_some function.
|
||||
*
|
||||
* @returns The number of bytes transferred.
|
||||
*
|
||||
@ -134,7 +135,7 @@ std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* read_some function.
|
||||
*
|
||||
* @param s The stream from which the data is to be read. The type must support
|
||||
@ -147,15 +148,16 @@ std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the read operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* const asio::error_code& error, // Result of latest read_some
|
||||
* // operation.
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest read_some operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* std::size_t bytes_transferred // Number of bytes transferred
|
||||
* // so far.
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the read operation is complete. False
|
||||
* indicates that further calls to the stream's read_some function are required.
|
||||
* A return value of 0 indicates that the read operation is complete. A non-zero
|
||||
* return value indicates the maximum number of bytes to be read on the next
|
||||
* call to the stream's read_some function.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
@ -174,7 +176,7 @@ std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
|
||||
*
|
||||
* @li An error occurred.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* read_some function.
|
||||
*
|
||||
* @param s The stream from which the data is to be read. The type must support
|
||||
@ -201,7 +203,7 @@ std::size_t read(SyncReadStream& s, basic_streambuf<Allocator>& b);
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* read_some function.
|
||||
*
|
||||
* @param s The stream from which the data is to be read. The type must support
|
||||
@ -212,15 +214,16 @@ std::size_t read(SyncReadStream& s, basic_streambuf<Allocator>& b);
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the read operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* const asio::error_code& error, // Result of latest read_some
|
||||
* // operation.
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest read_some operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* std::size_t bytes_transferred // Number of bytes transferred
|
||||
* // so far.
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the read operation is complete. False
|
||||
* indicates that further calls to the stream's read_some function are required.
|
||||
* A return value of 0 indicates that the read operation is complete. A non-zero
|
||||
* return value indicates the maximum number of bytes to be read on the next
|
||||
* call to the stream's read_some function.
|
||||
*
|
||||
* @returns The number of bytes transferred.
|
||||
*
|
||||
@ -238,7 +241,7 @@ std::size_t read(SyncReadStream& s, basic_streambuf<Allocator>& b,
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* read_some function.
|
||||
*
|
||||
* @param s The stream from which the data is to be read. The type must support
|
||||
@ -249,15 +252,16 @@ std::size_t read(SyncReadStream& s, basic_streambuf<Allocator>& b,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the read operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* const asio::error_code& error, // Result of latest read_some
|
||||
* // operation.
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest read_some operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* std::size_t bytes_transferred // Number of bytes transferred
|
||||
* // so far.
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the read operation is complete. False
|
||||
* indicates that further calls to the stream's read_some function are required.
|
||||
* A return value of 0 indicates that the read operation is complete. A non-zero
|
||||
* return value indicates the maximum number of bytes to be read on the next
|
||||
* call to the stream's read_some function.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
@ -291,7 +295,7 @@ std::size_t read(SyncReadStream& s, basic_streambuf<Allocator>& b,
|
||||
*
|
||||
* @li An error occurred.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* async_read_some function.
|
||||
*
|
||||
* @param s The stream from which the data is to be read. The type must support
|
||||
@ -365,16 +369,16 @@ void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the read operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* const asio::error_code& error, // Result of latest read_some
|
||||
* // operation.
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest async_read_some operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* std::size_t bytes_transferred // Number of bytes transferred
|
||||
* // so far.
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the read operation is complete. False
|
||||
* indicates that further calls to the stream's async_read_some function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the read operation is complete. A non-zero
|
||||
* return value indicates the maximum number of bytes to be read on the next
|
||||
* call to the stream's async_read_some function.
|
||||
*
|
||||
* @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
|
||||
@ -418,7 +422,7 @@ void async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
|
||||
*
|
||||
* @li An error occurred.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* async_read_some function.
|
||||
*
|
||||
* @param s The stream from which the data is to be read. The type must support
|
||||
@ -465,7 +469,7 @@ void async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* async_read_some function.
|
||||
*
|
||||
* @param s The stream from which the data is to be read. The type must support
|
||||
@ -478,16 +482,16 @@ void async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the read operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* const asio::error_code& error, // Result of latest read_some
|
||||
* // operation.
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest async_read_some operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* std::size_t bytes_transferred // Number of bytes transferred
|
||||
* // so far.
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the read operation is complete. False
|
||||
* indicates that further calls to the stream's async_read_some function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the read operation is complete. A non-zero
|
||||
* return value indicates the maximum number of bytes to be read on the next
|
||||
* call to the stream's async_read_some function.
|
||||
*
|
||||
* @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
|
||||
|
@ -48,7 +48,7 @@ namespace asio {
|
||||
*
|
||||
* @li An error occurred.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* read_some_at function.
|
||||
*
|
||||
* @param d The device from which the data is to be read. The type must support
|
||||
@ -92,7 +92,7 @@ std::size_t read_at(SyncRandomAccessReadDevice& d,
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* read_some_at function.
|
||||
*
|
||||
* @param d The device from which the data is to be read. The type must support
|
||||
@ -107,16 +107,16 @@ std::size_t read_at(SyncRandomAccessReadDevice& d,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the read operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest read_some_at operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the read operation is complete. False
|
||||
* indicates that further calls to the device's read_some_at function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the read operation is complete. A non-zero
|
||||
* return value indicates the maximum number of bytes to be read on the next
|
||||
* call to the device's read_some_at function.
|
||||
*
|
||||
* @returns The number of bytes transferred.
|
||||
*
|
||||
@ -148,7 +148,7 @@ std::size_t read_at(SyncRandomAccessReadDevice& d,
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* read_some_at function.
|
||||
*
|
||||
* @param d The device from which the data is to be read. The type must support
|
||||
@ -163,16 +163,16 @@ std::size_t read_at(SyncRandomAccessReadDevice& d,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the read operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* const asio::error_code& error, // Result of latest read_some_at
|
||||
* // operation.
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest read_some_at operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* std::size_t bytes_transferred // Number of bytes transferred
|
||||
* // so far.
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the read operation is complete. False
|
||||
* indicates that further calls to the device's read_some_at function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the read operation is complete. A non-zero
|
||||
* return value indicates the maximum number of bytes to be read on the next
|
||||
* call to the device's read_some_at function.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
@ -194,7 +194,7 @@ std::size_t read_at(SyncRandomAccessReadDevice& d,
|
||||
*
|
||||
* @li An error occurred.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* read_some_at function.
|
||||
*
|
||||
* @param d The device from which the data is to be read. The type must support
|
||||
@ -226,7 +226,7 @@ std::size_t read_at(SyncRandomAccessReadDevice& d,
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* read_some_at function.
|
||||
*
|
||||
* @param d The device from which the data is to be read. The type must support
|
||||
@ -239,16 +239,16 @@ std::size_t read_at(SyncRandomAccessReadDevice& d,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the read operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest read_some_at operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the read operation is complete. False
|
||||
* indicates that further calls to the device's read_some_at function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the read operation is complete. A non-zero
|
||||
* return value indicates the maximum number of bytes to be read on the next
|
||||
* call to the device's read_some_at function.
|
||||
*
|
||||
* @returns The number of bytes transferred.
|
||||
*
|
||||
@ -269,7 +269,7 @@ std::size_t read_at(SyncRandomAccessReadDevice& d,
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* read_some_at function.
|
||||
*
|
||||
* @param d The device from which the data is to be read. The type must support
|
||||
@ -282,16 +282,16 @@ std::size_t read_at(SyncRandomAccessReadDevice& d,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the read operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest read_some_at operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the read operation is complete. False
|
||||
* indicates that further calls to the device's read_some_at function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the read operation is complete. A non-zero
|
||||
* return value indicates the maximum number of bytes to be read on the next
|
||||
* call to the device's read_some_at function.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
@ -326,7 +326,7 @@ std::size_t read_at(SyncRandomAccessReadDevice& d,
|
||||
*
|
||||
* @li An error occurred.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* async_read_some_at function.
|
||||
*
|
||||
* @param d The device from which the data is to be read. The type must support
|
||||
@ -404,16 +404,16 @@ void async_read_at(AsyncRandomAccessReadDevice& d, boost::uint64_t offset,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the read operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* // Result of latest read_some_at operation.
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest async_read_some_at operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the read operation is complete. False
|
||||
* indicates that further calls to the device's async_read_some_at function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the read operation is complete. A non-zero
|
||||
* return value indicates the maximum number of bytes to be read on the next
|
||||
* call to the device's async_read_some_at function.
|
||||
*
|
||||
* @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
|
||||
@ -458,7 +458,7 @@ void async_read_at(AsyncRandomAccessReadDevice& d,
|
||||
*
|
||||
* @li An error occurred.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* async_read_some_at function.
|
||||
*
|
||||
* @param d The device from which the data is to be read. The type must support
|
||||
@ -508,7 +508,7 @@ void async_read_at(AsyncRandomAccessReadDevice& d, boost::uint64_t offset,
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* async_read_some_at function.
|
||||
*
|
||||
* @param d The device from which the data is to be read. The type must support
|
||||
@ -523,16 +523,16 @@ void async_read_at(AsyncRandomAccessReadDevice& d, boost::uint64_t offset,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the read operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* // Result of latest read_some_at operation.
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest async_read_some_at operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the read operation is complete. False
|
||||
* indicates that further calls to the device's async_read_some_at function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the read operation is complete. A non-zero
|
||||
* return value indicates the maximum number of bytes to be read on the next
|
||||
* call to the device's async_read_some_at function.
|
||||
*
|
||||
* @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
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <boost/type_traits/is_function.hpp>
|
||||
#include <boost/type_traits/remove_pointer.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <string>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
@ -34,6 +35,20 @@ namespace asio {
|
||||
|
||||
namespace detail
|
||||
{
|
||||
#if BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x610))
|
||||
template <typename T>
|
||||
struct has_result_type
|
||||
{
|
||||
template <typename U> struct inner
|
||||
{
|
||||
struct big { char a[100]; };
|
||||
static big helper(U, ...);
|
||||
static char helper(U, typename U::result_type* = 0);
|
||||
};
|
||||
static const T& ref();
|
||||
enum { value = (sizeof((inner<const T&>::helper)((ref)())) == 1) };
|
||||
};
|
||||
#else // BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x610))
|
||||
template <typename T>
|
||||
struct has_result_type
|
||||
{
|
||||
@ -43,6 +58,7 @@ namespace detail
|
||||
static const T& ref();
|
||||
enum { value = (sizeof((helper)((ref)())) == 1) };
|
||||
};
|
||||
#endif // BOOST_WORKAROUND(__CODEGEARC__, BOOST_TESTED_AT(0x610))
|
||||
} // namespace detail
|
||||
|
||||
/// Type trait used to determine whether a type can be used as a match condition
|
||||
|
@ -308,9 +308,9 @@ public:
|
||||
|
||||
::BIO_free(bio);
|
||||
int result = ::SSL_CTX_set_tmp_dh(impl, dh);
|
||||
::DH_free(dh);
|
||||
if (result != 1)
|
||||
{
|
||||
::DH_free(dh);
|
||||
ec = asio::error::invalid_argument;
|
||||
return ec;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "asio/detail/push_options.hpp"
|
||||
#include <vector>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
@ -86,11 +87,15 @@ private:
|
||||
private:
|
||||
static unsigned long openssl_id_func()
|
||||
{
|
||||
#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
return ::GetCurrentThreadId();
|
||||
#else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
void* id = instance()->thread_id_;
|
||||
if (id == 0)
|
||||
instance()->thread_id_ = id = &id; // Ugh.
|
||||
BOOST_ASSERT(sizeof(unsigned long) >= sizeof(void*));
|
||||
return reinterpret_cast<unsigned long>(id);
|
||||
#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
|
||||
}
|
||||
|
||||
static void openssl_locking_func(int mode, int n,
|
||||
@ -105,8 +110,10 @@ private:
|
||||
// Mutexes to be used in locking callbacks.
|
||||
std::vector<boost::shared_ptr<asio::detail::mutex> > mutexes_;
|
||||
|
||||
#if !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
// The thread identifiers to be used by openssl.
|
||||
asio::detail::tss_ptr<void> thread_id_;
|
||||
#endif // !defined(BOOST_WINDOWS) && !defined(__CYGWIN__)
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -158,6 +158,10 @@ public:
|
||||
0;
|
||||
int sys_error_code = ERR_get_error();
|
||||
|
||||
if (error_code == SSL_ERROR_SSL)
|
||||
return handler_(asio::error_code(
|
||||
error_code, asio::error::get_ssl_category()), rc);
|
||||
|
||||
bool is_read_needed = (error_code == SSL_ERROR_WANT_READ);
|
||||
bool is_write_needed = (error_code == SSL_ERROR_WANT_WRITE ||
|
||||
::BIO_ctrl_pending( ssl_bio_ ));
|
||||
|
@ -336,7 +336,7 @@ public:
|
||||
buffer_size = max_buffer_size;
|
||||
|
||||
boost::function<int (SSL*)> send_func =
|
||||
boost::bind(&::SSL_write, boost::arg<1>(),
|
||||
boost::bind(boost::type<int>(), &::SSL_write, boost::arg<1>(),
|
||||
asio::buffer_cast<const void*>(*buffers.begin()),
|
||||
static_cast<int>(buffer_size));
|
||||
openssl_operation<Stream> op(
|
||||
@ -372,7 +372,7 @@ public:
|
||||
buffer_size = max_buffer_size;
|
||||
|
||||
boost::function<int (SSL*)> send_func =
|
||||
boost::bind(&::SSL_write, boost::arg<1>(),
|
||||
boost::bind(boost::type<int>(), &::SSL_write, boost::arg<1>(),
|
||||
asio::buffer_cast<const void*>(*buffers.begin()),
|
||||
static_cast<int>(buffer_size));
|
||||
|
||||
@ -410,7 +410,7 @@ public:
|
||||
buffer_size = max_buffer_size;
|
||||
|
||||
boost::function<int (SSL*)> recv_func =
|
||||
boost::bind(&::SSL_read, boost::arg<1>(),
|
||||
boost::bind(boost::type<int>(), &::SSL_read, boost::arg<1>(),
|
||||
asio::buffer_cast<void*>(*buffers.begin()),
|
||||
static_cast<int>(buffer_size));
|
||||
openssl_operation<Stream> op(recv_func,
|
||||
@ -446,7 +446,7 @@ public:
|
||||
buffer_size = max_buffer_size;
|
||||
|
||||
boost::function<int (SSL*)> recv_func =
|
||||
boost::bind(&::SSL_read, boost::arg<1>(),
|
||||
boost::bind(boost::type<int>(), &::SSL_read, boost::arg<1>(),
|
||||
asio::buffer_cast<void*>(*buffers.begin()),
|
||||
static_cast<int>(buffer_size));
|
||||
|
||||
|
@ -149,6 +149,19 @@ public:
|
||||
return next_layer_.lowest_layer();
|
||||
}
|
||||
|
||||
/// Get a const reference to the lowest layer.
|
||||
/**
|
||||
* This function returns a const reference to the lowest layer in a stack of
|
||||
* stream layers.
|
||||
*
|
||||
* @return A const reference to the lowest layer in the stack of stream
|
||||
* layers. Ownership is not transferred to the caller.
|
||||
*/
|
||||
const lowest_layer_type& lowest_layer() const
|
||||
{
|
||||
return next_layer_.lowest_layer();
|
||||
}
|
||||
|
||||
/// Get the underlying implementation in the native type.
|
||||
/**
|
||||
* This function may be used to obtain the underlying implementation of the
|
||||
|
@ -58,7 +58,7 @@ public:
|
||||
*/
|
||||
template <typename Function>
|
||||
explicit thread(Function f)
|
||||
: impl_(f, asio::detail::thread::external)
|
||||
: impl_(f)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,6 @@
|
||||
// ASIO_VERSION % 100 is the sub-minor version
|
||||
// ASIO_VERSION / 100 % 1000 is the minor version
|
||||
// ASIO_VERSION / 100000 is the major version
|
||||
#define ASIO_VERSION 100100 // 1.1.0
|
||||
#define ASIO_VERSION 100401 // 1.4.1
|
||||
|
||||
#endif // ASIO_VERSION_HPP
|
||||
|
@ -94,6 +94,20 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Get a const reference to the lowest layer.
|
||||
/**
|
||||
* This function returns a const reference to the lowest layer in a stack of
|
||||
* layers. Since a basic_handle cannot contain any further layers, it simply
|
||||
* returns a reference to itself.
|
||||
*
|
||||
* @return A const reference to the lowest layer in the stack of layers.
|
||||
* Ownership is not transferred to the caller.
|
||||
*/
|
||||
const lowest_layer_type& lowest_layer() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Assign an existing native handle to the handle.
|
||||
/*
|
||||
* This function opens the handle to hold an existing native handle.
|
||||
|
@ -44,7 +44,7 @@ namespace asio {
|
||||
*
|
||||
* @li An error occurred.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* write_some function.
|
||||
*
|
||||
* @param s The stream to which the data is to be written. The type must support
|
||||
@ -83,7 +83,7 @@ std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers);
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* write_some function.
|
||||
*
|
||||
* @param s The stream to which the data is to be written. The type must support
|
||||
@ -96,16 +96,16 @@ std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers);
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the write operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* const asio::error_code& error, // Result of latest write_some
|
||||
* // operation.
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest write_some operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* std::size_t bytes_transferred // Number of bytes transferred
|
||||
* // so far.
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the write operation is complete. False
|
||||
* indicates that further calls to the stream's write_some function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the write operation is complete. A
|
||||
* non-zero return value indicates the maximum number of bytes to be written on
|
||||
* the next call to the stream's write_some function.
|
||||
*
|
||||
* @returns The number of bytes transferred.
|
||||
*
|
||||
@ -134,7 +134,7 @@ std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* write_some function.
|
||||
*
|
||||
* @param s The stream to which the data is to be written. The type must support
|
||||
@ -147,16 +147,16 @@ std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the write operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* const asio::error_code& error, // Result of latest write_some
|
||||
* // operation.
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest write_some operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* std::size_t bytes_transferred // Number of bytes transferred
|
||||
* // so far.
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the write operation is complete. False
|
||||
* indicates that further calls to the stream's write_some function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the write operation is complete. A
|
||||
* non-zero return value indicates the maximum number of bytes to be written on
|
||||
* the next call to the stream's write_some function.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
@ -177,7 +177,7 @@ std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
|
||||
*
|
||||
* @li An error occurred.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* write_some function.
|
||||
*
|
||||
* @param s The stream to which the data is to be written. The type must support
|
||||
@ -206,7 +206,7 @@ std::size_t write(SyncWriteStream& s, basic_streambuf<Allocator>& b);
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* write_some function.
|
||||
*
|
||||
* @param s The stream to which the data is to be written. The type must support
|
||||
@ -217,16 +217,16 @@ std::size_t write(SyncWriteStream& s, basic_streambuf<Allocator>& b);
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the write operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* const asio::error_code& error, // Result of latest write_some
|
||||
* // operation.
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest write_some operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* std::size_t bytes_transferred // Number of bytes transferred
|
||||
* // so far.
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the write operation is complete. False
|
||||
* indicates that further calls to the stream's write_some function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the write operation is complete. A
|
||||
* non-zero return value indicates the maximum number of bytes to be written on
|
||||
* the next call to the stream's write_some function.
|
||||
*
|
||||
* @returns The number of bytes transferred.
|
||||
*
|
||||
@ -246,7 +246,7 @@ std::size_t write(SyncWriteStream& s, basic_streambuf<Allocator>& b,
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* write_some function.
|
||||
*
|
||||
* @param s The stream to which the data is to be written. The type must support
|
||||
@ -257,16 +257,16 @@ std::size_t write(SyncWriteStream& s, basic_streambuf<Allocator>& b,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the write operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* const asio::error_code& error, // Result of latest write_some
|
||||
* // operation.
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest write_some operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* std::size_t bytes_transferred // Number of bytes transferred
|
||||
* // so far.
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the write operation is complete. False
|
||||
* indicates that further calls to the stream's write_some function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the write operation is complete. A
|
||||
* non-zero return value indicates the maximum number of bytes to be written on
|
||||
* the next call to the stream's write_some function.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
@ -300,7 +300,7 @@ std::size_t write(SyncWriteStream& s, basic_streambuf<Allocator>& b,
|
||||
*
|
||||
* @li An error occurred.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* async_write_some function.
|
||||
*
|
||||
* @param s The stream to which the data is to be written. The type must support
|
||||
@ -354,7 +354,7 @@ void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* async_write_some function.
|
||||
*
|
||||
* @param s The stream to which the data is to be written. The type must support
|
||||
@ -368,16 +368,16 @@ void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the write operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* const asio::error_code& error, // Result of latest write_some
|
||||
* // operation.
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest async_write_some operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* std::size_t bytes_transferred // Number of bytes transferred
|
||||
* // so far.
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the write operation is complete. False
|
||||
* indicates that further calls to the stream's async_write_some function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the write operation is complete. A
|
||||
* non-zero return value indicates the maximum number of bytes to be written on
|
||||
* the next call to the stream's async_write_some function.
|
||||
*
|
||||
* @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
|
||||
@ -422,7 +422,7 @@ void async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
|
||||
*
|
||||
* @li An error occurred.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* async_write_some function.
|
||||
*
|
||||
* @param s The stream to which the data is to be written. The type must support
|
||||
@ -464,7 +464,7 @@ void async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b,
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the stream's
|
||||
* This operation is implemented in terms of zero or more calls to the stream's
|
||||
* async_write_some function.
|
||||
*
|
||||
* @param s The stream to which the data is to be written. The type must support
|
||||
@ -477,16 +477,16 @@ void async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the write operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* const asio::error_code& error, // Result of latest write_some
|
||||
* // operation.
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest async_write_some operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* std::size_t bytes_transferred // Number of bytes transferred
|
||||
* // so far.
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the write operation is complete. False
|
||||
* indicates that further calls to the stream's async_write_some function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the write operation is complete. A
|
||||
* non-zero return value indicates the maximum number of bytes to be written on
|
||||
* the next call to the stream's async_write_some function.
|
||||
*
|
||||
* @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
|
||||
|
@ -46,7 +46,7 @@ namespace asio {
|
||||
*
|
||||
* @li An error occurred.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* write_some_at function.
|
||||
*
|
||||
* @param d The device to which the data is to be written. The type must support
|
||||
@ -89,7 +89,7 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d,
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* write_some_at function.
|
||||
*
|
||||
* @param d The device to which the data is to be written. The type must support
|
||||
@ -104,16 +104,16 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the write operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest write_some_at operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the write operation is complete. False
|
||||
* indicates that further calls to the device's write_some_at function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the write operation is complete. A
|
||||
* non-zero return value indicates the maximum number of bytes to be written on
|
||||
* the next call to the device's write_some_at function.
|
||||
*
|
||||
* @returns The number of bytes transferred.
|
||||
*
|
||||
@ -144,7 +144,7 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d,
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* write_some_at function.
|
||||
*
|
||||
* @param d The device to which the data is to be written. The type must support
|
||||
@ -159,16 +159,16 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the write operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest write_some_at operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the write operation is complete. False
|
||||
* indicates that further calls to the device's write_some_at function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the write operation is complete. A
|
||||
* non-zero return value indicates the maximum number of bytes to be written on
|
||||
* the next call to the device's write_some_at function.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
@ -191,7 +191,7 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d,
|
||||
*
|
||||
* @li An error occurred.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* write_some_at function.
|
||||
*
|
||||
* @param d The device to which the data is to be written. The type must support
|
||||
@ -224,7 +224,7 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d,
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* write_some_at function.
|
||||
*
|
||||
* @param d The device to which the data is to be written. The type must support
|
||||
@ -237,16 +237,16 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the write operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest write_some_at operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the write operation is complete. False
|
||||
* indicates that further calls to the device's write_some_at function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the write operation is complete. A
|
||||
* non-zero return value indicates the maximum number of bytes to be written on
|
||||
* the next call to the device's write_some_at function.
|
||||
*
|
||||
* @returns The number of bytes transferred.
|
||||
*
|
||||
@ -267,7 +267,7 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d, boost::uint64_t offset,
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* write_some_at function.
|
||||
*
|
||||
* @param d The device to which the data is to be written. The type must support
|
||||
@ -280,16 +280,16 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d, boost::uint64_t offset,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the write operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest write_some_at operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the write operation is complete. False
|
||||
* indicates that further calls to the device's write_some_at function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the write operation is complete. A
|
||||
* non-zero return value indicates the maximum number of bytes to be written on
|
||||
* the next call to the device's write_some_at function.
|
||||
*
|
||||
* @param ec Set to indicate what error occurred, if any.
|
||||
*
|
||||
@ -324,7 +324,7 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d, boost::uint64_t offset,
|
||||
*
|
||||
* @li An error occurred.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* async_write_some_at function.
|
||||
*
|
||||
* @param d The device to which the data is to be written. The type must support
|
||||
@ -380,7 +380,7 @@ void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset,
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* async_write_some_at function.
|
||||
*
|
||||
* @param d The device to which the data is to be written. The type must support
|
||||
@ -396,16 +396,16 @@ void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the write operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* // Result of latest write_some_at operation.
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest async_write_some_at operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the write operation is complete. False
|
||||
* indicates that further calls to the device's async_write_some_at function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the write operation is complete. A
|
||||
* non-zero return value indicates the maximum number of bytes to be written on
|
||||
* the next call to the device's async_write_some_at function.
|
||||
*
|
||||
* @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
|
||||
@ -451,7 +451,7 @@ void async_write_at(AsyncRandomAccessWriteDevice& d,
|
||||
*
|
||||
* @li An error occurred.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* async_write_some_at function.
|
||||
*
|
||||
* @param d The device to which the data is to be written. The type must support
|
||||
@ -496,7 +496,7 @@ void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset,
|
||||
*
|
||||
* @li The completion_condition function object returns true.
|
||||
*
|
||||
* This operation is implemented in terms of one or more calls to the device's
|
||||
* This operation is implemented in terms of zero or more calls to the device's
|
||||
* async_write_some_at function.
|
||||
*
|
||||
* @param d The device to which the data is to be written. The type must support
|
||||
@ -511,16 +511,16 @@ void async_write_at(AsyncRandomAccessWriteDevice& d, boost::uint64_t offset,
|
||||
* @param completion_condition The function object to be called to determine
|
||||
* whether the write operation is complete. The signature of the function object
|
||||
* must be:
|
||||
* @code bool completion_condition(
|
||||
* @code std::size_t completion_condition(
|
||||
* // Result of latest async_write_some_at operation.
|
||||
* const asio::error_code& error,
|
||||
*
|
||||
* // Number of bytes transferred so far.
|
||||
* std::size_t bytes_transferred
|
||||
* ); @endcode
|
||||
* A return value of true indicates that the write operation is complete. False
|
||||
* indicates that further calls to the device's async_write_some_at function are
|
||||
* required.
|
||||
* A return value of 0 indicates that the write operation is complete. A
|
||||
* non-zero return value indicates the maximum number of bytes to be written on
|
||||
* the next call to the device's async_write_some_at function.
|
||||
*
|
||||
* @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
|
||||
|
Loading…
x
Reference in New Issue
Block a user