191cdbe46SBenjamin Kietzman // Copyright (c) Benjamin Kietzman (github.com/bkietz) 291cdbe46SBenjamin Kietzman // 391cdbe46SBenjamin Kietzman // Distributed under the Boost Software License, Version 1.0. (See accompanying 491cdbe46SBenjamin Kietzman // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 591cdbe46SBenjamin Kietzman 60de54404SBenjamin Kietzman #ifndef DBUS_QUEUE_HPP 70de54404SBenjamin Kietzman #define DBUS_QUEUE_HPP 80de54404SBenjamin Kietzman 9cd8b76a3SBenjamin Kietzman #include <deque> 10da3eeb6aSEd Tanous #include <functional> 11cd8b76a3SBenjamin Kietzman #include <boost/asio.hpp> 12cd8b76a3SBenjamin Kietzman #include <boost/asio/detail/mutex.hpp> 13cd8b76a3SBenjamin Kietzman 14fc79e461SBenjamin Kietzman namespace dbus { 15fc79e461SBenjamin Kietzman namespace detail { 16cd8b76a3SBenjamin Kietzman 17cd8b76a3SBenjamin Kietzman template <typename Message> 18da3eeb6aSEd Tanous class queue { 19cd8b76a3SBenjamin Kietzman public: 20cd8b76a3SBenjamin Kietzman typedef ::boost::asio::detail::mutex mutex_type; 21cd8b76a3SBenjamin Kietzman typedef Message message_type; 22da3eeb6aSEd Tanous typedef std::function<void(boost::system::error_code, Message)> handler_type; 23cd8b76a3SBenjamin Kietzman 24cd8b76a3SBenjamin Kietzman private: 25cd8b76a3SBenjamin Kietzman boost::asio::io_service& io; 26cd8b76a3SBenjamin Kietzman mutex_type mutex; 27cd8b76a3SBenjamin Kietzman std::deque<message_type> messages; 28cd8b76a3SBenjamin Kietzman std::deque<handler_type> handlers; 29cd8b76a3SBenjamin Kietzman 30cd8b76a3SBenjamin Kietzman public: queue(boost::asio::io_service & io_service)31da3eeb6aSEd Tanous queue(boost::asio::io_service& io_service) : io(io_service) {} 32cd8b76a3SBenjamin Kietzman queue(const queue<Message> & m)33*01cae3feSEd Tanous queue(const queue<Message>& m) 34*01cae3feSEd Tanous : io(m.io), messages(m.messages), handlers(m.handlers) { 35*01cae3feSEd Tanous // TODO(ed) acquire the lock before copying messages and handlers 36*01cae3feSEd Tanous } 37*01cae3feSEd Tanous 38cd8b76a3SBenjamin Kietzman private: 39da3eeb6aSEd Tanous class closure { 40cd8b76a3SBenjamin Kietzman handler_type handler_; 41cd8b76a3SBenjamin Kietzman message_type message_; 42cd8b76a3SBenjamin Kietzman boost::system::error_code error_; 43cd8b76a3SBenjamin Kietzman 44cd8b76a3SBenjamin Kietzman public: operator ()()45cd8b76a3SBenjamin Kietzman void operator()() { handler_(error_, message_); } closure(handler_type h,Message m,boost::system::error_code e=boost::system::error_code ())460250ca19SEd Tanous closure(handler_type h, Message m, 47cd8b76a3SBenjamin Kietzman boost::system::error_code e = boost::system::error_code()) 48da3eeb6aSEd Tanous : handler_(h), message_(m), error_(e) {} 49cd8b76a3SBenjamin Kietzman }; 50cd8b76a3SBenjamin Kietzman 51cd8b76a3SBenjamin Kietzman public: push(message_type m)52da3eeb6aSEd Tanous void push(message_type m) { 53cd8b76a3SBenjamin Kietzman mutex_type::scoped_lock lock(mutex); 54cd8b76a3SBenjamin Kietzman if (handlers.empty()) 55cd8b76a3SBenjamin Kietzman messages.push_back(m); 56da3eeb6aSEd Tanous else { 57cd8b76a3SBenjamin Kietzman handler_type h = handlers.front(); 58cd8b76a3SBenjamin Kietzman handlers.pop_front(); 59cd8b76a3SBenjamin Kietzman 60cd8b76a3SBenjamin Kietzman lock.unlock(); 61cd8b76a3SBenjamin Kietzman 620250ca19SEd Tanous io.post(closure(h, m)); 63cd8b76a3SBenjamin Kietzman } 64cd8b76a3SBenjamin Kietzman } 65cd8b76a3SBenjamin Kietzman 66b2c2467dSBenjamin Kietzman template <typename MessageHandler> BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler,void (boost::system::error_code,message_type))67b2c2467dSBenjamin Kietzman inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler, 68da3eeb6aSEd Tanous void(boost::system::error_code, 69da3eeb6aSEd Tanous message_type)) 70da3eeb6aSEd Tanous async_pop(BOOST_ASIO_MOVE_ARG(MessageHandler) h) { 71cd8b76a3SBenjamin Kietzman typedef ::boost::asio::detail::async_result_init< 72da3eeb6aSEd Tanous MessageHandler, void(boost::system::error_code, message_type)> 73da3eeb6aSEd Tanous init_type; 74cd8b76a3SBenjamin Kietzman 75cd8b76a3SBenjamin Kietzman mutex_type::scoped_lock lock(mutex); 76da3eeb6aSEd Tanous if (messages.empty()) { 77b2c2467dSBenjamin Kietzman init_type init(BOOST_ASIO_MOVE_CAST(MessageHandler)(h)); 78cd8b76a3SBenjamin Kietzman 79cd8b76a3SBenjamin Kietzman handlers.push_back(init.handler); 80cd8b76a3SBenjamin Kietzman 81cd8b76a3SBenjamin Kietzman lock.unlock(); 82cd8b76a3SBenjamin Kietzman 83cd8b76a3SBenjamin Kietzman return init.result.get(); 84cd8b76a3SBenjamin Kietzman 85cd8b76a3SBenjamin Kietzman } else { 86cd8b76a3SBenjamin Kietzman message_type m = messages.front(); 87cd8b76a3SBenjamin Kietzman messages.pop_front(); 88cd8b76a3SBenjamin Kietzman 89cd8b76a3SBenjamin Kietzman lock.unlock(); 90cd8b76a3SBenjamin Kietzman 91b2c2467dSBenjamin Kietzman init_type init(BOOST_ASIO_MOVE_CAST(MessageHandler)(h)); 92cd8b76a3SBenjamin Kietzman 930250ca19SEd Tanous io.post(closure(init.handler, m)); 94cd8b76a3SBenjamin Kietzman 95cd8b76a3SBenjamin Kietzman return init.result.get(); 96cd8b76a3SBenjamin Kietzman } 97cd8b76a3SBenjamin Kietzman } 98cd8b76a3SBenjamin Kietzman }; 99cd8b76a3SBenjamin Kietzman 100fc79e461SBenjamin Kietzman } // namespace detail 101fc79e461SBenjamin Kietzman } // namespace dbus 102fc79e461SBenjamin Kietzman 1030de54404SBenjamin Kietzman #endif // DBUS_QUEUE_HPP 104