Add missing files
This commit is contained in:
parent
111b64d38b
commit
d795a66ae9
|
@ -0,0 +1,155 @@
|
||||||
|
//
|
||||||
|
// eventfd_select_interrupter.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
// Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_DETAIL_EVENTFD_SELECT_INTERRUPTER_HPP
|
||||||
|
#define ASIO_DETAIL_EVENTFD_SELECT_INTERRUPTER_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <boost/throw_exception.hpp>
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#if defined(linux)
|
||||||
|
# if !defined(ASIO_DISABLE_EVENTFD)
|
||||||
|
# include <linux/version.h>
|
||||||
|
# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||||
|
# define ASIO_HAS_EVENTFD
|
||||||
|
# endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
|
||||||
|
# endif // !defined(ASIO_DISABLE_EVENTFD)
|
||||||
|
#endif // defined(linux)
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_EVENTFD)
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
#include <fcntl.h>
|
||||||
|
#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
|
||||||
|
# include <asm/unistd.h>
|
||||||
|
#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
|
||||||
|
# include <sys/eventfd.h>
|
||||||
|
#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#include "asio/error.hpp"
|
||||||
|
#include "asio/system_error.hpp"
|
||||||
|
#include "asio/detail/socket_types.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class eventfd_select_interrupter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Constructor.
|
||||||
|
eventfd_select_interrupter()
|
||||||
|
{
|
||||||
|
#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
|
||||||
|
write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0);
|
||||||
|
#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
|
||||||
|
write_descriptor_ = read_descriptor_ = ::eventfd(0, 0);
|
||||||
|
#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8
|
||||||
|
if (read_descriptor_ != -1)
|
||||||
|
{
|
||||||
|
::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int pipe_fds[2];
|
||||||
|
if (pipe(pipe_fds) == 0)
|
||||||
|
{
|
||||||
|
read_descriptor_ = pipe_fds[0];
|
||||||
|
::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);
|
||||||
|
write_descriptor_ = pipe_fds[1];
|
||||||
|
::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
asio::error_code ec(errno,
|
||||||
|
asio::error::get_system_category());
|
||||||
|
asio::system_error e(ec, "eventfd_select_interrupter");
|
||||||
|
boost::throw_exception(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructor.
|
||||||
|
~eventfd_select_interrupter()
|
||||||
|
{
|
||||||
|
if (write_descriptor_ != -1 && write_descriptor_ != read_descriptor_)
|
||||||
|
::close(write_descriptor_);
|
||||||
|
if (read_descriptor_ != -1)
|
||||||
|
::close(read_descriptor_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interrupt the select call.
|
||||||
|
void interrupt()
|
||||||
|
{
|
||||||
|
uint64_t counter(1UL);
|
||||||
|
int result = ::write(write_descriptor_, &counter, sizeof(uint64_t));
|
||||||
|
(void)result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the select interrupt. Returns true if the call was interrupted.
|
||||||
|
bool reset()
|
||||||
|
{
|
||||||
|
if (write_descriptor_ == read_descriptor_)
|
||||||
|
{
|
||||||
|
// Only perform one read. The kernel maintains an atomic counter.
|
||||||
|
uint64_t counter(0);
|
||||||
|
int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t));
|
||||||
|
bool was_interrupted = (bytes_read > 0);
|
||||||
|
return was_interrupted;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Clear all data from the pipe.
|
||||||
|
char data[1024];
|
||||||
|
int bytes_read = ::read(read_descriptor_, data, sizeof(data));
|
||||||
|
bool was_interrupted = (bytes_read > 0);
|
||||||
|
while (bytes_read == sizeof(data))
|
||||||
|
bytes_read = ::read(read_descriptor_, data, sizeof(data));
|
||||||
|
return was_interrupted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the read descriptor to be passed to select.
|
||||||
|
int read_descriptor() const
|
||||||
|
{
|
||||||
|
return read_descriptor_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// The read end of a connection used to interrupt the select call. This file
|
||||||
|
// descriptor is passed to select such that when it is time to stop, a single
|
||||||
|
// 64bit value will be written on the other end of the connection and this
|
||||||
|
// descriptor will become readable.
|
||||||
|
int read_descriptor_;
|
||||||
|
|
||||||
|
// The write end of a connection used to interrupt the select call. A single
|
||||||
|
// 64bit non-zero value may be written to this to wake up the select which is
|
||||||
|
// waiting for the other end to become readable. This descriptor will only
|
||||||
|
// differ from the read descriptor when a pipe is used.
|
||||||
|
int write_descriptor_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_EVENTFD)
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_DETAIL_EVENTFD_SELECT_INTERRUPTER_HPP
|
|
@ -0,0 +1,207 @@
|
||||||
|
//
|
||||||
|
// win_iocp_overlapped_ptr.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_DETAIL_WIN_IOCP_OVERLAPPED_PTR_HPP
|
||||||
|
#define ASIO_DETAIL_WIN_IOCP_OVERLAPPED_PTR_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/win_iocp_io_service_fwd.hpp"
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_IOCP)
|
||||||
|
|
||||||
|
#include "asio/detail/noncopyable.hpp"
|
||||||
|
#include "asio/detail/win_iocp_io_service.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
// Wraps a handler to create an OVERLAPPED object for use with overlapped I/O.
|
||||||
|
class win_iocp_overlapped_ptr
|
||||||
|
: private noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Construct an empty win_iocp_overlapped_ptr.
|
||||||
|
win_iocp_overlapped_ptr()
|
||||||
|
: ptr_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct an win_iocp_overlapped_ptr to contain the specified handler.
|
||||||
|
template <typename Handler>
|
||||||
|
explicit win_iocp_overlapped_ptr(
|
||||||
|
asio::io_service& io_service, Handler handler)
|
||||||
|
: ptr_(0)
|
||||||
|
{
|
||||||
|
this->reset(io_service, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destructor automatically frees the OVERLAPPED object unless released.
|
||||||
|
~win_iocp_overlapped_ptr()
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset to empty.
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
if (ptr_)
|
||||||
|
{
|
||||||
|
ptr_->destroy();
|
||||||
|
ptr_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset to contain the specified handler, freeing any current OVERLAPPED
|
||||||
|
// object.
|
||||||
|
template <typename Handler>
|
||||||
|
void reset(asio::io_service& io_service, Handler handler)
|
||||||
|
{
|
||||||
|
typedef overlapped_operation<Handler> value_type;
|
||||||
|
typedef handler_alloc_traits<Handler, value_type> alloc_traits;
|
||||||
|
raw_handler_ptr<alloc_traits> raw_ptr(handler);
|
||||||
|
handler_ptr<alloc_traits> ptr(raw_ptr, io_service.impl_, handler);
|
||||||
|
reset();
|
||||||
|
ptr_ = ptr.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the contained OVERLAPPED object.
|
||||||
|
OVERLAPPED* get()
|
||||||
|
{
|
||||||
|
return ptr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the contained OVERLAPPED object.
|
||||||
|
const OVERLAPPED* get() const
|
||||||
|
{
|
||||||
|
return ptr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Release ownership of the OVERLAPPED object.
|
||||||
|
OVERLAPPED* release()
|
||||||
|
{
|
||||||
|
OVERLAPPED* tmp = ptr_;
|
||||||
|
ptr_ = 0;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post completion notification for overlapped operation. Releases ownership.
|
||||||
|
void complete(const asio::error_code& ec,
|
||||||
|
std::size_t bytes_transferred)
|
||||||
|
{
|
||||||
|
if (ptr_)
|
||||||
|
{
|
||||||
|
ptr_->ec_ = ec;
|
||||||
|
ptr_->io_service_.post_completion(ptr_, 0, bytes_transferred);
|
||||||
|
ptr_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct overlapped_operation_base
|
||||||
|
: public win_iocp_io_service::operation
|
||||||
|
{
|
||||||
|
overlapped_operation_base(win_iocp_io_service& io_service,
|
||||||
|
invoke_func_type invoke_func, destroy_func_type destroy_func)
|
||||||
|
: win_iocp_io_service::operation(io_service, invoke_func, destroy_func),
|
||||||
|
io_service_(io_service)
|
||||||
|
{
|
||||||
|
io_service_.work_started();
|
||||||
|
}
|
||||||
|
|
||||||
|
~overlapped_operation_base()
|
||||||
|
{
|
||||||
|
io_service_.work_finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
win_iocp_io_service& io_service_;
|
||||||
|
asio::error_code ec_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Handler>
|
||||||
|
struct overlapped_operation
|
||||||
|
: public overlapped_operation_base
|
||||||
|
{
|
||||||
|
overlapped_operation(win_iocp_io_service& io_service,
|
||||||
|
Handler handler)
|
||||||
|
: overlapped_operation_base(io_service,
|
||||||
|
&overlapped_operation<Handler>::do_completion_impl,
|
||||||
|
&overlapped_operation<Handler>::destroy_impl),
|
||||||
|
handler_(handler)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Prevent copying and assignment.
|
||||||
|
overlapped_operation(const overlapped_operation&);
|
||||||
|
void operator=(const overlapped_operation&);
|
||||||
|
|
||||||
|
static void do_completion_impl(win_iocp_io_service::operation* op,
|
||||||
|
DWORD last_error, size_t bytes_transferred)
|
||||||
|
{
|
||||||
|
// Take ownership of the operation object.
|
||||||
|
typedef overlapped_operation<Handler> op_type;
|
||||||
|
op_type* handler_op(static_cast<op_type*>(op));
|
||||||
|
typedef handler_alloc_traits<Handler, op_type> alloc_traits;
|
||||||
|
handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
|
||||||
|
|
||||||
|
// Make a copy of the handler and error_code so that the memory can be
|
||||||
|
// deallocated before the upcall is made.
|
||||||
|
Handler handler(handler_op->handler_);
|
||||||
|
asio::error_code ec(handler_op->ec_);
|
||||||
|
if (last_error)
|
||||||
|
ec = asio::error_code(last_error,
|
||||||
|
asio::error::get_system_category());
|
||||||
|
|
||||||
|
// Free the memory associated with the handler.
|
||||||
|
ptr.reset();
|
||||||
|
|
||||||
|
// Make the upcall.
|
||||||
|
asio_handler_invoke_helpers::invoke(
|
||||||
|
bind_handler(handler, ec, bytes_transferred), &handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroy_impl(win_iocp_io_service::operation* op)
|
||||||
|
{
|
||||||
|
// Take ownership of the operation object.
|
||||||
|
typedef overlapped_operation<Handler> op_type;
|
||||||
|
op_type* handler_op(static_cast<op_type*>(op));
|
||||||
|
typedef handler_alloc_traits<Handler, op_type> alloc_traits;
|
||||||
|
handler_ptr<alloc_traits> ptr(handler_op->handler_, handler_op);
|
||||||
|
|
||||||
|
// A sub-object of the handler may be the true owner of the memory
|
||||||
|
// associated with the handler. Consequently, a local copy of the handler
|
||||||
|
// is required to ensure that any owning sub-object remains valid until
|
||||||
|
// after we have deallocated the memory here.
|
||||||
|
Handler handler(handler_op->handler_);
|
||||||
|
(void)handler;
|
||||||
|
|
||||||
|
// Free the memory associated with the handler.
|
||||||
|
ptr.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
Handler handler_;
|
||||||
|
};
|
||||||
|
|
||||||
|
overlapped_operation_base* ptr_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_IOCP)
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_DETAIL_WIN_IOCP_OVERLAPPED_PTR_HPP
|
|
@ -0,0 +1,118 @@
|
||||||
|
//
|
||||||
|
// overlapped_ptr.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_WINDOWS_OVERLAPPED_PTR_HPP
|
||||||
|
#define ASIO_WINDOWS_OVERLAPPED_PTR_HPP
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
# pragma once
|
||||||
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
#include "asio/io_service.hpp"
|
||||||
|
#include "asio/detail/noncopyable.hpp"
|
||||||
|
#include "asio/detail/win_iocp_overlapped_ptr.hpp"
|
||||||
|
|
||||||
|
#if !defined(ASIO_DISABLE_WINDOWS_OVERLAPPED_PTR)
|
||||||
|
# if defined(ASIO_HAS_IOCP)
|
||||||
|
# define ASIO_HAS_WINDOWS_OVERLAPPED_PTR 1
|
||||||
|
# endif // defined(ASIO_HAS_IOCP)
|
||||||
|
#endif // !defined(ASIO_DISABLE_WINDOWS_OVERLAPPED_PTR)
|
||||||
|
|
||||||
|
#if defined(ASIO_HAS_WINDOWS_OVERLAPPED_PTR) \
|
||||||
|
|| defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
namespace windows {
|
||||||
|
|
||||||
|
/// Wraps a handler to create an OVERLAPPED object for use with overlapped I/O.
|
||||||
|
/**
|
||||||
|
* A special-purpose smart pointer used to wrap an application handler so that
|
||||||
|
* it can be passed as the LPOVERLAPPED argument to overlapped I/O functions.
|
||||||
|
*
|
||||||
|
* @par Thread Safety
|
||||||
|
* @e Distinct @e objects: Safe.@n
|
||||||
|
* @e Shared @e objects: Unsafe.
|
||||||
|
*/
|
||||||
|
class overlapped_ptr
|
||||||
|
: private noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// Construct an empty overlapped_ptr.
|
||||||
|
overlapped_ptr()
|
||||||
|
: impl_()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct an overlapped_ptr to contain the specified handler.
|
||||||
|
template <typename Handler>
|
||||||
|
explicit overlapped_ptr(asio::io_service& io_service, Handler handler)
|
||||||
|
: impl_(io_service, handler)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Destructor automatically frees the OVERLAPPED object unless released.
|
||||||
|
~overlapped_ptr()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reset to empty.
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
impl_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reset to contain the specified handler, freeing any current OVERLAPPED
|
||||||
|
/// object.
|
||||||
|
template <typename Handler>
|
||||||
|
void reset(asio::io_service& io_service, Handler handler)
|
||||||
|
{
|
||||||
|
impl_.reset(io_service, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the contained OVERLAPPED object.
|
||||||
|
OVERLAPPED* get()
|
||||||
|
{
|
||||||
|
return impl_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the contained OVERLAPPED object.
|
||||||
|
const OVERLAPPED* get() const
|
||||||
|
{
|
||||||
|
return impl_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Release ownership of the OVERLAPPED object.
|
||||||
|
OVERLAPPED* release()
|
||||||
|
{
|
||||||
|
return impl_.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Post completion notification for overlapped operation. Releases ownership.
|
||||||
|
void complete(const asio::error_code& ec,
|
||||||
|
std::size_t bytes_transferred)
|
||||||
|
{
|
||||||
|
impl_.complete(ec, bytes_transferred);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
detail::win_iocp_overlapped_ptr impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace windows
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#endif // defined(ASIO_HAS_WINDOWS_OVERLAPPED_PTR)
|
||||||
|
// || defined(GENERATING_DOCUMENTATION)
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_WINDOWS_OVERLAPPED_PTR_HPP
|
Loading…
Reference in New Issue