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