-Boost Software License - Version 1.0 - August 17th, 2003\r
-\r
-Permission is hereby granted, free of charge, to any person or organization\r
-obtaining a copy of the software and accompanying documentation covered by\r
-this license (the "Software") to use, reproduce, display, distribute,\r
-execute, and transmit the Software, and to prepare derivative works of the\r
-Software, and to permit third-parties to whom the Software is furnished to\r
-do so, all subject to the following:\r
-\r
-The copyright notices in the Software and this entire statement, including\r
-the above license grant, this restriction and the following disclaimer,\r
-must be included in all copies of the Software, in whole or in part, and\r
-all derivative works of the Software, unless such copies or derivative\r
-works are solely in the form of machine-executable object code generated by\r
-a source language processor.\r
-\r
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
-FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\r
-SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\r
-FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\r
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\r
-DEALINGS IN THE SOFTWARE.\r
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
-// \r
-// Copyright (c) 2009, 2010 Boris Schaeling <boris@highscore.de> \r
-// \r
-// Distributed under the Boost Software License, Version 1.0. (See accompanying \r
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) \r
-// \r
-\r
-#ifndef BOOST_ASIO_POSIX_BASIC_SIGNAL_HANDLER_HPP \r
-#define BOOST_ASIO_POSIX_BASIC_SIGNAL_HANDLER_HPP \r
-\r
-#include <boost/asio.hpp> \r
-#include <signal.h> \r
-\r
-namespace boost { \r
-namespace asio { \r
-namespace posix { \r
-\r
-template <typename Service> \r
-class basic_signal_handler \r
- : public boost::asio::basic_io_object<Service> \r
-{ \r
-public: \r
- explicit basic_signal_handler(boost::asio::io_service &io_service) \r
- : boost::asio::basic_io_object<Service>(io_service) \r
- { \r
- } \r
-\r
- void add_signal(int signal, int flags = 0, sigset_t *mask = 0) \r
- { \r
- this->service.add_signal(this->implementation, signal, flags, mask); \r
- } \r
-\r
- void remove_signal(int signal) \r
- { \r
- this->service.remove_signal(this->implementation, signal); \r
- } \r
-\r
- int wait() \r
- { \r
- boost::system::error_code ec; \r
- int signal = this->service.wait(this->implementation, ec); \r
- boost::asio::detail::throw_error(ec); \r
- return signal; \r
- } \r
-\r
- int wait(boost::system::error_code &ec) \r
- { \r
- return this->service.wait(this->implementation, ec); \r
- } \r
-\r
- template <typename Handler> \r
- void async_wait(Handler handler) \r
- { \r
- this->service.async_wait(this->implementation, handler); \r
- } \r
-}; \r
-\r
-} \r
-} \r
-} \r
-\r
-#endif \r
+//
+// Copyright (c) 2009, 2010 Boris Schaeling <boris@highscore.de>
+//
+// 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 BOOST_ASIO_POSIX_BASIC_SIGNAL_HANDLER_HPP
+#define BOOST_ASIO_POSIX_BASIC_SIGNAL_HANDLER_HPP
+
+#include <boost/asio.hpp>
+#include <signal.h>
+
+namespace boost {
+namespace asio {
+namespace posix {
+
+template <typename Service>
+class basic_signal_handler
+ : public boost::asio::basic_io_object<Service>
+{
+public:
+ explicit basic_signal_handler(boost::asio::io_service &io_service)
+ : boost::asio::basic_io_object<Service>(io_service)
+ {
+ }
+
+ void add_signal(int signal, int flags = 0, sigset_t *mask = 0)
+ {
+ this->service.add_signal(this->implementation, signal, flags, mask);
+ }
+
+ void remove_signal(int signal)
+ {
+ this->service.remove_signal(this->implementation, signal);
+ }
+
+ int wait()
+ {
+ boost::system::error_code ec;
+ int signal = this->service.wait(this->implementation, ec);
+ boost::asio::detail::throw_error(ec);
+ return signal;
+ }
+
+ int wait(boost::system::error_code &ec)
+ {
+ return this->service.wait(this->implementation, ec);
+ }
+
+ template <typename Handler>
+ void async_wait(Handler handler)
+ {
+ this->service.async_wait(this->implementation, handler);
+ }
+};
+
+}
+}
+}
+
+#endif
-// \r
-// Copyright (c) 2009, 2010 Boris Schaeling <boris@highscore.de> \r
-// \r
-// Distributed under the Boost Software License, Version 1.0. (See accompanying \r
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) \r
-// \r
-\r
-#ifndef BOOST_ASIO_POSIX_BASIC_SIGNAL_HANDLER_SERVICE_HPP \r
-#define BOOST_ASIO_POSIX_BASIC_SIGNAL_HANDLER_SERVICE_HPP \r
-\r
-#include "signal_handler_impl.hpp" \r
-#include <boost/asio.hpp> \r
-#include <boost/thread.hpp> \r
-#include <boost/bind.hpp> \r
-#include <boost/shared_ptr.hpp> \r
-#include <boost/weak_ptr.hpp> \r
-#include <boost/scoped_ptr.hpp> \r
-#include <boost/system/error_code.hpp> \r
-#include <boost/system/system_error.hpp> \r
-#include <cstring> \r
-#include <signal.h> \r
-#include <unistd.h> \r
-\r
-namespace boost { \r
-namespace asio { \r
-namespace posix { \r
-\r
-template <typename SignalHandlerImplementation = signal_handler_impl> \r
-class basic_signal_handler_service \r
- : public boost::asio::io_service::service \r
-{ \r
-public: \r
- static boost::asio::io_service::id id; \r
-\r
- explicit basic_signal_handler_service(boost::asio::io_service &io_service) \r
- : boost::asio::io_service::service(io_service), \r
- async_wait_work_(new boost::asio::io_service::work(async_wait_io_service_)), \r
- async_wait_thread_(boost::bind(&boost::asio::io_service::run, &async_wait_io_service_)) \r
- { \r
- } \r
-\r
- virtual ~basic_signal_handler_service()\r
- { \r
- // The async_wait thread will finish when async_wait_work_ is reset as all asynchronous \r
- // operations have been aborted and were discarded before (in destroy). \r
- async_wait_work_.reset(); \r
-\r
- // Event processing is stopped to discard queued operations. \r
- async_wait_io_service_.stop(); \r
-\r
- // The async_wait thread is joined to make sure the signal handler service is \r
- // destroyed _after_ the thread is finished (not that the thread tries to access \r
- // instance properties which don't exist anymore). \r
- async_wait_thread_.join(); \r
- } \r
-\r
- typedef boost::shared_ptr<SignalHandlerImplementation> implementation_type; \r
-\r
- void construct(implementation_type &impl) \r
- { \r
- // We must count the I/O objects and can't rely on the shared pointer impl_ \r
- // as an asynchronous call can hold a shared pointer at any time, too, thus \r
- // preventing the implementation to be destroyed in destroy(). \r
- ++count_; \r
-\r
- implementation_type shared_impl = impl_.lock(); \r
- if (shared_impl) \r
- { \r
- impl = shared_impl; \r
- } \r
- else \r
- { \r
- impl.reset(new SignalHandlerImplementation()); \r
- impl_ = impl; \r
- fd_ = impl->write_end(); \r
- } \r
- } \r
-\r
- void destroy(implementation_type &impl) \r
- { \r
- // If an asynchronous call is currently waiting for a signal \r
- // we must interrupt the blocked call to make sure it returns. \r
- if (!--count_) \r
- impl->destroy(); \r
-\r
- impl.reset(); \r
- } \r
-\r
- void add_signal(implementation_type &impl, int signal, int flags, sigset_t *mask) \r
- { \r
- struct sigaction act, oldact; \r
-\r
- std::memset(&act, 0, sizeof(struct sigaction)); \r
- act.sa_handler = basic_signal_handler_service<SignalHandlerImplementation>::signal_handler; \r
- act.sa_flags = flags; \r
- if (mask) \r
- act.sa_mask = *mask; \r
-\r
- int res = sigaction(signal, &act, &oldact); \r
- if (res == -1) \r
- { \r
- boost::system::system_error e(boost::system::error_code(errno, boost::system::get_system_category()), "boost::asio::posix::basic_signal_handler_service::add_signal: sigaction failed"); \r
- boost::throw_exception(e); \r
- } \r
-\r
- impl->add_signal(signal, oldact); \r
- } \r
-\r
- void remove_signal(implementation_type &impl, int signal) \r
- { \r
- impl->remove_signal(signal); \r
- } \r
-\r
- int wait(implementation_type &impl, boost::system::error_code &ec) \r
- { \r
- return impl->wait(ec); \r
- } \r
-\r
- template <typename Handler> \r
- class wait_operation \r
- { \r
- public: \r
- wait_operation(implementation_type &impl, boost::asio::io_service &io_service, Handler handler) \r
- : impl_(impl), \r
- io_service_(io_service), \r
- work_(io_service), \r
- handler_(handler) \r
- { \r
- } \r
-\r
- void operator()() const \r
- { \r
- implementation_type impl = impl_.lock(); \r
- if (impl) \r
- { \r
- boost::system::error_code ec; \r
- int signal = impl->wait(ec); \r
- this->io_service_.post(boost::asio::detail::bind_handler(handler_, ec, signal)); \r
- } \r
- else \r
- { \r
- this->io_service_.post(boost::asio::detail::bind_handler(handler_, boost::asio::error::operation_aborted, 0)); \r
- } \r
- } \r
-\r
- private: \r
- boost::weak_ptr<SignalHandlerImplementation> impl_; \r
- boost::asio::io_service &io_service_; \r
- boost::asio::io_service::work work_; \r
- Handler handler_; \r
- }; \r
-\r
- template <typename Handler> \r
- void async_wait(implementation_type &impl, Handler handler) \r
- { \r
- this->async_wait_io_service_.post(wait_operation<Handler>(impl, this->get_io_service(), handler)); \r
- } \r
-\r
-private: \r
- void shutdown_service() \r
- { \r
- } \r
-\r
- static void signal_handler(int signal) \r
- { \r
- while (::write(fd_, &signal, sizeof(signal)) == -1 && errno == EINTR); \r
- } \r
-\r
- static int count_; \r
- static boost::weak_ptr<SignalHandlerImplementation> impl_; \r
- static int fd_; \r
- boost::asio::io_service async_wait_io_service_; \r
- boost::scoped_ptr<boost::asio::io_service::work> async_wait_work_; \r
- boost::thread async_wait_thread_; \r
-}; \r
-\r
-template <typename SignalHandlerImplementation> \r
-boost::asio::io_service::id basic_signal_handler_service<SignalHandlerImplementation>::id; \r
-\r
-template <typename SignalHandlerImplementation> \r
-int basic_signal_handler_service<SignalHandlerImplementation>::count_ = 0; \r
-\r
-template <typename SignalHandlerImplementation> \r
-boost::weak_ptr<SignalHandlerImplementation> basic_signal_handler_service<SignalHandlerImplementation>::impl_; \r
-\r
-template <typename SignalHandlerImplementation> \r
-int basic_signal_handler_service<SignalHandlerImplementation>::fd_; \r
-\r
-} \r
-} \r
-} \r
-\r
-#endif \r
+//
+// Copyright (c) 2009, 2010 Boris Schaeling <boris@highscore.de>
+//
+// 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 BOOST_ASIO_POSIX_BASIC_SIGNAL_HANDLER_SERVICE_HPP
+#define BOOST_ASIO_POSIX_BASIC_SIGNAL_HANDLER_SERVICE_HPP
+
+#include "signal_handler_impl.hpp"
+#include <boost/asio.hpp>
+#include <boost/thread.hpp>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/system/system_error.hpp>
+#include <cstring>
+#include <signal.h>
+#include <unistd.h>
+
+namespace boost {
+namespace asio {
+namespace posix {
+
+template <typename SignalHandlerImplementation = signal_handler_impl>
+class basic_signal_handler_service
+ : public boost::asio::io_service::service
+{
+public:
+ static boost::asio::io_service::id id;
+
+ explicit basic_signal_handler_service(boost::asio::io_service &io_service)
+ : boost::asio::io_service::service(io_service),
+ async_wait_work_(new boost::asio::io_service::work(async_wait_io_service_)),
+ async_wait_thread_(boost::bind(&boost::asio::io_service::run, &async_wait_io_service_))
+ {
+ }
+
+ virtual ~basic_signal_handler_service()
+ {
+ // The async_wait thread will finish when async_wait_work_ is reset as all asynchronous
+ // operations have been aborted and were discarded before (in destroy).
+ async_wait_work_.reset();
+
+ // Event processing is stopped to discard queued operations.
+ async_wait_io_service_.stop();
+
+ // The async_wait thread is joined to make sure the signal handler service is
+ // destroyed _after_ the thread is finished (not that the thread tries to access
+ // instance properties which don't exist anymore).
+ async_wait_thread_.join();
+ }
+
+ typedef boost::shared_ptr<SignalHandlerImplementation> implementation_type;
+
+ void construct(implementation_type &impl)
+ {
+ // We must count the I/O objects and can't rely on the shared pointer impl_
+ // as an asynchronous call can hold a shared pointer at any time, too, thus
+ // preventing the implementation to be destroyed in destroy().
+ ++count_;
+
+ implementation_type shared_impl = impl_.lock();
+ if (shared_impl)
+ {
+ impl = shared_impl;
+ }
+ else
+ {
+ impl.reset(new SignalHandlerImplementation());
+ impl_ = impl;
+ fd_ = impl->write_end();
+ }
+ }
+
+ void destroy(implementation_type &impl)
+ {
+ // If an asynchronous call is currently waiting for a signal
+ // we must interrupt the blocked call to make sure it returns.
+ if (!--count_)
+ impl->destroy();
+
+ impl.reset();
+ }
+
+ void add_signal(implementation_type &impl, int signal, int flags, sigset_t *mask)
+ {
+ struct sigaction act, oldact;
+
+ std::memset(&act, 0, sizeof(struct sigaction));
+ act.sa_handler = basic_signal_handler_service<SignalHandlerImplementation>::signal_handler;
+ act.sa_flags = flags;
+ if (mask)
+ act.sa_mask = *mask;
+
+ int res = sigaction(signal, &act, &oldact);
+ if (res == -1)
+ {
+ boost::system::system_error e(boost::system::error_code(errno, boost::system::get_system_category()), "boost::asio::posix::basic_signal_handler_service::add_signal: sigaction failed");
+ boost::throw_exception(e);
+ }
+
+ impl->add_signal(signal, oldact);
+ }
+
+ void remove_signal(implementation_type &impl, int signal)
+ {
+ impl->remove_signal(signal);
+ }
+
+ int wait(implementation_type &impl, boost::system::error_code &ec)
+ {
+ return impl->wait(ec);
+ }
+
+ template <typename Handler>
+ class wait_operation
+ {
+ public:
+ wait_operation(implementation_type &impl, boost::asio::io_service &io_service, Handler handler)
+ : impl_(impl),
+ io_service_(io_service),
+ work_(io_service),
+ handler_(handler)
+ {
+ }
+
+ void operator()() const
+ {
+ implementation_type impl = impl_.lock();
+ if (impl)
+ {
+ boost::system::error_code ec;
+ int signal = impl->wait(ec);
+ this->io_service_.post(boost::asio::detail::bind_handler(handler_, ec, signal));
+ }
+ else
+ {
+ this->io_service_.post(boost::asio::detail::bind_handler(handler_, boost::asio::error::operation_aborted, 0));
+ }
+ }
+
+ private:
+ boost::weak_ptr<SignalHandlerImplementation> impl_;
+ boost::asio::io_service &io_service_;
+ boost::asio::io_service::work work_;
+ Handler handler_;
+ };
+
+ template <typename Handler>
+ void async_wait(implementation_type &impl, Handler handler)
+ {
+ this->async_wait_io_service_.post(wait_operation<Handler>(impl, this->get_io_service(), handler));
+ }
+
+private:
+ void shutdown_service()
+ {
+ }
+
+ static void signal_handler(int signal)
+ {
+ while (::write(fd_, &signal, sizeof(signal)) == -1 && errno == EINTR);
+ }
+
+ static int count_;
+ static boost::weak_ptr<SignalHandlerImplementation> impl_;
+ static int fd_;
+ boost::asio::io_service async_wait_io_service_;
+ boost::scoped_ptr<boost::asio::io_service::work> async_wait_work_;
+ boost::thread async_wait_thread_;
+};
+
+template <typename SignalHandlerImplementation>
+boost::asio::io_service::id basic_signal_handler_service<SignalHandlerImplementation>::id;
+
+template <typename SignalHandlerImplementation>
+int basic_signal_handler_service<SignalHandlerImplementation>::count_ = 0;
+
+template <typename SignalHandlerImplementation>
+boost::weak_ptr<SignalHandlerImplementation> basic_signal_handler_service<SignalHandlerImplementation>::impl_;
+
+template <typename SignalHandlerImplementation>
+int basic_signal_handler_service<SignalHandlerImplementation>::fd_;
+
+}
+}
+}
+
+#endif
-// \r
-// Copyright (c) 2009, 2010 Boris Schaeling <boris@highscore.de> \r
-// \r
-// Distributed under the Boost Software License, Version 1.0. (See accompanying \r
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) \r
-// \r
-\r
-#ifndef BOOST_ASIO_POSIX_SIGNAL_HANDLER_HPP \r
-#define BOOST_ASIO_POSIX_SIGNAL_HANDLER_HPP \r
-\r
-#include "basic_signal_handler.hpp" \r
-#include "basic_signal_handler_service.hpp" \r
-\r
-namespace boost { \r
-namespace asio { \r
-namespace posix { \r
-\r
-typedef basic_signal_handler<basic_signal_handler_service<> > signal_handler; \r
-\r
-} \r
-} \r
-} \r
-\r
-#endif \r
+//
+// Copyright (c) 2009, 2010 Boris Schaeling <boris@highscore.de>
+//
+// 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 BOOST_ASIO_POSIX_SIGNAL_HANDLER_HPP
+#define BOOST_ASIO_POSIX_SIGNAL_HANDLER_HPP
+
+#include "basic_signal_handler.hpp"
+#include "basic_signal_handler_service.hpp"
+
+namespace boost {
+namespace asio {
+namespace posix {
+
+typedef basic_signal_handler<basic_signal_handler_service<> > signal_handler;
+
+}
+}
+}
+
+#endif
-// \r
-// Copyright (c) 2009, 2010 Boris Schaeling <boris@highscore.de> \r
-// \r
-// Distributed under the Boost Software License, Version 1.0. (See accompanying \r
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) \r
-// \r
-\r
-#ifndef BOOST_ASIO_POSIX_SIGNAL_HANDLER_IMPL_HPP \r
-#define BOOST_ASIO_POSIX_SIGNAL_HANDLER_IMPL_HPP \r
-\r
-#include <boost/asio.hpp> \r
-#include <boost/thread.hpp> \r
-#include <boost/bind.hpp> \r
-#include <boost/system/error_code.hpp> \r
-#include <boost/system/system_error.hpp> \r
-#include <map> \r
-#include <deque> \r
-#include <signal.h> \r
-#include <unistd.h> \r
-\r
-namespace boost { \r
-namespace asio { \r
-namespace posix { \r
-\r
-class signal_handler_impl \r
-{ \r
-public: \r
- signal_handler_impl() \r
- : sd_(signal_handler_io_service_), \r
- run_(true) \r
- { \r
- int res = pipe(fds_); \r
- if (res == -1) \r
- { \r
- boost::system::system_error e(boost::system::error_code(errno, boost::system::get_system_category()), "boost::asio::posix::signal_handler_impl::signal_handler_impl: pipe failed"); \r
- boost::throw_exception(e); \r
- } \r
-\r
- sd_.assign(fds_[0]); \r
- begin_read(); \r
- signal_handler_thread_ = boost::thread(boost::bind(&boost::asio::io_service::run, &signal_handler_io_service_)); \r
- } \r
-\r
- ~signal_handler_impl() \r
- { \r
- for (sigactions_t::iterator it = sigactions_.begin(); it != sigactions_.end(); ++it) \r
- sigaction(it->first, &it->second, 0); \r
-\r
- close(fds_[1]); \r
- sd_.close(); \r
-\r
- signal_handler_io_service_.stop(); \r
- signal_handler_thread_.join(); \r
- } \r
-\r
- int write_end() const \r
- { \r
- return fds_[1]; \r
- } \r
-\r
- void add_signal(int signal, struct sigaction oldact) \r
- { \r
- sigactions_.insert(sigactions_t::value_type(signal, oldact)); \r
- } \r
-\r
- void remove_signal(int signal) \r
- { \r
- sigactions_t::iterator it = sigactions_.find(signal); \r
- if (it != sigactions_.end()) \r
- { \r
- sigaction(signal, &it->second, 0); \r
- sigactions_.erase(it); \r
- } \r
- } \r
-\r
- void destroy() \r
- { \r
- boost::unique_lock<boost::mutex> lock(pending_signals_mutex_); \r
- run_ = false; \r
- pending_signals_cond_.notify_all(); \r
- } \r
-\r
- int wait(boost::system::error_code &ec) \r
- { \r
- boost::unique_lock<boost::mutex> lock(pending_signals_mutex_); \r
- while (run_ && pending_signals_.empty()) \r
- pending_signals_cond_.wait(lock); \r
- int signal = 0; \r
- if (!pending_signals_.empty()) \r
- { \r
- signal = pending_signals_.front(); \r
- pending_signals_.pop_front(); \r
- } \r
- else \r
- ec = boost::asio::error::operation_aborted; \r
- return signal; \r
- } \r
-\r
-private: \r
- void begin_read() \r
- { \r
- boost::asio::async_read(sd_, boost::asio::buffer(signal_buffer_), \r
- boost::bind(&signal_handler_impl::end_read, this, \r
- boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); \r
- } \r
-\r
- void end_read(const boost::system::error_code &ec, std::size_t bytes_transferred) \r
- { \r
- if (!ec) \r
- { \r
- boost::unique_lock<boost::mutex> lock(pending_signals_mutex_); \r
- pending_signals_.push_back(signal_buffer_[0]); \r
- pending_signals_cond_.notify_all(); \r
- begin_read(); \r
- } \r
- } \r
-\r
- int fds_[2]; \r
- boost::asio::io_service signal_handler_io_service_; \r
- boost::thread signal_handler_thread_; \r
- boost::asio::posix::stream_descriptor sd_; \r
- int signal_buffer_[1]; \r
- typedef std::map<int, struct sigaction> sigactions_t; \r
- sigactions_t sigactions_; \r
- boost::mutex pending_signals_mutex_; \r
- boost::condition_variable_any pending_signals_cond_; \r
- bool run_; \r
- std::deque<int> pending_signals_; \r
-}; \r
-\r
-} \r
-} \r
-} \r
-\r
-#endif \r
+//
+// Copyright (c) 2009, 2010 Boris Schaeling <boris@highscore.de>
+//
+// 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 BOOST_ASIO_POSIX_SIGNAL_HANDLER_IMPL_HPP
+#define BOOST_ASIO_POSIX_SIGNAL_HANDLER_IMPL_HPP
+
+#include <boost/asio.hpp>
+#include <boost/thread.hpp>
+#include <boost/bind.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/system/system_error.hpp>
+#include <map>
+#include <deque>
+#include <signal.h>
+#include <unistd.h>
+
+namespace boost {
+namespace asio {
+namespace posix {
+
+class signal_handler_impl
+{
+public:
+ signal_handler_impl()
+ : sd_(signal_handler_io_service_),
+ run_(true)
+ {
+ int res = pipe(fds_);
+ if (res == -1)
+ {
+ boost::system::system_error e(boost::system::error_code(errno, boost::system::get_system_category()), "boost::asio::posix::signal_handler_impl::signal_handler_impl: pipe failed");
+ boost::throw_exception(e);
+ }
+
+ sd_.assign(fds_[0]);
+ begin_read();
+ signal_handler_thread_ = boost::thread(boost::bind(&boost::asio::io_service::run, &signal_handler_io_service_));
+ }
+
+ ~signal_handler_impl()
+ {
+ for (sigactions_t::iterator it = sigactions_.begin(); it != sigactions_.end(); ++it)
+ sigaction(it->first, &it->second, 0);
+
+ close(fds_[1]);
+ sd_.close();
+
+ signal_handler_io_service_.stop();
+ signal_handler_thread_.join();
+ }
+
+ int write_end() const
+ {
+ return fds_[1];
+ }
+
+ void add_signal(int signal, struct sigaction oldact)
+ {
+ sigactions_.insert(sigactions_t::value_type(signal, oldact));
+ }
+
+ void remove_signal(int signal)
+ {
+ sigactions_t::iterator it = sigactions_.find(signal);
+ if (it != sigactions_.end())
+ {
+ sigaction(signal, &it->second, 0);
+ sigactions_.erase(it);
+ }
+ }
+
+ void destroy()
+ {
+ boost::unique_lock<boost::mutex> lock(pending_signals_mutex_);
+ run_ = false;
+ pending_signals_cond_.notify_all();
+ }
+
+ int wait(boost::system::error_code &ec)
+ {
+ boost::unique_lock<boost::mutex> lock(pending_signals_mutex_);
+ while (run_ && pending_signals_.empty())
+ pending_signals_cond_.wait(lock);
+ int signal = 0;
+ if (!pending_signals_.empty())
+ {
+ signal = pending_signals_.front();
+ pending_signals_.pop_front();
+ }
+ else
+ ec = boost::asio::error::operation_aborted;
+ return signal;
+ }
+
+private:
+ void begin_read()
+ {
+ boost::asio::async_read(sd_, boost::asio::buffer(signal_buffer_),
+ boost::bind(&signal_handler_impl::end_read, this,
+ boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
+ }
+
+ void end_read(const boost::system::error_code &ec, std::size_t bytes_transferred)
+ {
+ if (!ec)
+ {
+ boost::unique_lock<boost::mutex> lock(pending_signals_mutex_);
+ pending_signals_.push_back(signal_buffer_[0]);
+ pending_signals_cond_.notify_all();
+ begin_read();
+ }
+ }
+
+ int fds_[2];
+ boost::asio::io_service signal_handler_io_service_;
+ boost::thread signal_handler_thread_;
+ boost::asio::posix::stream_descriptor sd_;
+ int signal_buffer_[1];
+ typedef std::map<int, struct sigaction> sigactions_t;
+ sigactions_t sigactions_;
+ boost::mutex pending_signals_mutex_;
+ boost::condition_variable_any pending_signals_cond_;
+ bool run_;
+ std::deque<int> pending_signals_;
+};
+
+}
+}
+}
+
+#endif