I'm came across this code in a unix book I took out from the library. I know some c++ but I don't know a thing about Unix. I'm curious about it. I tried running this with my MS C++ 6.0, but it gave me an error. Can someone tell me how to compile it and run it. I want to know what this does.
Thanks!
#include <thread.h>
#include <synch.h>
#include <list.h>
#include <iterator.h>
#include <iostream.h>
//creates the structure where the results are placed in the linked list
struct item
{
int value;
thread_t thrid;
item(int v = 0, thread_t tid = 0) : value(v), thrid(tid){}
};
//Linked Lists: task list and results list
list<int> tasks;
list<item> results;
list<item>::iterator indexItem; //Item list iterator
list<int>::iterator indexInt; //Integer list iterator
//Global Variables
int numberOfTasks; //# of tasks
int bufferSize; //Size of buffer
//Two semaphores: tasks and results
sema_t sTasks;
sema_t sResults;
//Flag that signals readers that writer has finished
bool done = false;
//Prototypes for the writer(producer) and reader(consumer) functions
void *reader(void* rn);
void *writer(void* wri);
int main (void)
{
// Initializes semaphores for 2 lists and cout statements
if(sema_init(&sTasks, 1, USYNC_THREAD, 0) != 0)
cout << "ERROR, Task List Semaphore NOT Initialized\n";
if(sema_init(&sResults, 1, USYNC_THREAD, 0) != 0)
cout << "ERROR, Result List Semaphore NOT Initialized\n";
//Get buffer size and number of tasks
cout << "Enter the total number tasks: ";
cin >>NumberTasks;
cout << "\nEnter the buffer size: ";
cin >> bufferSize;
//Creates and starts the threads
thread_t reader1, reader2, writer1;
if(thr_create(NULL, 0, writer, NULL, THR_BOUND, &writer1)!= 0)
cout << "Error creating writer1 thread!";
if(thr_create(NULL, 0, reader, NULL, THR_BOUND, &reader1) != 0)
cout << "Error creating reader1 thread!";
if(thr_create(NULL, 0, reader, NULL, THR_BOUND, &reader2) != 0)
cout << "Error creating reader2 thread!";
thr_continue(writer1);
thr_continue(reader1);
thr_continue(reader2);
thr_join(writer1, NULL, NULL);
thr_join(reader1, NULL, NULL);
thr_join(reader2, NULL, NULL);
cout << "\n\nTasks to be done: " <<NumberTasks << "\n";
cout << "Results list size: "<< results.size() << "\n";
//Initializing both reader counters:
int r1Count = 0;
int r2Count = 0;
struct item mrItem;
int total = 0;
//Assigning the results list iterator to the beginning of the linked list
indexItem = results.begin();
thread_t temp = indexItem->thrid;
for(; indexItem != results.end();indexItem++)
{
mrItem = *indexItem;
if(mrItem.thrid ==reader1) r1Count++;
if(mrItem.thrid == reader2) r2Count++;
total +=mrItem.value;
}
//Printing the results
cout << "Tasks done by thread " << reader1 << ": "<< r1Count<<"\n";
cout << "Tasks done by thread " << reader2 << ": "<< r2Count<<"\n";
cout << "Total done by both threads: " << r1Count + r2Count<<"\n";
cout << "\nCompleted Task checksum: " << total << "\n";
cout << "Expected checksum: " << (NumberTasks * (NumberTasks +1)/2) << "\n";
}
void *reader(void *rn)
{
//I'm not assigning the passed variable to anything since
//the *rn variable contains nothing anyways
int i = 0;
sema_wait(&sTasks);
while(!done ||(tasks.size() > 0))
{
bool isIf = false;
if(tasks.size() > 0) // If the tasks list is not empty, this pops an element off it
{
isIf = true;
indexInt = tasks.end();
indexInt--;
i = *indexInt;
tasks.pop_back();
}
sema_post(&sTasks);
if(isIf) //This makes an output item and pushes it on the results list
{
sema_wait(&sResults);
struct item result;
result.value = i;
result.thrid = thr_self();
results.push_back(result);
sema_post(&sResults);
}
sema_wait(&sTasks);
}
sema_post(&sTasks); //Terminate
return NULL;
}
void *writer(void *wri)
{
for(int i = 1; i <= NumberTasks; i++)
{ //
sema_wait(&sTasks); // Wait if the buffer is full
while(tasks.size()>= N)
{
sema_post(&sTasks); //Give the readers a chance to pop some tasks off
sema_wait(&sTasks);
}
//push i on Tasks
tasks.push_back(i);
//If this was last loop, set done flag to true
if(i == NumberTasks)
done = true;
sema_post(&sTasks);
}
done = true; //Terminate
return NULL;
}