From 24e0725efa5d441a0926e8694408245df774d11f Mon Sep 17 00:00:00 2001 From: chris Date: Mon, 22 Mar 2004 07:56:59 +0000 Subject: [PATCH] Added initial locking_dispatcher implementation. --- asio/include/Makefile.am | 6 +- asio/include/asio.hpp | 2 + asio/include/asio/basic_demuxer.hpp | 33 +-- .../include/asio/basic_locking_dispatcher.hpp | 139 ++++++++++ asio/include/asio/detail/bind_handler.hpp | 85 ++++++ .../detail/locking_dispatcher_service.hpp | 252 ++++++++++++++++++ asio/include/asio/locking_dispatcher.hpp | 43 +++ asio/include/asio/wrapped_handler.hpp | 119 +++++++++ asio/src/Makefile.am | 2 + asio/src/Makefile.bor | 2 + asio/src/Makefile.mgw | 1 + asio/src/Makefile.msc | 2 + 12 files changed, 658 insertions(+), 28 deletions(-) create mode 100644 asio/include/asio/basic_locking_dispatcher.hpp create mode 100644 asio/include/asio/detail/locking_dispatcher_service.hpp create mode 100644 asio/include/asio/locking_dispatcher.hpp create mode 100644 asio/include/asio/wrapped_handler.hpp diff --git a/asio/include/Makefile.am b/asio/include/Makefile.am index cf249b41..4f9ba83b 100644 --- a/asio/include/Makefile.am +++ b/asio/include/Makefile.am @@ -2,6 +2,7 @@ nobase_include_HEADERS = \ asio.hpp \ asio/basic_demuxer.hpp \ asio/basic_dgram_socket.hpp \ + asio/basic_locking_dispatcher.hpp \ asio/basic_socket_acceptor.hpp \ asio/basic_socket_connector.hpp \ asio/basic_stream_socket.hpp \ @@ -13,6 +14,7 @@ nobase_include_HEADERS = \ asio/detail/bind_handler.hpp \ asio/detail/buffer_resize_guard.hpp \ asio/detail/event.hpp \ + asio/detail/locking_dispatcher_service.hpp \ asio/detail/mutex.hpp \ asio/detail/pipe_select_interrupter.hpp \ asio/detail/pop_options.hpp \ @@ -57,6 +59,7 @@ nobase_include_HEADERS = \ asio/ipv4/address.hpp \ asio/ipv4/tcp.hpp \ asio/ipv4/udp.hpp \ + asio/locking_dispatcher.hpp \ asio/recv.hpp \ asio/send.hpp \ asio/service_factory.hpp \ @@ -66,7 +69,8 @@ nobase_include_HEADERS = \ asio/socket_option.hpp \ asio/stream_socket.hpp \ asio/timer.hpp \ - asio/timer_base.hpp + asio/timer_base.hpp \ + asio/wrapped_handler.hpp MAINTAINERCLEANFILES = \ Makefile.in diff --git a/asio/include/asio.hpp b/asio/include/asio.hpp index 44b4be9d..18e54359 100644 --- a/asio/include/asio.hpp +++ b/asio/include/asio.hpp @@ -17,6 +17,7 @@ #include "asio/basic_demuxer.hpp" #include "asio/basic_dgram_socket.hpp" +#include "asio/basic_locking_dispatcher.hpp" #include "asio/basic_socket_acceptor.hpp" #include "asio/basic_socket_connector.hpp" #include "asio/basic_stream_socket.hpp" @@ -31,6 +32,7 @@ #include "asio/ipv4/address.hpp" #include "asio/ipv4/tcp.hpp" #include "asio/ipv4/udp.hpp" +#include "asio/locking_dispatcher.hpp" #include "asio/recv.hpp" #include "asio/send.hpp" #include "asio/service_factory.hpp" diff --git a/asio/include/asio/basic_demuxer.hpp b/asio/include/asio/basic_demuxer.hpp index cad4f59d..5e71f679 100644 --- a/asio/include/asio/basic_demuxer.hpp +++ b/asio/include/asio/basic_demuxer.hpp @@ -22,6 +22,8 @@ #include "asio/detail/pop_options.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/signal_init.hpp" #include "asio/detail/winsock_init.hpp" @@ -162,31 +164,6 @@ public: service_.post(handler); } - template - class wrapped_handler - { - public: - wrapped_handler(basic_demuxer& demuxer, Handler handler) - : demuxer_(demuxer), - handler_(handler) - { - } - - void operator()() - { - demuxer_.dispatch(handler_); - } - - void operator()() const - { - demuxer_.dispatch(handler_); - } - - private: - basic_demuxer& demuxer_; - Handler handler_; - }; - /// Create a new handler that automatically dispatches the wrapped handler /// on the demuxer. /** @@ -199,9 +176,11 @@ public: * the handler must be: @code void handler(); @endcode */ template - wrapped_handler wrap(Handler handler) + wrapped_handler, Handler> wrap( + Handler handler) { - return wrapped_handler(*this, handler); + return wrapped_handler, Handler>(*this, + handler); } /// Obtain the service interface corresponding to the given type. diff --git a/asio/include/asio/basic_locking_dispatcher.hpp b/asio/include/asio/basic_locking_dispatcher.hpp new file mode 100644 index 00000000..1e5bf186 --- /dev/null +++ b/asio/include/asio/basic_locking_dispatcher.hpp @@ -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 +#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 +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())), + 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 + 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 + 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 + wrapped_handler, Handler> wrap( + Handler handler) + { + return wrapped_handler, 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 diff --git a/asio/include/asio/detail/bind_handler.hpp b/asio/include/asio/detail/bind_handler.hpp index a564c76d..7b1e875b 100644 --- a/asio/include/asio/detail/bind_handler.hpp +++ b/asio/include/asio/detail/bind_handler.hpp @@ -128,6 +128,91 @@ binder3 bind_handler(Handler handler, Arg1 arg1, return binder3(handler, arg1, arg2, arg3); } +template +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 +binder4 bind_handler(Handler handler, + Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) +{ + return binder4(handler, arg1, arg2, arg3, + arg4); +} + +template +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 +binder5 bind_handler(Handler handler, + Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) +{ + return binder5(handler, arg1, arg2, + arg3, arg4, arg5); +} + } // namespace detail } // namespace asio diff --git a/asio/include/asio/detail/locking_dispatcher_service.hpp b/asio/include/asio/detail/locking_dispatcher_service.hpp new file mode 100644 index 00000000..48cc243f --- /dev/null +++ b/asio/include/asio/detail/locking_dispatcher_service.hpp @@ -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 +#include "asio/detail/pop_options.hpp" + +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/mutex.hpp" + +namespace asio { +namespace detail { + +template +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 + 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); + 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); + last_waiter_ = last_waiter_->next_; + } + } + + // Request a dispatcher to invoke the given handler and return immediately. + template + 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); + 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); + 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 + 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 + void dispatch(impl_type& impl, Handler handler) + { + impl->dispatch(demuxer_, handler); + } + + // Request a dispatcher to invoke the given handler and return immediately. + template + 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 diff --git a/asio/include/asio/locking_dispatcher.hpp b/asio/include/asio/locking_dispatcher.hpp new file mode 100644 index 00000000..7c074252 --- /dev/null +++ b/asio/include/asio/locking_dispatcher.hpp @@ -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 + > locking_dispatcher; +#endif + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_LOCKING_DISPATCHER_HPP diff --git a/asio/include/asio/wrapped_handler.hpp b/asio/include/asio/wrapped_handler.hpp new file mode 100644 index 00000000..f6ff1ff3 --- /dev/null +++ b/asio/include/asio/wrapped_handler.hpp @@ -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 +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 + void operator()(Arg1 arg1) + { + dispatcher_.dispatch(detail::bind_handler(handler_, arg1)); + } + + template + void operator()(Arg1 arg1) const + { + dispatcher_.dispatch(detail::bind_handler(handler_, arg1)); + } + + template + void operator()(Arg1 arg1, Arg2 arg2) + { + dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2)); + } + + template + void operator()(Arg1 arg1, Arg2 arg2) const + { + dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2)); + } + + template + void operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3) + { + dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2, arg3)); + } + + template + void operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3) const + { + dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2, arg3)); + } + + template + void operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) + { + dispatcher_.dispatch( + detail::bind_handler(handler_, arg1, arg2, arg3, arg4)); + } + + template + void operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) const + { + dispatcher_.dispatch( + detail::bind_handler(handler_, arg1, arg2, arg3, arg4)); + } + + template + void operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) + { + dispatcher_.dispatch( + detail::bind_handler(handler_, arg1, arg2, arg3, arg4, arg5)); + } + + template + 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 diff --git a/asio/src/Makefile.am b/asio/src/Makefile.am index 993ae3c1..cd215972 100644 --- a/asio/src/Makefile.am +++ b/asio/src/Makefile.am @@ -9,6 +9,7 @@ noinst_PROGRAMS = \ tests/unit/dgram_socket_test \ tests/unit/error_handler_test \ tests/unit/fixed_buffer_test \ + tests/unit/locking_dispatcher_test \ tests/unit/socket_acceptor_test \ tests/unit/timer_test \ 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_error_handler_test_SOURCES = tests/unit/error_handler_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_timer_test_SOURCES = tests/unit/timer_test.cpp examples_chat_chat_client_SOURCES = examples/chat/chat_client.cpp diff --git a/asio/src/Makefile.bor b/asio/src/Makefile.bor index d411a4fc..668b542b 100644 --- a/asio/src/Makefile.bor +++ b/asio/src/Makefile.bor @@ -13,6 +13,7 @@ all: \ tests\unit\dgram_socket_test.exe \ tests\unit\error_handler_test.exe \ tests\unit\fixed_buffer_test.exe \ + tests\unit\locking_dispatcher_test.exe \ tests\unit\socket_acceptor_test.exe \ tests\unit\timer_test.exe \ examples\chat\chat_client.exe \ @@ -36,6 +37,7 @@ check: all @tests\unit\dgram_socket_test.exe @tests\unit\error_handler_test.exe @tests\unit\fixed_buffer_test.exe + @tests\unit\locking_dispatcher_test.exe @tests\unit\socket_acceptor_test.exe @tests\unit\timer_test.exe diff --git a/asio/src/Makefile.mgw b/asio/src/Makefile.mgw index 869020fa..b08fd4df 100644 --- a/asio/src/Makefile.mgw +++ b/asio/src/Makefile.mgw @@ -13,6 +13,7 @@ TEST_EXES = \ tests/unit/dgram_socket_test.exe \ tests/unit/error_handler_test.exe \ tests/unit/fixed_buffer_test.exe \ + tests/unit/locking_dispatcher_test.exe \ tests/unit/socket_acceptor_test.exe \ tests/unit/timer_test.exe diff --git a/asio/src/Makefile.msc b/asio/src/Makefile.msc index 2fc129c7..0f6c79ca 100644 --- a/asio/src/Makefile.msc +++ b/asio/src/Makefile.msc @@ -13,6 +13,7 @@ all: \ tests\unit\dgram_socket_test.exe \ tests\unit\error_handler_test.exe \ tests\unit\fixed_buffer_test.exe \ + tests\unit\locking_dispatcher_test.exe \ tests\unit\socket_acceptor_test.exe \ tests\unit\timer_test.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\error_handler_test.exe: tests\unit\error_handler_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\timer_test.exe: tests\unit\timer_test.obj examples\chat\chat_client.exe: examples\chat\chat_client.obj