Created
April 9, 2017 16:04
-
-
Save ivcn/3618cad8fbf4b9950d8e725b4c0e841f to your computer and use it in GitHub Desktop.
Simple implementation of producer-consumre pattern in C++
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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