mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-04-30 12:47:48 +02:00
116 lines
3.3 KiB
C++
116 lines
3.3 KiB
C++
/*
|
|
* Copyright (c) 2013-2020, The PurpleI2P Project
|
|
*
|
|
* This file is part of Purple i2pd project and licensed under BSD3
|
|
*
|
|
* See full license text in LICENSE file at top of project tree
|
|
*/
|
|
|
|
#ifndef QUEUE_H__
|
|
#define QUEUE_H__
|
|
|
|
#include <queue>
|
|
#include <vector>
|
|
#include <mutex>
|
|
#include <thread>
|
|
#include <condition_variable>
|
|
#include <functional>
|
|
#include <utility>
|
|
|
|
namespace i2p {
|
|
namespace util {
|
|
template<typename Element>
|
|
class Queue {
|
|
public:
|
|
|
|
void Put(Element e) {
|
|
std::unique_lock <std::mutex> l(m_QueueMutex);
|
|
m_Queue.push(std::move(e));
|
|
m_NonEmpty.notify_one();
|
|
}
|
|
|
|
template<template<typename, typename...> class Container, typename... R>
|
|
void Put(const Container<Element, R...> &vec) {
|
|
if (!vec.empty()) {
|
|
std::unique_lock <std::mutex> l(m_QueueMutex);
|
|
for (const auto &it: vec)
|
|
m_Queue.push(std::move(it));
|
|
m_NonEmpty.notify_one();
|
|
}
|
|
}
|
|
|
|
Element GetNext() {
|
|
std::unique_lock <std::mutex> l(m_QueueMutex);
|
|
auto el = GetNonThreadSafe();
|
|
if (!el) {
|
|
m_NonEmpty.wait(l);
|
|
el = GetNonThreadSafe();
|
|
}
|
|
return el;
|
|
}
|
|
|
|
Element GetNextWithTimeout(int usec) {
|
|
std::unique_lock <std::mutex> l(m_QueueMutex);
|
|
auto el = GetNonThreadSafe();
|
|
if (!el) {
|
|
m_NonEmpty.wait_for(l, std::chrono::milliseconds(usec));
|
|
el = GetNonThreadSafe();
|
|
}
|
|
return el;
|
|
}
|
|
|
|
void Wait() {
|
|
std::unique_lock <std::mutex> l(m_QueueMutex);
|
|
m_NonEmpty.wait(l);
|
|
}
|
|
|
|
bool Wait(int sec, int usec) {
|
|
std::unique_lock <std::mutex> l(m_QueueMutex);
|
|
return m_NonEmpty.wait_for(l, std::chrono::seconds(sec) + std::chrono::milliseconds(usec)) !=
|
|
std::cv_status::timeout;
|
|
}
|
|
|
|
bool IsEmpty() {
|
|
std::unique_lock <std::mutex> l(m_QueueMutex);
|
|
return m_Queue.empty();
|
|
}
|
|
|
|
int GetSize() {
|
|
std::unique_lock <std::mutex> l(m_QueueMutex);
|
|
return m_Queue.size();
|
|
}
|
|
|
|
void WakeUp() { m_NonEmpty.notify_all(); };
|
|
|
|
Element Get() {
|
|
std::unique_lock <std::mutex> l(m_QueueMutex);
|
|
return GetNonThreadSafe();
|
|
}
|
|
|
|
Element Peek() {
|
|
std::unique_lock <std::mutex> l(m_QueueMutex);
|
|
return GetNonThreadSafe(true);
|
|
}
|
|
|
|
private:
|
|
|
|
Element GetNonThreadSafe(bool peek = false) {
|
|
if (!m_Queue.empty()) {
|
|
auto el = m_Queue.front();
|
|
if (!peek)
|
|
m_Queue.pop();
|
|
return el;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
private:
|
|
|
|
std::queue <Element> m_Queue;
|
|
std::mutex m_QueueMutex;
|
|
std::condition_variable m_NonEmpty;
|
|
};
|
|
}
|
|
}
|
|
|
|
#endif
|