xref: /openbmc/boost-dbus/include/dbus/detail/queue.hpp (revision a8b4eac45384d53a3848c17591ec02c8a02448dc)
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