#ifndef QUEUE_H__ #define QUEUE_H__ #include #include #include #include namespace i2p { namespace util { template class Queue { public: void Put (Element * e) { std::unique_lock l(m_QueueMutex); m_Queue.push (e); m_NonEmpty.notify_one (); } Element * GetNext () { std::unique_lock l(m_QueueMutex); Element * el = GetNonThreadSafe (); if (!el) { m_NonEmpty.wait (l); el = GetNonThreadSafe (); } return el; } Element * GetNextWithTimeout (int usec) { std::unique_lock l(m_QueueMutex); Element * el = GetNonThreadSafe (); if (!el) { m_NonEmpty.wait_for (l, std::chrono::milliseconds (usec)); el = GetNonThreadSafe (); } return el; } void WakeUp () { m_NonEmpty.notify_one (); }; Element * Get () { std::unique_lock l(m_QueueMutex); return GetNonThreadSafe (); } private: Element * GetNonThreadSafe () { if (!m_Queue.empty ()) { Element * el = m_Queue.front (); m_Queue.pop (); return el; } return nullptr; } private: std::queue m_Queue; std::mutex m_QueueMutex; std::condition_variable m_NonEmpty; }; template class MsgQueue: public Queue { public: MsgQueue (): m_Thread (std::bind (&MsgQueue::Run, this)) {}; private: void Run () { Msg * msg = nullptr; while ((msg = Queue::GetNext ()) != nullptr) { msg->Process (); delete msg; } } private: std::thread m_Thread; }; } } #endif