blob: c435af3f4e8a44207617aaabad8653216d5dcee6 [file] [log] [blame]
Ed Tanousc9b55212017-06-12 13:25:51 -07001// Copyright (c) Benjamin Kietzman (github.com/bkietz)
2//
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef DBUS_QUEUE_HPP
7#define DBUS_QUEUE_HPP
8
9#include <deque>
10#include <functional>
11#include <boost/asio.hpp>
12#include <boost/asio/detail/mutex.hpp>
13
14namespace dbus {
15namespace detail {
16
17template <typename Message>
18class queue {
19 public:
20 typedef ::boost::asio::detail::mutex mutex_type;
21 typedef Message message_type;
22 typedef std::function<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 queue(boost::asio::io_service& io_service) : io(io_service) {}
32
33 private:
34 class closure {
35 handler_type handler_;
36 message_type message_;
37 boost::system::error_code error_;
38
39 public:
40 void operator()() { handler_(error_, message_); }
41 closure(BOOST_ASIO_MOVE_ARG(handler_type) h, Message m,
42 boost::system::error_code e = boost::system::error_code())
43 : handler_(h), message_(m), error_(e) {}
44 };
45
46 public:
47 void push(message_type m) {
48 mutex_type::scoped_lock lock(mutex);
49 if (handlers.empty())
50 messages.push_back(m);
51 else {
52 handler_type h = handlers.front();
53 handlers.pop_front();
54
55 lock.unlock();
56
57 io.post(closure(BOOST_ASIO_MOVE_CAST(handler_type)(h), m));
58 }
59 }
60
61 template <typename MessageHandler>
62 inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler,
63 void(boost::system::error_code,
64 message_type))
65 async_pop(BOOST_ASIO_MOVE_ARG(MessageHandler) h) {
66 typedef ::boost::asio::detail::async_result_init<
67 MessageHandler, void(boost::system::error_code, message_type)>
68 init_type;
69
70 mutex_type::scoped_lock lock(mutex);
71 if (messages.empty()) {
72 init_type init(BOOST_ASIO_MOVE_CAST(MessageHandler)(h));
73
74 handlers.push_back(init.handler);
75
76 lock.unlock();
77
78 return init.result.get();
79
80 } else {
81 message_type m = messages.front();
82 messages.pop_front();
83
84 lock.unlock();
85
86 init_type init(BOOST_ASIO_MOVE_CAST(MessageHandler)(h));
87
88 io.post(closure(BOOST_ASIO_MOVE_CAST(handler_type)(init.handler), m));
89
90 return init.result.get();
91 }
92 }
93};
94
95} // namespace detail
96} // namespace dbus
97
98#endif // DBUS_QUEUE_HPP