#include <pthread.h>
#include <list>
using namespace std;
template <typename T> class wqueue
{
list<T> m_queue;
pthread_mutex_t m_mutex;
pthread_cond_t m_condv;
public:
wqueue() {
pthread_mutex_init(&m_mutex, NULL);
pthread_cond_init(&m_condv, NULL);
}
~wqueue() {
pthread_mutex_destroy(&m_mutex);
pthread_cond_destroy(&m_condv);
}
void add(T item) {
pthread_mutex_lock(&m_mutex);
m_queue.push_back(item);
pthread_cond_signal(&m_condv);
pthread_mutex_unlock(&m_mutex);
}
T remove() {
pthread_mutex_lock(&m_mutex);
while (m_queue.size() == 0) {
pthread_cond_wait(&m_condv, &m_mutex);
}
T item = m_queue.front();
m_queue.pop_front();
pthread_mutex_unlock(&m_mutex);
return item;
}
int size() {
pthread_mutex_lock(&m_mutex);
int size = m_queue.size();
pthread_mutex_unlock(&m_mutex);
return size;
}
};
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include "thread.h"
#include "wqueue.h"
class WorkItem
{
string m_message;
int m_number;
public:
WorkItem(const char* message, int number)
: m_message(message), m_number(number) {}
~WorkItem() {}
const char* getMessage() { return m_message.c_str(); }
int getNumber() { return m_number; }
};
class ConsumerThread : public Thread
{
wqueue<WorkItem*>& m_queue;
public:
ConsumerThread(wqueue<WorkItem*>& queue) : m_queue(queue) {}
void* run() {
// Remove 1 item at a time and process it. Blocks if no items are
// available to process.
for (int i = 0;; i++) {
printf("thread %lu, loop %d - waiting for item...\n",
(long unsigned int)self(), i);
WorkItem* item = m_queue.remove();
printf("thread %lu, loop %d - got one item\n",
(long unsigned int)self(), i);
printf("thread %lu, loop %d - item: message - %s, number - %d\n",
(long unsigned int)self(), i, item->getMessage(),
item->getNumber());
delete item;
}
return NULL;
}
};
int main(int argc, char** argv)
{
// Process command line arguments
if ( argc != 2 ) {
printf("usage: %s <iterations>\n", argv[0]);
exit(-1);
}
int iterations = atoi(argv[1]);
// Create the queue and consumer (worker) threads
wqueue<WorkItem*> queue;
ConsumerThread* thread1 = new ConsumerThread(queue);
ConsumerThread* thread2 = new ConsumerThread(queue);
thread1->start();
thread2->start();
// Add items to the queue
WorkItem* item;
for (int i = 0; i < iterations; i++) {
item = new WorkItem("abc", 123);
queue.add(item);
item = new WorkItem("def", 456);
queue.add(item);
item = new WorkItem("ghi", 789);
queue.add(item);
sleep(1);
}
// Wait for the queue to be empty
while (queue.size() < 0);
printf("done\n");
exit(0);
}