// Copyright (c) 2012-2015, The CryptoNote developers, The Bytecoin developers // // This file is part of Bytecoin. // // Bytecoin is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Bytecoin is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with Bytecoin. If not, see . #pragma once #include #include "IntrusiveLinkedList.h" #include "System/Event.h" #include "System/InterruptedException.h" namespace CryptoNote { template class MessageQueue { public: MessageQueue(System::Dispatcher& dispatcher); const MessageType& front(); void pop(); void push(const MessageType& message); void stop(); typename IntrusiveLinkedList>::hook& getHook(); private: void wait(); std::queue messageQueue; System::Event event; bool stopped; typename IntrusiveLinkedList>::hook hook; }; template class MesageQueueGuard { public: MesageQueueGuard(MessageQueueContainer& container, MessageQueue& messageQueue) : container(container), messageQueue(messageQueue) { container.addMessageQueue(messageQueue); } MesageQueueGuard(const MesageQueueGuard& other) = delete; MesageQueueGuard& operator=(const MesageQueueGuard& other) = delete; ~MesageQueueGuard() { container.removeMessageQueue(messageQueue); } private: MessageQueueContainer& container; MessageQueue& messageQueue; }; template MessageQueue::MessageQueue(System::Dispatcher& dispatcher) : event(dispatcher), stopped(false) {} template void MessageQueue::wait() { if (messageQueue.empty()) { if (stopped) { throw System::InterruptedException(); } event.clear(); while (!event.get()) { event.wait(); } } } template const MessageType& MessageQueue::front() { wait(); return messageQueue.front(); } template void MessageQueue::pop() { wait(); messageQueue.pop(); } template void MessageQueue::push(const MessageType& message) { messageQueue.push(message); event.set(); } template void MessageQueue::stop() { stopped = true; event.set(); } template typename IntrusiveLinkedList>::hook& MessageQueue::getHook() { return hook; } }