/*


    tcond.cc

    C++ source to test condition class.

    Copyright (C) 1999 by Matt Roberts, KK5JY,
    All rights reserved


*/


#include <iostream.h>
#include <stdio.h>
#include <unistd.h>

#include <my++/thread.h>

#ifndef NUM_THREADS
  #define NUM_THREADS (32)
#else
  #error NUM_THREADS already defined!
#endif

using namespace my;

int x = 0;
mutex cm, m;
condition cv;

void report (char *message) {
	m.lock ();
	cout << message;
	m.unlock ();
}

int getnum (void) {
	int num = 0;
	cin >> num;
	return num;
}

class MyThread : public thread {
	int id;
	char buffer [80];

	public:
	MyThread (int the_id) { id = the_id; };

	void *run (void *) {
		sprintf (buffer, "Thread %d started.\n", id); report (buffer);
		cm.lock ();
		sprintf (buffer, "Thread %d has aquired mutex for condition variable.\n", id); report (buffer);
		while (x != id) {
			sprintf (buffer, "Thread %d rejects predicate...going to sleep.\n", id); report (buffer);
			cv.wait (cm);
		}
		cm.unlock ();
		sprintf (buffer, "Thread %d accepts predicate...doing something useful.\n", id); report (buffer);
		sleep (4);
		sprintf (buffer, "Thread %d exit.\n", id); report (buffer);
	}
};

int main (int argc, char **argv, char **envp) {
	MyThread *thread [NUM_THREADS];
	int id [NUM_THREADS];
	int input;
	int i;

	for (i = 0; i < NUM_THREADS; i++)
		id [i] = i + 1;

	for (i = 0; i < NUM_THREADS; i++) {
		thread [i] = new MyThread (id [i]);
		thread [i]->start();
	}

	while (x != 999) {
		sleep (1);
		report ("Enter thread id: ");
		input = getnum ();
		cm.lock ();
		x = input;
		cv.broadcast ();
		cm.unlock ();
	}

	for (i = 0; i < NUM_THREADS; i++)
		thread [i]->join ();
}
