Skip to content

Instantly share code, notes, and snippets.

@carlchen0928
Created June 23, 2015 07:51
Show Gist options
  • Select an option

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

Select an option

Save carlchen0928/0d0d9e8f59728a4872f3 to your computer and use it in GitHub Desktop.
thread safe queue with condition_variable and mutex
#include <queue>
#include <mutex>
#include <memory>
#include <condition_variable>
#include <stdio.h>
#include <iostream>
/*
* thread safe queue implementation.
* Use a mutex and condition_variable to keep thread safe.
* When queue is empty, wait_and_pop function will block
* until queue has item. try_pop function will return false
* when queue empty.
* I provide two way to pop item from queue. Reference parameter
* or shared_ptr return value.
* Length of queue is unlimited.
*/
#define DEBUG
template <class T>
class threadsafe_queue
{
public:
threadsafe_queue() {};
threadsafe_queue(const threadsafe_queue& other);
threadsafe_queue& operator=(const threadsafe_queue&);
void push(T value)
{
std::lock_guard<std::mutex> lg(mtx);
Q.push(value);
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 = 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(
std::make_shared<T>(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 = 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(
std::make_shared<T>(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<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