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