blob: c435af3f4e8a44207617aaabad8653216d5dcee6 [file] [log] [blame]
// Copyright (c) Benjamin Kietzman (github.com/bkietz)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef DBUS_QUEUE_HPP
#define DBUS_QUEUE_HPP
#include <deque>
#include <functional>
#include <boost/asio.hpp>
#include <boost/asio/detail/mutex.hpp>
namespace dbus {
namespace detail {
template <typename Message>
class queue {
public:
typedef ::boost::asio::detail::mutex mutex_type;
typedef Message message_type;
typedef std::function<void(boost::system::error_code, Message)> handler_type;
private:
boost::asio::io_service& io;
mutex_type mutex;
std::deque<message_type> messages;
std::deque<handler_type> handlers;
public:
queue(boost::asio::io_service& io_service) : io(io_service) {}
private:
class closure {
handler_type handler_;
message_type message_;
boost::system::error_code error_;
public:
void operator()() { handler_(error_, message_); }
closure(BOOST_ASIO_MOVE_ARG(handler_type) h, Message m,
boost::system::error_code e = boost::system::error_code())
: handler_(h), message_(m), error_(e) {}
};
public:
void push(message_type m) {
mutex_type::scoped_lock lock(mutex);
if (handlers.empty())
messages.push_back(m);
else {
handler_type h = handlers.front();
handlers.pop_front();
lock.unlock();
io.post(closure(BOOST_ASIO_MOVE_CAST(handler_type)(h), m));
}
}
template <typename MessageHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(MessageHandler,
void(boost::system::error_code,
message_type))
async_pop(BOOST_ASIO_MOVE_ARG(MessageHandler) h) {
typedef ::boost::asio::detail::async_result_init<
MessageHandler, void(boost::system::error_code, message_type)>
init_type;
mutex_type::scoped_lock lock(mutex);
if (messages.empty()) {
init_type init(BOOST_ASIO_MOVE_CAST(MessageHandler)(h));
handlers.push_back(init.handler);
lock.unlock();
return init.result.get();
} else {
message_type m = messages.front();
messages.pop_front();
lock.unlock();
init_type init(BOOST_ASIO_MOVE_CAST(MessageHandler)(h));
io.post(closure(BOOST_ASIO_MOVE_CAST(handler_type)(init.handler), m));
return init.result.get();
}
}
};
} // namespace detail
} // namespace dbus
#endif // DBUS_QUEUE_HPP