/******************************************************************************
*
* @file ts_deque.h
* @author Wei Wang -> shaxikai@outlook.com
* @date 2025.6.13
* @version V1.0.0"
* @brief thread safe deque
*
*****************************************************************************/
#pragma once
#include <deque>
#include <mutex>
#include <condition_variable>
#include <utility>
#include <stdexcept>
template<typename T>
class TSDeque {
public:
TSDeque() = default;
~TSDeque() = default;
TSDeque(const TSDeque&) = delete;
TSDeque& operator=(const TSDeque&) = delete;
void push_back(const T& item) {
std::lock_guard<std::mutex> lock(mutex_);
deque_.push_back(item);
cond_.notify_one();
}
void push_back(T&& item) {
std::lock_guard<std::mutex> lock(mutex_);
deque_.push_back(std::move(item));
cond_.notify_one();
}
void push_front(const T& item) {
std::lock_guard<std::mutex> lock(mutex_);
deque_.push_front(item);
cond_.notify_one();
}
void push_front(T&& item) {
std::lock_guard<std::mutex> lock(mutex_);
deque_.push_front(std::move(item));
cond_.notify_one();
}
bool pop_front(T& item) {
std::unique_lock<std::mutex> lock(mutex_);
cond_.wait(lock, [this]() { return !deque_.empty() || stopped_; });
if (stopped_ && deque_.empty())
return false;
item = std::move(deque_.front());
deque_.pop_front();
return true;
}
bool pop_back(T& item) {
std::unique_lock<std::mutex> lock(mutex_);
cond_.wait(lock, [this]() { return !deque_.empty() || stopped_; });
if (stopped_ && deque_.empty())
return false;
item = std::move(deque_.back());
deque_.pop_back();
return true;
}
bool pop_front() {
std::lock_guard<std::mutex> lock(mutex_);
if (deque_.empty() || stopped_)
return false;
deque_.pop_front();
return true;
}
bool pop_back() {
std::lock_guard<std::mutex> lock(mutex_);
if (deque_.empty() || stopped_)
return false;
deque_.pop_back();
return true;
}
void stop() {
std::lock_guard<std::mutex> lock(mutex_);
stopped_ = true;
cond_.notify_all();
}
bool empty() const {
std::lock_guard<std::mutex> lock(mutex_);
return deque_.empty();
}
size_t size() const {
std::lock_guard<std::mutex> lock(mutex_);
return deque_.size();
}
T& front() {
std::lock_guard<std::mutex> lock(mutex_);
return deque_.front();
}
const T& front() const {
std::lock_guard<std::mutex> lock(mutex_);
return deque_.front();
}
T& back() {
std::lock_guard<std::mutex> lock(mutex_);
return deque_.back();
}
const T& back() const {
std::lock_guard<std::mutex> lock(mutex_);
return deque_.back();
}
T& operator[](size_t index) {
std::lock_guard<std::mutex> lock(mutex_);
return deque_.at(index);
}
const T& operator[](size_t index) const {
std::lock_guard<std::mutex> lock(mutex_);
return deque_.at(index);
}
bool wait_for_data() {
std::unique_lock<std::mutex> lock(mutex_);
cond_.wait(lock, [this]() { return !deque_.empty() || stopped_; });
return !deque_.empty();
}
private:
mutable std::mutex mutex_;
std::condition_variable cond_;
std::deque<T> deque_;
bool stopped_ = false;
};