Add missing files

This commit is contained in:
Andrew Resch 2009-04-20 22:01:52 +00:00
parent 111b64d38b
commit d795a66ae9
3 changed files with 480 additions and 0 deletions

View File

@ -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

View File

@ -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

View File

@ -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