1 #ifndef DBUS_QUEUE_HPP 2 #define DBUS_QUEUE_HPP 3 4 #include <deque> 5 #include <functional> 6 #include <boost/asio.hpp> 7 #include <boost/asio/detail/mutex.hpp> 8 9 10 namespace dbus { 11 namespace detail { 12 13 using std::function; 14 15 template<typename Message> 16 class queue 17 { 18 public: 19 typedef ::boost::asio::detail::mutex mutex_type; 20 typedef Message message_type; 21 typedef function< 22 void(boost::system::error_code, Message)> handler_type; 23 24 private: 25 boost::asio::io_service& io; 26 mutex_type mutex; 27 std::deque<message_type> messages; 28 std::deque<handler_type> handlers; 29 30 public: 31 32 queue(boost::asio::io_service& io_service) 33 : io(io_service) 34 {} 35 36 private: 37 class closure 38 { 39 handler_type handler_; 40 message_type message_; 41 boost::system::error_code error_; 42 43 public: 44 void operator()() { handler_(error_, message_); } 45 closure( 46 BOOST_ASIO_MOVE_ARG(handler_type) h, 47 Message m, 48 boost::system::error_code e = boost::system::error_code()) 49 : handler_(h), 50 message_(m), 51 error_(e) 52 {} 53 }; 54 55 public: 56 57 void push(message_type m) 58 { 59 mutex_type::scoped_lock lock(mutex); 60 if(handlers.empty()) 61 messages.push_back(m); 62 else 63 { 64 handler_type h = handlers.front(); 65 handlers.pop_front(); 66 67 lock.unlock(); 68 69 io.post( 70 closure(BOOST_ASIO_MOVE_CAST(handler_type)(h), m)); 71 } 72 } 73 74 template<typename PopHandler> 75 inline BOOST_ASIO_INITFN_RESULT_TYPE(PopHandler, 76 void(boost::system::error_code, message_type)) 77 async_pop(BOOST_ASIO_MOVE_ARG(PopHandler) h) 78 { 79 typedef ::boost::asio::detail::async_result_init< 80 PopHandler, void(boost::system::error_code, message_type)> init_type; 81 82 mutex_type::scoped_lock lock(mutex); 83 if(messages.empty()) 84 { 85 init_type init(BOOST_ASIO_MOVE_CAST(PopHandler)(h)); 86 87 handlers.push_back(init.handler); 88 89 lock.unlock(); 90 91 return init.result.get(); 92 93 } else { 94 message_type m = messages.front(); 95 messages.pop_front(); 96 97 lock.unlock(); 98 99 init_type init(BOOST_ASIO_MOVE_CAST(PopHandler)(h)); 100 101 io.post(closure( 102 BOOST_ASIO_MOVE_CAST(handler_type)(init.handler), m)); 103 104 return init.result.get(); 105 } 106 } 107 }; 108 109 110 } // namespace detail 111 } // namespace dbus 112 113 #endif // DBUS_QUEUE_HPP 114