A C++ thread-safe queue implementation.
ThreadSafeQueue
is a template class that provides a thread-safe wrapper around std::queue
.
It uses mutex and condition variables to ensure safe concurrent access from multiple threads.
- Thread-safe operations: All operations are protected by mutex locks
- Move semantics: Uses
std::unique_ptr
for efficient memory management - Blocking and non-blocking operations: Flexible API for different use cases
- Timeout support: Timed wait operations with configurable timeouts
- No copy operations: Prevents resource conflicts by disabling copy constructor and assignment
- C++17 or later
- Standard library headers:
<queue>
,<mutex>
,<condition_variable>
,<chrono>
,<thread>
push(std::unique_ptr<T> value)
- Add an element to the queuetry_pop(std::unique_ptr<T>& value)
- Non-blocking pop, returns false if emptywait_and_pop(std::unique_ptr<T>& value)
- Blocking pop, waits for elementtry_wait_and_pop(std::unique_ptr<T>& value, duration timeout)
- Pop with timeoutempty()
- Check if queue is emptysize()
- Get number of elements in queue
#include "ThreadSafeQueue.hpp"
#include <iostream>
#include <memory>
// Create a queue for integers
ThreadSafeQueue<int> queue;
// Push elements
queue.push(std::make_unique<int>(42));
queue.push(std::make_unique<int>(100));
// Pop element (non-blocking)
std::unique_ptr<int> value;
if (queue.try_pop(value)) {
std::cout << "Popped: " << *value << std::endl;
}
#include "ThreadSafeQueue.hpp"
#include <thread>
#include <iostream>
ThreadSafeQueue<int> queue;
// Producer thread
void producer() {
for (int i = 0; i < 10; ++i) {
queue.push(std::make_unique<int>(i));
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
// Consumer thread
void consumer() {
for (int i = 0; i < 10; ++i) {
std::unique_ptr<int> value;
queue.wait_and_pop(value);
std::cout << "Consumed: " << *value << std::endl;
}
}
int main() {
std::thread prod(producer);
std::thread cons(consumer);
prod.join();
cons.join();
return 0;
}
#include "ThreadSafeQueue.hpp"
#include <chrono>
ThreadSafeQueue<std::string> queue;
std::unique_ptr<std::string> value;
auto timeout = std::chrono::seconds(5);
if (queue.try_wait_and_pop(value, timeout)) {
std::cout << "Got value: " << *value << std::endl;
} else {
std::cout << "Timeout expired, no value available" << std::endl;
}
struct Message {
int id;
std::string content;
Message(int i, std::string c) : id(i), content(std::move(c)) {}
};
ThreadSafeQueue<Message> messageQueue;
// Push custom type
messageQueue.push(std::make_unique<Message>(1, "Hello World"));
// Pop and process
std::unique_ptr<Message> msg;
if (messageQueue.try_pop(msg)) {
std::cout << "Message " << msg->id << ": " << msg->content << std::endl;
}
- All public methods are thread-safe and can be called concurrently from multiple threads
- The queue uses RAII and lock guards to ensure exception safety
- Condition variables are used for efficient waiting without busy-polling
- Uses
std::unique_ptr
to avoid unnecessary copying of large objects notify_one()
is used instead ofnotify_all()
for better performance when multiple consumers are waiting- Lock contention may occur under heavy concurrent access
Copyright 2025 TierOne Software
Licensed under the Apache License, Version 2.0. See the source file for full license text.