
1 changed files with 0 additions and 180 deletions
@ -1,180 +0,0 @@ |
|||
// This file is under GNU General Public License 3.0
|
|||
// see LICENSE.txt
|
|||
|
|||
#ifndef LIBPEPADAPTER_LOCKED_QUEUE_HH |
|||
#define LIBPEPADAPTER_LOCKED_QUEUE_HH |
|||
|
|||
#include <deque> |
|||
#include <condition_variable> |
|||
#include <mutex> |
|||
|
|||
namespace utility { |
|||
template<class T, void (*Deleter)(T) = nullptr> |
|||
class locked_queue { |
|||
typedef std::recursive_mutex Mutex; |
|||
typedef std::unique_lock<Mutex> Lock; |
|||
|
|||
int _waiting = 0; |
|||
Mutex _mtx; |
|||
std::condition_variable_any _cv; |
|||
std::deque<T> _q; |
|||
|
|||
public: |
|||
~locked_queue() |
|||
{ |
|||
clear(); |
|||
} |
|||
|
|||
void clear() |
|||
{ |
|||
Lock L(_mtx); |
|||
if (Deleter != nullptr) { |
|||
for (auto q : _q) { |
|||
Deleter(q); |
|||
} |
|||
} |
|||
_q.clear(); |
|||
} |
|||
|
|||
// defined behavior when queue empty
|
|||
T back() |
|||
{ |
|||
Lock lg(_mtx); |
|||
if (_q.empty()) |
|||
throw std::underflow_error("queue empty"); |
|||
return _q.back(); |
|||
} |
|||
|
|||
// defined behavior when queue empty
|
|||
T front() |
|||
{ |
|||
Lock lg(_mtx); |
|||
if (_q.empty()) |
|||
throw std::underflow_error("queue empty"); |
|||
return _q.front(); |
|||
} |
|||
|
|||
// returns a copy of the last element.
|
|||
// blocks when queue is empty
|
|||
T pop_back() |
|||
{ |
|||
Lock L(_mtx); |
|||
_cv.wait(L, [&] { return !_q.empty(); }); |
|||
T r{std::move(_q.back())}; |
|||
_q.pop_back(); |
|||
return r; |
|||
} |
|||
|
|||
// returns a copy of the first element.
|
|||
// blocks when queue is empty
|
|||
T pop_front() |
|||
{ |
|||
Lock L(_mtx); |
|||
_cv.wait(L, [&] { return !_q.empty(); }); |
|||
T r{std::move(_q.front())}; |
|||
_q.pop_front(); |
|||
return r; |
|||
} |
|||
|
|||
// returns true and set a copy of the last element and pop it from queue if there is any
|
|||
// returns false and leaves 'out' untouched if queue is empty even after 'end_time'
|
|||
bool try_pop_back(T& out, std::chrono::steady_clock::time_point end_time) |
|||
{ |
|||
Lock L(_mtx); |
|||
++_waiting; |
|||
if (!_cv.wait_until(L, end_time, [this] { return !_q.empty(); })) { |
|||
--_waiting; |
|||
return false; |
|||
} |
|||
|
|||
--_waiting; |
|||
out = std::move(_q.back()); |
|||
_q.pop_back(); |
|||
return true; |
|||
} |
|||
|
|||
// returns true and set a copy of the first element and pop it from queue if there is any
|
|||
// returns false and leaves 'out' untouched if queue is empty even after 'end_time'
|
|||
bool try_pop_front(T& out, std::chrono::steady_clock::time_point end_time) |
|||
{ |
|||
Lock L(_mtx); |
|||
++_waiting; |
|||
if (!_cv.wait_until(L, end_time, [this] { return !_q.empty(); })) { |
|||
--_waiting; |
|||
return false; |
|||
} |
|||
|
|||
--_waiting; |
|||
out = std::move(_q.front()); |
|||
_q.pop_front(); |
|||
return true; |
|||
} |
|||
|
|||
// returns true and set a copy of the first element and pop it from queue if there is any
|
|||
// returns false and leaves 'out' untouched if queue is empty even after 'duration'
|
|||
bool try_pop_front(T& out, std::chrono::seconds duration) |
|||
{ |
|||
Lock L(_mtx); |
|||
++_waiting; |
|||
if (!_cv.wait_for(L, duration, [this] { return !_q.empty(); })) { |
|||
--_waiting; |
|||
return false; |
|||
} |
|||
|
|||
--_waiting; |
|||
out = std::move(_q.front()); |
|||
_q.pop_front(); |
|||
return true; |
|||
} |
|||
|
|||
|
|||
void push_back(const T& data) |
|||
{ |
|||
{ |
|||
Lock L(_mtx); |
|||
_q.push_back(data); |
|||
} |
|||
_cv.notify_one(); |
|||
} |
|||
|
|||
void emplace_back(const T& data) |
|||
{ |
|||
{ |
|||
Lock L(_mtx); |
|||
_q.emplace_back(data); |
|||
} |
|||
_cv.notify_one(); |
|||
} |
|||
|
|||
void push_front(const T& data) |
|||
{ |
|||
{ |
|||
Lock L(_mtx); |
|||
_q.push_front(data); |
|||
} |
|||
_cv.notify_one(); |
|||
} |
|||
|
|||
size_t size() |
|||
{ |
|||
Lock lg(_mtx); |
|||
return _q.size(); |
|||
} |
|||
|
|||
bool empty() |
|||
{ |
|||
Lock lg(_mtx); |
|||
return _q.empty(); |
|||
} |
|||
|
|||
// returns the number of threads that are waiting in pop_...() or try_pop_...()
|
|||
int waiting() |
|||
{ |
|||
Lock L(_mtx); |
|||
return _waiting; |
|||
} |
|||
}; |
|||
|
|||
} // end of namespace utility
|
|||
|
|||
#endif // LIBPEPADAPTER_LOCKED_QUEUE_HH
|
Loading…
Reference in new issue