Skip to content

Instantly share code, notes, and snippets.

@carlchen0928
Last active August 29, 2015 14:23
Show Gist options
  • Select an option

  • Save carlchen0928/d6b38f1a0536d691e860 to your computer and use it in GitHub Desktop.

Select an option

Save carlchen0928/d6b38f1a0536d691e860 to your computer and use it in GitHub Desktop.
thread safe && exception safe queue
#include <queue>
#include <mutex>
#include <memory>
#include <condition_variable>
#include <stdio.h>
#include <iostream>
/*
* thread safe && exception safe queue implementation.
* Save item in shared_ptr in the queue to make sure all
* construction called in push function, when exception
* happened, nothing will change and data still in consistence.
* If we construct object in pop functions, when exception happened,
* things already pop from queue, behavior undefined.
* Base on threadsafe_queue.
*/
#define DEBUG
template <class T>
class threadsafe_exceptionsafe_queue
{
public:
threadsafe_exceptionsafe_queue() {};
threadsafe_exceptionsafe_queue(const threadsafe_exceptionsafe_queue& other);
threadsafe_exceptionsafe_queue& operator=(const threadsafe_exceptionsafe_queue&);
void push(T value)
{
shared_ptr<T> ptr(
make_shared<T>(std::move(value)));
std::lock_guard<std::mutex> lg(mtx);
Q.push(ptr);
cv.notify_one();
#ifdef DEBUG
std::cout << "push " << value << std::endl;
#endif
}
bool try_pop(T& value)
{
{
std::lock_guard<std::mutex> lg(mtx);
if (Q.empty()) {
#ifdef DEBUG
std::cout << "try_pop but empty" << std::endl;
#endif
return false;
}
value = std::move(*Q.front());
Q.pop();
}
#ifdef DEBUG
std::cout << "try_pop " << value << std::endl;
#endif
return true;
}
std::shared_ptr<T> try_pop()
{
{
std::lock_guard<std::mutex> lg(mtx);
if (Q.empty()) {
#ifdef DEBUG
std::cout << "try_pop but empty" << std::endl;
#endif
return std::shared_ptr();
}
std::shared_ptr<T> ptr = Q.front();
Q.pop();
}
#ifdef DEBUG
std::cout << "try_pop " << *ptr << std::endl;
#endif
return ptr;
}
void wait_and_pop(T& value)
{
std::unique_lock<std::mutex> ul(mtx);
cv.wait(ul, [this](){
return !Q.empty();
});
value = std::move(*Q.front());
Q.pop();
#ifdef DEBUG
std::cout << "wait_and_pop " << value << std::endl;
#endif
}
std::shared_ptr<T> wait_and_pop()
{
std::unique_lock<std::mutex> ul(mtx);
cv.wait(ul, [this](){
return !Q.empty();
});
std::shared_ptr<T> ptr = Q.front();
Q.pop();
#ifdef DEBUG
std::cout << "wait_and_pop " << *ptr << std::endl;
#endif
return ptr;
}
bool empty() const
{
std::lock_guard<std::mutex> lg(mtx);
return Q.empty();
}
size_t size() const
{
std::lock_guard<std::mutex> gl(mtx);
return Q.size();
}
private:
std::queue<shared_ptr<T> > Q;
std::mutex mtx;
std::condition_variable cv;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment