Added initial locking_dispatcher implementation.
This commit is contained in:
parent
271db66458
commit
24e0725efa
@ -2,6 +2,7 @@ nobase_include_HEADERS = \
|
|||||||
asio.hpp \
|
asio.hpp \
|
||||||
asio/basic_demuxer.hpp \
|
asio/basic_demuxer.hpp \
|
||||||
asio/basic_dgram_socket.hpp \
|
asio/basic_dgram_socket.hpp \
|
||||||
|
asio/basic_locking_dispatcher.hpp \
|
||||||
asio/basic_socket_acceptor.hpp \
|
asio/basic_socket_acceptor.hpp \
|
||||||
asio/basic_socket_connector.hpp \
|
asio/basic_socket_connector.hpp \
|
||||||
asio/basic_stream_socket.hpp \
|
asio/basic_stream_socket.hpp \
|
||||||
@ -13,6 +14,7 @@ nobase_include_HEADERS = \
|
|||||||
asio/detail/bind_handler.hpp \
|
asio/detail/bind_handler.hpp \
|
||||||
asio/detail/buffer_resize_guard.hpp \
|
asio/detail/buffer_resize_guard.hpp \
|
||||||
asio/detail/event.hpp \
|
asio/detail/event.hpp \
|
||||||
|
asio/detail/locking_dispatcher_service.hpp \
|
||||||
asio/detail/mutex.hpp \
|
asio/detail/mutex.hpp \
|
||||||
asio/detail/pipe_select_interrupter.hpp \
|
asio/detail/pipe_select_interrupter.hpp \
|
||||||
asio/detail/pop_options.hpp \
|
asio/detail/pop_options.hpp \
|
||||||
@ -57,6 +59,7 @@ nobase_include_HEADERS = \
|
|||||||
asio/ipv4/address.hpp \
|
asio/ipv4/address.hpp \
|
||||||
asio/ipv4/tcp.hpp \
|
asio/ipv4/tcp.hpp \
|
||||||
asio/ipv4/udp.hpp \
|
asio/ipv4/udp.hpp \
|
||||||
|
asio/locking_dispatcher.hpp \
|
||||||
asio/recv.hpp \
|
asio/recv.hpp \
|
||||||
asio/send.hpp \
|
asio/send.hpp \
|
||||||
asio/service_factory.hpp \
|
asio/service_factory.hpp \
|
||||||
@ -66,7 +69,8 @@ nobase_include_HEADERS = \
|
|||||||
asio/socket_option.hpp \
|
asio/socket_option.hpp \
|
||||||
asio/stream_socket.hpp \
|
asio/stream_socket.hpp \
|
||||||
asio/timer.hpp \
|
asio/timer.hpp \
|
||||||
asio/timer_base.hpp
|
asio/timer_base.hpp \
|
||||||
|
asio/wrapped_handler.hpp
|
||||||
|
|
||||||
MAINTAINERCLEANFILES = \
|
MAINTAINERCLEANFILES = \
|
||||||
Makefile.in
|
Makefile.in
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "asio/basic_demuxer.hpp"
|
#include "asio/basic_demuxer.hpp"
|
||||||
#include "asio/basic_dgram_socket.hpp"
|
#include "asio/basic_dgram_socket.hpp"
|
||||||
|
#include "asio/basic_locking_dispatcher.hpp"
|
||||||
#include "asio/basic_socket_acceptor.hpp"
|
#include "asio/basic_socket_acceptor.hpp"
|
||||||
#include "asio/basic_socket_connector.hpp"
|
#include "asio/basic_socket_connector.hpp"
|
||||||
#include "asio/basic_stream_socket.hpp"
|
#include "asio/basic_stream_socket.hpp"
|
||||||
@ -31,6 +32,7 @@
|
|||||||
#include "asio/ipv4/address.hpp"
|
#include "asio/ipv4/address.hpp"
|
||||||
#include "asio/ipv4/tcp.hpp"
|
#include "asio/ipv4/tcp.hpp"
|
||||||
#include "asio/ipv4/udp.hpp"
|
#include "asio/ipv4/udp.hpp"
|
||||||
|
#include "asio/locking_dispatcher.hpp"
|
||||||
#include "asio/recv.hpp"
|
#include "asio/recv.hpp"
|
||||||
#include "asio/send.hpp"
|
#include "asio/send.hpp"
|
||||||
#include "asio/service_factory.hpp"
|
#include "asio/service_factory.hpp"
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include "asio/detail/pop_options.hpp"
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
#include "asio/service_factory.hpp"
|
#include "asio/service_factory.hpp"
|
||||||
|
#include "asio/wrapped_handler.hpp"
|
||||||
|
#include "asio/detail/bind_handler.hpp"
|
||||||
#include "asio/detail/service_registry.hpp"
|
#include "asio/detail/service_registry.hpp"
|
||||||
#include "asio/detail/signal_init.hpp"
|
#include "asio/detail/signal_init.hpp"
|
||||||
#include "asio/detail/winsock_init.hpp"
|
#include "asio/detail/winsock_init.hpp"
|
||||||
@ -162,31 +164,6 @@ public:
|
|||||||
service_.post(handler);
|
service_.post(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Handler>
|
|
||||||
class wrapped_handler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
wrapped_handler(basic_demuxer<Demuxer_Service>& demuxer, Handler handler)
|
|
||||||
: demuxer_(demuxer),
|
|
||||||
handler_(handler)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()()
|
|
||||||
{
|
|
||||||
demuxer_.dispatch(handler_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()() const
|
|
||||||
{
|
|
||||||
demuxer_.dispatch(handler_);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
basic_demuxer<Demuxer_Service>& demuxer_;
|
|
||||||
Handler handler_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Create a new handler that automatically dispatches the wrapped handler
|
/// Create a new handler that automatically dispatches the wrapped handler
|
||||||
/// on the demuxer.
|
/// on the demuxer.
|
||||||
/**
|
/**
|
||||||
@ -199,9 +176,11 @@ public:
|
|||||||
* the handler must be: @code void handler(); @endcode
|
* the handler must be: @code void handler(); @endcode
|
||||||
*/
|
*/
|
||||||
template <typename Handler>
|
template <typename Handler>
|
||||||
wrapped_handler<Handler> wrap(Handler handler)
|
wrapped_handler<basic_demuxer<Demuxer_Service>, Handler> wrap(
|
||||||
|
Handler handler)
|
||||||
{
|
{
|
||||||
return wrapped_handler<Handler>(*this, handler);
|
return wrapped_handler<basic_demuxer<Demuxer_Service>, Handler>(*this,
|
||||||
|
handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Obtain the service interface corresponding to the given type.
|
/// Obtain the service interface corresponding to the given type.
|
||||||
|
139
asio/include/asio/basic_locking_dispatcher.hpp
Normal file
139
asio/include/asio/basic_locking_dispatcher.hpp
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
//
|
||||||
|
// basic_locking_dispatcher.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003, 2004 Christopher M. Kohlhoff (chris@kohlhoff.com)
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software and its
|
||||||
|
// documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
// the above copyright notice appears in all copies and that both the copyright
|
||||||
|
// notice and this permission notice appear in supporting documentation. This
|
||||||
|
// software is provided "as is" without express or implied warranty, and with
|
||||||
|
// no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_BASIC_LOCKING_DISPATCHER_HPP
|
||||||
|
#define ASIO_BASIC_LOCKING_DISPATCHER_HPP
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#include "asio/wrapped_handler.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
/// The basic_locking_dispatcher class template provides the ability to post
|
||||||
|
/// and dispatch handlers with the guarantee that none of those handlers will
|
||||||
|
/// execute concurrently. Most applications will use the locking_dispatcher
|
||||||
|
/// typedef.
|
||||||
|
template <typename Service>
|
||||||
|
class basic_locking_dispatcher
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the service that will be used to provide locking dispatcher
|
||||||
|
/// operations.
|
||||||
|
typedef Service service_type;
|
||||||
|
|
||||||
|
/// The native implementation type of the locking dispatcher.
|
||||||
|
typedef typename service_type::impl_type impl_type;
|
||||||
|
|
||||||
|
/// The demuxer type for this dispatcher.
|
||||||
|
typedef typename service_type::demuxer_type demuxer_type;
|
||||||
|
|
||||||
|
/// Constructor.
|
||||||
|
/**
|
||||||
|
* Constructs the locking dispatcher.
|
||||||
|
*
|
||||||
|
* @param d The demuxer object that the locking dispatcher will use to
|
||||||
|
* dispatch handlers that are ready to be run.
|
||||||
|
*/
|
||||||
|
explicit basic_locking_dispatcher(demuxer_type& d)
|
||||||
|
: service_(d.get_service(service_factory<Service>())),
|
||||||
|
impl_(service_.null())
|
||||||
|
{
|
||||||
|
service_.create(impl_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Destructor.
|
||||||
|
~basic_locking_dispatcher()
|
||||||
|
{
|
||||||
|
service_.destroy(impl_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Request the dispatcher to invoke the given handler.
|
||||||
|
/**
|
||||||
|
* This function is used to ask the dispatcher to execute the given handler.
|
||||||
|
*
|
||||||
|
* The dispatcher guarantees that the handler will only be called in a thread
|
||||||
|
* in which the underlying demuxer's run member function is currently being
|
||||||
|
* invoked. It also guarantees that only one handler executed through this
|
||||||
|
* dispatcher will be invoked at a time. The handler may be executed inside
|
||||||
|
* this function if the guarantee can be met.
|
||||||
|
*
|
||||||
|
* @param handler The handler to be called. The dispatcher will make
|
||||||
|
* a copy of the handler object as required. The equivalent function
|
||||||
|
* signature of the handler must be: @code void handler(); @endcode
|
||||||
|
*/
|
||||||
|
template <typename Handler>
|
||||||
|
void dispatch(Handler handler)
|
||||||
|
{
|
||||||
|
service_.dispatch(impl_, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Request the dispatcher to invoke the given handler and return
|
||||||
|
/// immediately.
|
||||||
|
/**
|
||||||
|
* This function is used to ask the dispatcher to execute the given handler,
|
||||||
|
* but without allowing the dispatcher to call the handler from inside this
|
||||||
|
* function.
|
||||||
|
*
|
||||||
|
* The dispatcher guarantees that the handler will only be called in a thread
|
||||||
|
* in which the underlying demuxer's run member function is currently being
|
||||||
|
* invoked. It also guarantees that only one handler executed through this
|
||||||
|
* dispatcher will be invoked at a time.
|
||||||
|
*
|
||||||
|
* @param handler The handler to be called. The dispatcher will make
|
||||||
|
* a copy of the handler object as required. The equivalent function
|
||||||
|
* signature of the handler must be: @code void handler(); @endcode
|
||||||
|
*/
|
||||||
|
template <typename Handler>
|
||||||
|
void post(Handler handler)
|
||||||
|
{
|
||||||
|
service_.post(impl_, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new handler that automatically dispatches the wrapped handler
|
||||||
|
/// on the dispatcher.
|
||||||
|
/**
|
||||||
|
* This function is used to create a new handler function object that, when
|
||||||
|
* invoked, will automatically pass the wrapped handler to the dispatcher's
|
||||||
|
* dispatch function.
|
||||||
|
*
|
||||||
|
* @param handler The handler to be wrapped. The dispatcher will make a copy
|
||||||
|
* of the handler object as required. The equivalent function signature of
|
||||||
|
* the handler must be: @code void handler(); @endcode
|
||||||
|
*/
|
||||||
|
template <typename Handler>
|
||||||
|
wrapped_handler<basic_locking_dispatcher<Service>, Handler> wrap(
|
||||||
|
Handler handler)
|
||||||
|
{
|
||||||
|
return wrapped_handler<basic_locking_dispatcher<Service>, Handler>(*this,
|
||||||
|
handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// The backend service implementation.
|
||||||
|
service_type& service_;
|
||||||
|
|
||||||
|
/// The underlying native implementation.
|
||||||
|
impl_type impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_BASIC_LOCKING_DISPATCHER_HPP
|
@ -128,6 +128,91 @@ binder3<Handler, Arg1, Arg2, Arg3> bind_handler(Handler handler, Arg1 arg1,
|
|||||||
return binder3<Handler, Arg1, Arg2, Arg3>(handler, arg1, arg2, arg3);
|
return binder3<Handler, Arg1, Arg2, Arg3>(handler, arg1, arg2, arg3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
|
||||||
|
typename Arg4>
|
||||||
|
class binder4
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
binder4(Handler handler, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
|
||||||
|
: handler_(handler),
|
||||||
|
arg1_(arg1),
|
||||||
|
arg2_(arg2),
|
||||||
|
arg3_(arg3),
|
||||||
|
arg4_(arg4)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()()
|
||||||
|
{
|
||||||
|
handler_(arg1_, arg2_, arg3_, arg4_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()() const
|
||||||
|
{
|
||||||
|
handler_(arg1_, arg2_, arg3_, arg4_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Handler handler_;
|
||||||
|
Arg1 arg1_;
|
||||||
|
Arg2 arg2_;
|
||||||
|
Arg3 arg3_;
|
||||||
|
Arg4 arg4_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
|
||||||
|
typename Arg4>
|
||||||
|
binder4<Handler, Arg1, Arg2, Arg3, Arg4> bind_handler(Handler handler,
|
||||||
|
Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
|
||||||
|
{
|
||||||
|
return binder4<Handler, Arg1, Arg2, Arg3, Arg4>(handler, arg1, arg2, arg3,
|
||||||
|
arg4);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
|
||||||
|
typename Arg4, typename Arg5>
|
||||||
|
class binder5
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
binder5(Handler handler, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4,
|
||||||
|
Arg5 arg5)
|
||||||
|
: handler_(handler),
|
||||||
|
arg1_(arg1),
|
||||||
|
arg2_(arg2),
|
||||||
|
arg3_(arg3),
|
||||||
|
arg4_(arg4),
|
||||||
|
arg5_(arg5)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()()
|
||||||
|
{
|
||||||
|
handler_(arg1_, arg2_, arg3_, arg4_, arg5_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()() const
|
||||||
|
{
|
||||||
|
handler_(arg1_, arg2_, arg3_, arg4_, arg5_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Handler handler_;
|
||||||
|
Arg1 arg1_;
|
||||||
|
Arg2 arg2_;
|
||||||
|
Arg3 arg3_;
|
||||||
|
Arg4 arg4_;
|
||||||
|
Arg5 arg5_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
|
||||||
|
typename Arg4, typename Arg5>
|
||||||
|
binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5> bind_handler(Handler handler,
|
||||||
|
Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
|
||||||
|
{
|
||||||
|
return binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>(handler, arg1, arg2,
|
||||||
|
arg3, arg4, arg5);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace asio
|
} // namespace asio
|
||||||
|
|
||||||
|
252
asio/include/asio/detail/locking_dispatcher_service.hpp
Normal file
252
asio/include/asio/detail/locking_dispatcher_service.hpp
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
//
|
||||||
|
// locking_dispatcher_service.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003, 2004 Christopher M. Kohlhoff (chris@kohlhoff.com)
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software and its
|
||||||
|
// documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
// the above copyright notice appears in all copies and that both the copyright
|
||||||
|
// notice and this permission notice appear in supporting documentation. This
|
||||||
|
// software is provided "as is" without express or implied warranty, and with
|
||||||
|
// no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_DETAIL_LOCKING_DISPATCHER_SERVICE_HPP
|
||||||
|
#define ASIO_DETAIL_LOCKING_DISPATCHER_SERVICE_HPP
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/bind_handler.hpp"
|
||||||
|
#include "asio/detail/mutex.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename Demuxer>
|
||||||
|
class locking_dispatcher_service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class dispatcher_impl
|
||||||
|
: private boost::noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Constructor.
|
||||||
|
dispatcher_impl()
|
||||||
|
: first_waiter_(),
|
||||||
|
last_waiter_(),
|
||||||
|
mutex_()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request a dispatcher to invoke the given handler.
|
||||||
|
template <typename Handler>
|
||||||
|
void dispatch(Demuxer& demuxer, Handler handler)
|
||||||
|
{
|
||||||
|
detail::mutex::scoped_lock lock(mutex_);
|
||||||
|
|
||||||
|
if (first_waiter_ == 0)
|
||||||
|
{
|
||||||
|
// This handler now has the lock, so can be dispatched immediately.
|
||||||
|
first_waiter_ = last_waiter_ = new waiter<Handler>(handler);
|
||||||
|
lock.unlock();
|
||||||
|
demuxer.dispatch(waiter_handler(demuxer, *this));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Another waiter already holds the lock, so this handler must join
|
||||||
|
// the list of waiters. The handler will be posted automatically when
|
||||||
|
// its turn comes.
|
||||||
|
last_waiter_->next_ = new waiter<Handler>(handler);
|
||||||
|
last_waiter_ = last_waiter_->next_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request a dispatcher to invoke the given handler and return immediately.
|
||||||
|
template <typename Handler>
|
||||||
|
void post(Demuxer& demuxer, Handler handler)
|
||||||
|
{
|
||||||
|
detail::mutex::scoped_lock lock(mutex_);
|
||||||
|
|
||||||
|
if (first_waiter_ == 0)
|
||||||
|
{
|
||||||
|
// This handler now has the lock, so can be posted immediately.
|
||||||
|
first_waiter_ = last_waiter_ = new waiter<Handler>(handler);
|
||||||
|
lock.unlock();
|
||||||
|
demuxer.post(waiter_handler(demuxer, *this));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Another waiter already holds the lock, so this handler must join
|
||||||
|
// the list of waiters. The handler will be posted automatically when
|
||||||
|
// its turn comes.
|
||||||
|
last_waiter_->next_ = new waiter<Handler>(handler);
|
||||||
|
last_waiter_ = last_waiter_->next_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Base class for all waiter types.
|
||||||
|
class waiter_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
waiter_base()
|
||||||
|
: next_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~waiter_base()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void call() = 0;
|
||||||
|
|
||||||
|
waiter_base* next_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Class template for a waiter.
|
||||||
|
template <typename Handler>
|
||||||
|
class waiter
|
||||||
|
: public waiter_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
waiter(Handler handler)
|
||||||
|
: handler_(handler)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void call()
|
||||||
|
{
|
||||||
|
handler_();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Handler handler_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper class to allow waiting handlers to be dispatched.
|
||||||
|
class waiter_handler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
waiter_handler(Demuxer& demuxer, dispatcher_impl& impl)
|
||||||
|
: demuxer_(demuxer),
|
||||||
|
impl_(impl)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()()
|
||||||
|
{
|
||||||
|
do_upcall();
|
||||||
|
detail::mutex::scoped_lock lock(impl_.mutex_);
|
||||||
|
waiter_base* tmp = impl_.first_waiter_;
|
||||||
|
impl_.first_waiter_ = impl_.first_waiter_->next_;
|
||||||
|
delete tmp;
|
||||||
|
if (impl_.first_waiter_)
|
||||||
|
{
|
||||||
|
lock.unlock();
|
||||||
|
demuxer_.post(*this);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
impl_.last_waiter_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void do_upcall()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
impl_.first_waiter_->call();
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Demuxer& demuxer_;
|
||||||
|
dispatcher_impl& impl_;
|
||||||
|
};
|
||||||
|
|
||||||
|
friend class waiter_handler;
|
||||||
|
|
||||||
|
// The start of the list of waiters for the dispatcher. If this pointer
|
||||||
|
// is non-null then it indicates that a handler holds the lock.
|
||||||
|
waiter_base* first_waiter_;
|
||||||
|
|
||||||
|
// The end of the list of waiters for the dispatcher.
|
||||||
|
waiter_base* last_waiter_;
|
||||||
|
|
||||||
|
// Mutex to protect access to internal data.
|
||||||
|
detail::mutex mutex_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The native type of the locking dispatcher.
|
||||||
|
typedef dispatcher_impl* impl_type;
|
||||||
|
|
||||||
|
// Return a null locking dispatcher implementation.
|
||||||
|
static impl_type null()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor.
|
||||||
|
locking_dispatcher_service(Demuxer& d)
|
||||||
|
: demuxer_(d)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// The demuxer type for this service.
|
||||||
|
typedef Demuxer demuxer_type;
|
||||||
|
|
||||||
|
// Get the demuxer associated with the service.
|
||||||
|
demuxer_type& demuxer()
|
||||||
|
{
|
||||||
|
return demuxer_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new locking dispatcher implementation.
|
||||||
|
void create(impl_type& impl)
|
||||||
|
{
|
||||||
|
impl = new dispatcher_impl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy a locking dispatcher implementation.
|
||||||
|
void destroy(impl_type& impl)
|
||||||
|
{
|
||||||
|
if (impl != null())
|
||||||
|
{
|
||||||
|
delete impl;
|
||||||
|
impl = null();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request a dispatcher to invoke the given handler.
|
||||||
|
template <typename Handler>
|
||||||
|
void dispatch(impl_type& impl, Handler handler)
|
||||||
|
{
|
||||||
|
impl->dispatch(demuxer_, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request a dispatcher to invoke the given handler and return immediately.
|
||||||
|
template <typename Handler>
|
||||||
|
void post(impl_type& impl, Handler handler)
|
||||||
|
{
|
||||||
|
impl->post(demuxer_, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// The demuxer used for dispatching handlers.
|
||||||
|
Demuxer& demuxer_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_DETAIL_LOCKING_DISPATCHER_SERVICE_HPP
|
43
asio/include/asio/locking_dispatcher.hpp
Normal file
43
asio/include/asio/locking_dispatcher.hpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
//
|
||||||
|
// locking_dispatcher.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003, 2004 Christopher M. Kohlhoff (chris@kohlhoff.com)
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software and its
|
||||||
|
// documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
// the above copyright notice appears in all copies and that both the copyright
|
||||||
|
// notice and this permission notice appear in supporting documentation. This
|
||||||
|
// software is provided "as is" without express or implied warranty, and with
|
||||||
|
// no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_LOCKING_DISPATCHER_HPP
|
||||||
|
#define ASIO_LOCKING_DISPATCHER_HPP
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
#include "asio/basic_locking_dispatcher.hpp"
|
||||||
|
#include "asio/demuxer.hpp"
|
||||||
|
#include "asio/detail/locking_dispatcher_service.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
/// Typedef for the typical usage of locking_dispatcher.
|
||||||
|
#if defined(GENERATING_DOCUMENTATION)
|
||||||
|
typedef basic_locking_dispatcher
|
||||||
|
<
|
||||||
|
implementation_defined
|
||||||
|
> locking_dispatcher;
|
||||||
|
#else
|
||||||
|
typedef basic_locking_dispatcher
|
||||||
|
<
|
||||||
|
detail::locking_dispatcher_service<demuxer>
|
||||||
|
> locking_dispatcher;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_LOCKING_DISPATCHER_HPP
|
119
asio/include/asio/wrapped_handler.hpp
Normal file
119
asio/include/asio/wrapped_handler.hpp
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
//
|
||||||
|
// wrapped_handler.hpp
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~
|
||||||
|
//
|
||||||
|
// Copyright (c) 2003, 2004 Christopher M. Kohlhoff (chris@kohlhoff.com)
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, distribute and sell this software and its
|
||||||
|
// documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
// the above copyright notice appears in all copies and that both the copyright
|
||||||
|
// notice and this permission notice appear in supporting documentation. This
|
||||||
|
// software is provided "as is" without express or implied warranty, and with
|
||||||
|
// no claim as to its suitability for any purpose.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ASIO_WRAPPED_HANDLER_HPP
|
||||||
|
#define ASIO_WRAPPED_HANDLER_HPP
|
||||||
|
|
||||||
|
#include "asio/detail/push_options.hpp"
|
||||||
|
|
||||||
|
#include "asio/detail/bind_handler.hpp"
|
||||||
|
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
template <typename Dispatcher, typename Handler>
|
||||||
|
class wrapped_handler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wrapped_handler(Dispatcher& dispatcher, Handler handler)
|
||||||
|
: dispatcher_(dispatcher),
|
||||||
|
handler_(handler)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()()
|
||||||
|
{
|
||||||
|
dispatcher_.dispatch(handler_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()() const
|
||||||
|
{
|
||||||
|
dispatcher_.dispatch(handler_);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Arg1>
|
||||||
|
void operator()(Arg1 arg1)
|
||||||
|
{
|
||||||
|
dispatcher_.dispatch(detail::bind_handler(handler_, arg1));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Arg1>
|
||||||
|
void operator()(Arg1 arg1) const
|
||||||
|
{
|
||||||
|
dispatcher_.dispatch(detail::bind_handler(handler_, arg1));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Arg1, typename Arg2>
|
||||||
|
void operator()(Arg1 arg1, Arg2 arg2)
|
||||||
|
{
|
||||||
|
dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Arg1, typename Arg2>
|
||||||
|
void operator()(Arg1 arg1, Arg2 arg2) const
|
||||||
|
{
|
||||||
|
dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Arg1, typename Arg2, typename Arg3>
|
||||||
|
void operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3)
|
||||||
|
{
|
||||||
|
dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2, arg3));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Arg1, typename Arg2, typename Arg3>
|
||||||
|
void operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3) const
|
||||||
|
{
|
||||||
|
dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2, arg3));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
|
||||||
|
void operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
|
||||||
|
{
|
||||||
|
dispatcher_.dispatch(
|
||||||
|
detail::bind_handler(handler_, arg1, arg2, arg3, arg4));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
|
||||||
|
void operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) const
|
||||||
|
{
|
||||||
|
dispatcher_.dispatch(
|
||||||
|
detail::bind_handler(handler_, arg1, arg2, arg3, arg4));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
|
||||||
|
typename Arg5>
|
||||||
|
void operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
|
||||||
|
{
|
||||||
|
dispatcher_.dispatch(
|
||||||
|
detail::bind_handler(handler_, arg1, arg2, arg3, arg4, arg5));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,
|
||||||
|
typename Arg5>
|
||||||
|
void operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) const
|
||||||
|
{
|
||||||
|
dispatcher_.dispatch(
|
||||||
|
detail::bind_handler(handler_, arg1, arg2, arg3, arg4, arg5));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Dispatcher& dispatcher_;
|
||||||
|
Handler handler_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace asio
|
||||||
|
|
||||||
|
#include "asio/detail/pop_options.hpp"
|
||||||
|
|
||||||
|
#endif // ASIO_WRAPPED_HANDLER_HPP
|
@ -9,6 +9,7 @@ noinst_PROGRAMS = \
|
|||||||
tests/unit/dgram_socket_test \
|
tests/unit/dgram_socket_test \
|
||||||
tests/unit/error_handler_test \
|
tests/unit/error_handler_test \
|
||||||
tests/unit/fixed_buffer_test \
|
tests/unit/fixed_buffer_test \
|
||||||
|
tests/unit/locking_dispatcher_test \
|
||||||
tests/unit/socket_acceptor_test \
|
tests/unit/socket_acceptor_test \
|
||||||
tests/unit/timer_test \
|
tests/unit/timer_test \
|
||||||
examples/chat/chat_client \
|
examples/chat/chat_client \
|
||||||
@ -47,6 +48,7 @@ tests_unit_demuxer_test_SOURCES = tests/unit/demuxer_test.cpp
|
|||||||
tests_unit_dgram_socket_test_SOURCES = tests/unit/dgram_socket_test.cpp
|
tests_unit_dgram_socket_test_SOURCES = tests/unit/dgram_socket_test.cpp
|
||||||
tests_unit_error_handler_test_SOURCES = tests/unit/error_handler_test.cpp
|
tests_unit_error_handler_test_SOURCES = tests/unit/error_handler_test.cpp
|
||||||
tests_unit_fixed_buffer_test_SOURCES = tests/unit/fixed_buffer_test.cpp
|
tests_unit_fixed_buffer_test_SOURCES = tests/unit/fixed_buffer_test.cpp
|
||||||
|
tests_unit_locking_dispatcher_test_SOURCES = tests/unit/locking_dispatcher_test.cpp
|
||||||
tests_unit_socket_acceptor_test_SOURCES = tests/unit/socket_acceptor_test.cpp
|
tests_unit_socket_acceptor_test_SOURCES = tests/unit/socket_acceptor_test.cpp
|
||||||
tests_unit_timer_test_SOURCES = tests/unit/timer_test.cpp
|
tests_unit_timer_test_SOURCES = tests/unit/timer_test.cpp
|
||||||
examples_chat_chat_client_SOURCES = examples/chat/chat_client.cpp
|
examples_chat_chat_client_SOURCES = examples/chat/chat_client.cpp
|
||||||
|
@ -13,6 +13,7 @@ all: \
|
|||||||
tests\unit\dgram_socket_test.exe \
|
tests\unit\dgram_socket_test.exe \
|
||||||
tests\unit\error_handler_test.exe \
|
tests\unit\error_handler_test.exe \
|
||||||
tests\unit\fixed_buffer_test.exe \
|
tests\unit\fixed_buffer_test.exe \
|
||||||
|
tests\unit\locking_dispatcher_test.exe \
|
||||||
tests\unit\socket_acceptor_test.exe \
|
tests\unit\socket_acceptor_test.exe \
|
||||||
tests\unit\timer_test.exe \
|
tests\unit\timer_test.exe \
|
||||||
examples\chat\chat_client.exe \
|
examples\chat\chat_client.exe \
|
||||||
@ -36,6 +37,7 @@ check: all
|
|||||||
@tests\unit\dgram_socket_test.exe
|
@tests\unit\dgram_socket_test.exe
|
||||||
@tests\unit\error_handler_test.exe
|
@tests\unit\error_handler_test.exe
|
||||||
@tests\unit\fixed_buffer_test.exe
|
@tests\unit\fixed_buffer_test.exe
|
||||||
|
@tests\unit\locking_dispatcher_test.exe
|
||||||
@tests\unit\socket_acceptor_test.exe
|
@tests\unit\socket_acceptor_test.exe
|
||||||
@tests\unit\timer_test.exe
|
@tests\unit\timer_test.exe
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ TEST_EXES = \
|
|||||||
tests/unit/dgram_socket_test.exe \
|
tests/unit/dgram_socket_test.exe \
|
||||||
tests/unit/error_handler_test.exe \
|
tests/unit/error_handler_test.exe \
|
||||||
tests/unit/fixed_buffer_test.exe \
|
tests/unit/fixed_buffer_test.exe \
|
||||||
|
tests/unit/locking_dispatcher_test.exe \
|
||||||
tests/unit/socket_acceptor_test.exe \
|
tests/unit/socket_acceptor_test.exe \
|
||||||
tests/unit/timer_test.exe
|
tests/unit/timer_test.exe
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ all: \
|
|||||||
tests\unit\dgram_socket_test.exe \
|
tests\unit\dgram_socket_test.exe \
|
||||||
tests\unit\error_handler_test.exe \
|
tests\unit\error_handler_test.exe \
|
||||||
tests\unit\fixed_buffer_test.exe \
|
tests\unit\fixed_buffer_test.exe \
|
||||||
|
tests\unit\locking_dispatcher_test.exe \
|
||||||
tests\unit\socket_acceptor_test.exe \
|
tests\unit\socket_acceptor_test.exe \
|
||||||
tests\unit\timer_test.exe \
|
tests\unit\timer_test.exe \
|
||||||
examples\chat\chat_client.exe \
|
examples\chat\chat_client.exe \
|
||||||
@ -37,6 +38,7 @@ tests\unit\demuxer_test.exe: tests\unit\demuxer_test.obj
|
|||||||
tests\unit\dgram_socket_test.exe: tests\unit\dgram_socket_test.obj
|
tests\unit\dgram_socket_test.exe: tests\unit\dgram_socket_test.obj
|
||||||
tests\unit\error_handler_test.exe: tests\unit\error_handler_test.obj
|
tests\unit\error_handler_test.exe: tests\unit\error_handler_test.obj
|
||||||
tests\unit\fixed_buffer_test.exe: tests\unit\fixed_buffer_test.obj
|
tests\unit\fixed_buffer_test.exe: tests\unit\fixed_buffer_test.obj
|
||||||
|
tests\unit\locking_dispatcher_test.exe: tests\unit\locking_dispatcher_test.obj
|
||||||
tests\unit\socket_acceptor_test.exe: tests\unit\socket_acceptor_test.obj
|
tests\unit\socket_acceptor_test.exe: tests\unit\socket_acceptor_test.obj
|
||||||
tests\unit\timer_test.exe: tests\unit\timer_test.obj
|
tests\unit\timer_test.exe: tests\unit\timer_test.obj
|
||||||
examples\chat\chat_client.exe: examples\chat\chat_client.obj
|
examples\chat\chat_client.exe: examples\chat\chat_client.obj
|
||||||
|
Loading…
Reference in New Issue
Block a user