Skip to content

Instantly share code, notes, and snippets.

@ivcn
Created April 9, 2017 16:04
Show Gist options
  • Select an option

  • Save ivcn/3618cad8fbf4b9950d8e725b4c0e841f to your computer and use it in GitHub Desktop.

Select an option

Save ivcn/3618cad8fbf4b9950d8e725b4c0e841f to your computer and use it in GitHub Desktop.
Simple implementation of producer-consumre pattern in C++
template<typename ElementType>
class Queue {
public:
Queue(size_t size) :
buffer(size),
front(0),
end(0) {}
void push(ElementType newElement) {
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, [this] { return !isFull(); });
buffer[end] = newElement;
if (end == buffer.size() - 1)
end = 0;
else
++end;
lk.unlock();
cv.notify_all();
}
ElementType pop() {
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, [this] { return !isEmpty(); });
auto v = std::move(buffer[front]);
if (front == buffer.size() - 1)
front = 0;
else
++front;
lk.unlock();
cv.notify_all();
return v;
}
private:
inline bool isEmpty() {
return front == end;
}
inline bool isFull() {
if ((front == 0 && end == buffer.size() - 1) || end == front - 1)
return true;
else
return false;
}
std::mutex m;
std::condition_variable cv;
size_t front;
size_t end;
std::vector<ElementType> buffer;
};
struct Entity {
int i;
Entity() : i(0) {}
Entity(int _i) : i(_i) {}
};
template<typename T>
void process(T v) {}
template<>
void process<Entity>(Entity e) {
print("Thread ", std::this_thread::get_id(), " processed: ", e.i, " \n");
}
template<typename T>
void producer(Queue<T>& queue) {
int i = 0;
while (true) {
queue.push(++i);
}
}
template<typename T>
void consumer(Queue<T>& queue) {
while (true) {
auto e = queue.pop();
process(e);
}
}
int main() {
Queue<Entity> queue(100);
auto f1 = std::async(&producer<Entity>, std::ref(queue));
auto f2 = std::async(&consumer<Entity>, std::ref(queue));
auto f3 = std::async(&consumer<Entity>, std::ref(queue));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment