diff --git a/ProducerConsumerQueue.cpp b/ProducerConsumerQueue.cpp new file mode 100644 index 0000000000000000000000000000000000000000..33beab8fb6af28ab5789a250267f8bf4450719ff --- /dev/null +++ b/ProducerConsumerQueue.cpp @@ -0,0 +1,47 @@ +// +// Created by Ben Bergkamp on 1/25/18. +// + +#include "ProducerConsumerQueue.h" + +template <class T> +void ProducerConsumerQueue<T>::Push(T obj) +{ + pthread_mutex_lock(&m); + + queue.push(obj); + + if(queue.size() == 1) + { + pthread_cond_signal(&consumer_cv); + } + + pthread_mutex_unlock(&m); +} + +template <class T> +T ProducerConsumerQueue<T>::Pop() +{ + pthread_mutex_lock(&m); + + while(queue.empty() == true) + { + pthread_cond_wait(&consumer_cv, &m); + } + + T front = queue.front(); + queue.pop(); + + pthread_mutex_unlock(&m); + + return front; +} + +template <class T> +size_t ProducerConsumerQueue<T>::Size() +{ + pthread_mutex_lock(&m); + size_t size = queue.size(); + pthread_mutex_unlock(&m); + return size; +} \ No newline at end of file diff --git a/ProducerConsumerQueue.h b/ProducerConsumerQueue.h new file mode 100644 index 0000000000000000000000000000000000000000..b57d4740a4b36c09cb74d22a2ae03cb3d55a5bda --- /dev/null +++ b/ProducerConsumerQueue.h @@ -0,0 +1,33 @@ +// +// Created by Ben Bergkamp on 1/25/18. +// + +#ifndef EECS398_SEARCH_PRODUCERCONSUMERQUEUE_H +#define EECS398_SEARCH_PRODUCERCONSUMERQUEUE_H + +#include <queue> +#include <pthread.h> + +//for now use STL queue, create better one later + + +template <class T> class ProducerConsumerQueue { +private: + std::queue<T> queue; + pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; + pthread_cond_t consumer_cv = PTHREAD_COND_INITIALIZER; + +public: + + ProducerConsumerQueue() {} + void Push(T obj); + T Pop(); + size_t Size(); + + //Right now these pass objects by value but + // probably should pass pointers in future + +}; + + +#endif //EECS398_SEARCH_PRODUCERCONSUMERQUEUE_H diff --git a/ProducerConsumerQueue_test.cpp b/ProducerConsumerQueue_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..535a66a2b368818bca366ce308ec21b193168de6 --- /dev/null +++ b/ProducerConsumerQueue_test.cpp @@ -0,0 +1,76 @@ +/// +// Created by Ben Bergkamp on 1/25/18. +// + +#include <iostream> +#include <stdlib.h> +#include <pthread.h> +#include "ProducerConsumerQueue.h" +#include "ProducerConsumerQueue.cpp" // needed here because class is a template + +pthread_mutex_t cout_lock = PTHREAD_MUTEX_INITIALIZER; + +void* Producer(void* p) +{ + ProducerConsumerQueue<int> * queue = (ProducerConsumerQueue<int>*)p; + + for(int i = 0; i < 10; i++) + { + if(queue->Size()){ + pthread_yield_np(); // let the consumer thread run + } + + queue->Push(i); + + pthread_mutex_lock(&cout_lock); + std::cout << "Pushed: " << i << "\n"; + pthread_mutex_unlock(&cout_lock); + } + + return p; +} + +void* Consumer(void* p) +{ + ProducerConsumerQueue<int> * queue = (ProducerConsumerQueue<int>*)p; + + for(int i = 0; i < 10; i++) + { + int r = queue->Pop(); + + pthread_mutex_lock(&cout_lock); + std::cout << "Popped: " << r << "\n"; + pthread_mutex_unlock(&cout_lock); + } + + return p; +} + + + +int main(int argc, const char * argv[]) +{ + ProducerConsumerQueue<int>* queue = new(ProducerConsumerQueue<int>); + + pthread_t producer, consumer; + + pthread_mutex_lock(&cout_lock); + std::cout << "Creating Consumer\n"; + pthread_mutex_unlock(&cout_lock); + pthread_create(&consumer, NULL, Consumer, queue); + + pthread_mutex_lock(&cout_lock); + std::cout << "Creating Producer\n"; + pthread_mutex_unlock(&cout_lock); + pthread_create(&producer, NULL, Producer, queue); + + pthread_mutex_lock(&cout_lock); + std::cout << "Waiting for Producer and Consumer\n"; + pthread_mutex_unlock(&cout_lock); + pthread_join(producer, NULL); + pthread_join(consumer, NULL); + + delete queue; + + return 0; +} \ No newline at end of file