1// LAF Base Library
2// Copyright (c) 2019-2022 Igara Studio S.A.
3// Copyright (c) 2001-2016 David Capello
4//
5// This file is released under the terms of the MIT license.
6// Read LICENSE.txt for more information.
7
8#ifndef BASE_CONCURRENT_QUEUE_H_INCLUDED
9#define BASE_CONCURRENT_QUEUE_H_INCLUDED
10#pragma once
11
12#include <algorithm>
13#include <deque>
14#include <mutex>
15
16namespace base {
17
18 template<typename T>
19 class concurrent_queue {
20 public:
21 concurrent_queue() { }
22 concurrent_queue(const concurrent_queue&) = delete;
23 concurrent_queue& operator=(const concurrent_queue&) = delete;
24 ~concurrent_queue() { }
25
26 bool empty() const {
27 bool result;
28 {
29 std::lock_guard lock(m_mutex);
30 result = m_queue.empty();
31 }
32 return result;
33 }
34
35 void clear() {
36 std::lock_guard lock(m_mutex);
37 m_queue.clear();
38 }
39
40 size_t size() const {
41 size_t result;
42 {
43 std::lock_guard lock(m_mutex);
44 result = m_queue.size();
45 }
46 return result;
47 }
48
49 void push(const T& value) {
50 std::lock_guard lock(m_mutex);
51 m_queue.push_back(value);
52 }
53
54 bool try_pop(T& value) {
55 if (!m_mutex.try_lock())
56 return false;
57
58 std::lock_guard unlock(m_mutex, std::adopt_lock);
59 if (m_queue.empty())
60 return false;
61
62 value = m_queue.front();
63 m_queue.pop_front();
64 return true;
65 }
66
67 template<typename UnaryPredicate>
68 void prioritize(UnaryPredicate p) {
69 std::lock_guard lock(m_mutex);
70
71 auto it = std::find_if(m_queue.begin(), m_queue.end(), p);
72 if (it != m_queue.end()) {
73 T value(std::move(*it));
74 m_queue.erase(it);
75 m_queue.push_front(std::move(value));
76 }
77 }
78
79 private:
80 std::deque<T> m_queue;
81 mutable std::mutex m_mutex;
82 };
83
84} // namespace base
85
86#endif
87