A Thread Safe Queue in C++
Thread-safe Queue
In this code sample project, I illustrate the implementation of a thread-safe queue for inter-thread message exchange. The comprehensive implementation is provided below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#ifndef SAFE_QUEUE_H
#define SAFE_QUEUE_H
#include <condition_variable>
#include <mutex>
#include <queue>
// A threadsafe-queue.
template <typename T>
class SafeQueue
{
public:
SafeQueue(void) : m_queue(), m_mutex(), m_cv() {}
~SafeQueue(void) {}
// Add an element to the queue.
void enqueue(T t)
{
std::lock_guard<std::mutex> lock(m_mutex);
m_queue.push(t);
m_cv.notify_all();
}
// Get the front element. If the queue is empty, wait till a element is avaiable.
T dequeue(void)
{
std::unique_lock<std::mutex> lock(m_mutex);
while (m_queue.empty())
{
// release lock as long as the wait and reaquire it on wake up.
m_cv.wait(lock);
}
T val = m_queue.front();
m_queue.pop();
return val;
}
void dequeue_with_timeout(const int ms, T &val)
{
// Lock so that if the notify happens before the wait, the notify wont get "lost".
std::unique_lock<std::mutex> lock(m_mutex);
/*
Release the lock and enter a waiting state. Resume execution after a specified duration in milliseconds or when notified. If the awakening is triggered by a notification, assess a predicate, and revert to waiting if the predicate evaluates to false. The wait_for() function returns false if the stop_waiting predicate remains false after the rel_time timeout has elapsed; otherwise, it returns true.
*/
m_cv.wait_for(lock, std::chrono::milliseconds(ms), [this]()
{
bool stop_waiting = !m_queue.empty();
return stop_waiting;
}
);
if (!m_queue.empty())
{
val = m_queue.front();
m_queue.pop();
}
}
size_t size()
{
std::unique_lock<std::mutex> lock(m_mutex);
return m_queue.size();
}
private:
std::queue<T> m_queue;
mutable std::mutex m_mutex;
std::condition_variable m_cv;
};
#endif
This post is licensed under CC BY 4.0 by the author.