Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifndef _TSDEQUE_HPP_
- #define _TSDEQUE_HPP_
- // System includes
- #include <atomic>
- #include <condition_variable>
- #include <deque>
- #include <exception>
- #include <iterator>
- #include <mutex>
- #include <utility>
- #include <vector>
- // Project includes
- namespace DataStructures
- {
- template<typename T>
- class TSDeque
- {
- private:
- std::deque<T> m_Deque;
- std::mutex m_DequeMutex;
- std::condition_variable m_WaitBlock;
- std::mutex m_WaitMutex;
- std::atomic<bool> m_DisposeCalled;
- public:
- TSDeque(const TSDeque<T>&) = delete;
- TSDeque& operator=(const TSDeque<T>&) = delete;
- TSDeque()
- : m_Deque(),
- m_DequeMutex(),
- m_WaitBlock(),
- m_WaitMutex(),
- m_DisposeCalled(false)
- {
- }
- TSDeque(TSDeque<T>&& tsDeque)
- : m_Deque(std::move(tsDeque.m_Deque)),
- m_DisposeCalled(false)
- {
- }
- TSDeque& operator=(TSDeque<T>&& tsDeque)
- {
- if (this == &tsDeque)
- {
- return *this;
- }
- std::unique_lock<std::mutex> l_ulockDM(m_DequeMutex, std::defer_lock);
- std::unique_lock<std::mutex> ulockDM(tsDeque.m_DequeMutex, std::defer_lock);
- std::lock(l_ulockDM, ulockDM);
- m_Deque(std::move(tsDeque.m_Deque));
- return *this;
- }
- ~TSDeque()
- {
- }
- void Dispose()
- {
- m_DisposeCalled = true;
- // Terminate waiting.
- m_WaitBlock.notify_all();
- }
- void push_back(const T& value)
- {
- std::scoped_lock<std::mutex> lock(m_DequeMutex);
- m_Deque.emplace_back(std::move(value));
- std::unique_lock<std::mutex> ulock(m_WaitMutex);
- m_WaitBlock.notify_one();
- }
- void push_back(T&& value)
- {
- std::scoped_lock<std::mutex> lock(m_DequeMutex);
- m_Deque.emplace_back(std::move(value));
- std::unique_lock<std::mutex> ulock(m_WaitMutex);
- m_WaitBlock.notify_one();
- }
- void push_front(const T& value)
- {
- std::scoped_lock<std::mutex> lock(m_DequeMutex);
- m_Deque.emplace_front(std::move(value));
- std::unique_lock<std::mutex> ulock(m_WaitMutex);
- m_WaitBlock.notify_one();
- }
- void push_front(T&& value)
- {
- std::scoped_lock<std::mutex> lock(m_DequeMutex);
- m_Deque.emplace_front(std::move(value));
- std::unique_lock<std::mutex> ulock(m_WaitMutex);
- m_WaitBlock.notify_one();
- }
- T pop_front()
- {
- if (m_DisposeCalled)
- {
- throw std::runtime_error("Dispose has been called");
- }
- wait();
- std::scoped_lock<std::mutex> lock(m_DequeMutex);
- auto item = std::move(m_Deque.front());
- m_Deque.pop_front();
- return item;
- }
- T pop_back()
- {
- if (m_DisposeCalled)
- {
- throw std::runtime_error("Dispose has been called");
- }
- wait();
- std::scoped_lock<std::mutex> lock(m_DequeMutex);
- auto item = std::move(m_Deque.back());
- m_Deque.pop_back();
- return item;
- }
- std::size_t size()
- {
- std::scoped_lock<std::mutex> lock(m_DequeMutex);
- return m_Deque.size();
- }
- bool empty()
- {
- std::scoped_lock<std::mutex> lock(m_DequeMutex);
- return m_Deque.empty();
- }
- void wait()
- {
- if (empty() && !m_DisposeCalled)
- {
- std::unique_lock<std::mutex> ulock(m_WaitMutex);
- m_WaitBlock.wait(ulock);
- }
- }
- void clear()
- {
- std::scoped_lock<std::mutex> lock(m_DequeMutex);
- m_Deque.clear();
- }
- template<typename Iter>
- void insert(Iter begin, Iter end)
- {
- std::scoped_lock<std::mutex> lock(m_DequeMutex);
- m_Deque.insert(m_Deque.end(), begin, end);
- std::unique_lock<std::mutex> ulock(m_WaitMutex);
- m_WaitBlock.notify_one();
- }
- const T& front()
- {
- std::scoped_lock<std::mutex> lock(m_DequeMutex);
- return m_Deque.front();
- }
- const T& back()
- {
- std::scoped_lock<std::mutex> lock(m_DequeMutex);
- return m_Deque.back();
- }
- };
- }
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement