Why Java?Why not C++?
A. First Edition
This is first edition of my one-to-one translation of programming assignment of comp346 from Java
to C++.
public class Future {
static int length = 9; // 1-indexed semaphores
static int number = 8; // 0-indexed workers
static int sum = 0;
static Daemon daemon = new Daemon ();
static Semaphore future[] = new Semaphore[length];
static int arr[] = new int[] {0, -1, -1, -1, -1, -1, -1, -1, +1};
public static void main (String[] a) {
Worker w[] = new Worker[number];
for( int j=0; j<length; j++ ) // definition before use
future[j] = new Semaphore (0);
for( int j=0; j<number; j++ ) {
w[number-j-1] = new Worker (number-j);
w[number-j-1].start ();
}
System.out.println ("Eight workers have started.");
System.out.println ("Main thread continues work.");
for( int j=0; j<number; j++ ) {
System.out.println ("Main thread waits on semaphore " + (j+1) + ".");
future[j+1].Wait ();
System.out.println ("Main thread reads " + arr[j+1] + " from position "
+ (j+1) + ".");
sum = sum + arr[j+1];
}
System.out.println ("Sum = " + sum);
for( int j=0; j<number; j++ ) { // wait for workers
try { w[j].join (); } // to terminate
catch (InterruptedException e) { };
}
System.out.println ("System terminates normally.");
}
}
class Daemon {
private static int d[] = new int[] {0, 4, 4, 4, 6, 4, 6, 4, 6};
public synchronized void interrupt (int tid) {
if ( d[tid] > 4 )
{
System.out.println("worker "+tid+ " is interrupted.");
Thread.yield ();
}
}
}
class Semaphore {
private int value;
Semaphore (int value1) {
value = value1;
}
public synchronized void Wait () {
while( value <= 0 ) {
try { wait (); }
catch (InterruptedException e) { };
}
value--;
}
public synchronized void Signal () {
++value;
notify ();
}
}
class Worker extends Thread {
private int tid;
Worker (int tid1) {
tid = tid1;
}
public void run () {
System.out.println ("Worker " + tid + " begins execution.");
yield ();
System.out.println ("Worker " + tid + " doubles own array component.");
Future.arr[tid] = 2 * Future.arr[tid];
Future.daemon.interrupt (tid);
System.out.println ("Worker " + tid + " sets neighbor's array component.");
Future.arr[tid-1] = 1;
System.out.println ("Worker " + tid + " signals semaphore " + tid + ".");
Future.future[tid].Signal ();
System.out.println ("Worker " + tid + " terminates.");
}
}
E.Further improvement
F.File listing
1. semaphore.cpp (main)
file name: semaphore.cpp (main)
#include <iostream>
#include <windows.h>
using namespace std;
const int ThreadCount=8;
int array[ThreadCount+1]={1,-1,-1,-1,-1,-1,-1,-1,-1};
HANDLE mutex;
int params[ThreadCount]={0,1,2,3,4,5,6,7};
int daemon[ThreadCount]={1,1,5,1,6,1,6,1};
DWORD WINAPI run(LPVOID param);
HANDLE Workers[ThreadCount];
HANDLE semaphores[ThreadCount];
void interrupt(int i);
void display(char* str, int i);
int main()
{
int sum=0;
//this is mutex for cout, otherwise output will be messed up.
mutex=CreateMutex(NULL, false, NULL);
//create semaphores and initialized to unsignaled
for (int i=0; i<ThreadCount; i++)
{
semaphores[i]=CreateSemaphore(NULL, 0, 1, NULL);
}
//create threads with suspended and in descending order of index
for (i=ThreadCount-1; i>=0; i--)
{
Workers[i]=CreateThread(NULL, 0, run, ¶ms[i], CREATE_SUSPENDED , NULL);
}
display("Eight worker have started", -1);
display("Main thread continues to work", -1);
//equivalent to "start"
for (i=0; i<ThreadCount; i++)
{
ResumeThread(Workers[i]);
}
for (i=0; i<ThreadCount; i++)
{
display("main thread waits on semaphore ", i);
WaitForSingleObject(semaphores[i], INFINITE);
display("main thread reads ", array[i]);
sum+=array[i];
}
display("the sum is ", sum);
return 0;
}
void display(char* str, int i)
{
WaitForSingleObject(mutex, INFINITE);
cout<<str;
if (i!=-1)
{
cout<<i;
}
cout<<"\n";
ReleaseMutex(mutex);
}
void interrupt(int i)
{
if (daemon[i]>4)
{
display("interrupt of worker ", i);
Sleep(0);
}
}
//if you want to get result of 16, you have to comment out all
//display() because in order to "cout" properly, I used a "mutex"
//to block all concurrent "cout" within "display".
//So, you see all "displays" "divides" executions into independent
//parts, therefore the output is always 9 unless displays are commented out.
DWORD WINAPI run(LPVOID parameter)
{
//at first I thought I cannot declare local variable to replace this
//but finally I understand that thread has its own stack and some
//local variable, right?
int i=*((int*)(parameter));
display(" begins execution of worker of ", i);
//display(" begins execution of worker of ", i);
Sleep(0);
//display(" doubles own array component of worker of ", i);
array[i]*=2;
//array[*((int*)(parameter))]*=2;//
//the Professor's mistake is to add "synchronized" in front of
//interrupt, so it is equivalent to add a "wait" here
//and a release "mutex" or "semaphore after "interruption"
//This is explained very clearly by Mr. Mokhov and I learned it from
//him. Well done!
interrupt(i);
//interrupt(*((int*)(parameter)));
//display(" set neighbour's array component of worker ", i);
array[i+1]=1;
//array[*((int*)(parameter))+1]=1;
//display("send semaphore to ", i);
ReleaseSemaphore(semaphores[i], 1, NULL);
//display("terminates of worker of ", i);
return i;
}
Here is the result:
Eight worker have started Main thread continues to work begins execution of worker of 0 begins execution of worker of 1 begins execution of worker of 2 begins execution of worker of 3 begins execution of worker of 4 begins execution of worker of 5 begins execution of worker of 6 begins execution of worker of 7 main thread waits on semaphore 0 interrupt of worker 2 interrupt of worker 4 interrupt of worker 6 main thread reads 2 main thread waits on semaphore 1 main thread reads 2 main thread waits on semaphore 2 main thread reads 2 main thread waits on semaphore 3 main thread reads 1 main thread waits on semaphore 4 main thread reads 2 main thread waits on semaphore 5 main thread reads 1 main thread waits on semaphore 6 main thread reads 2 main thread waits on semaphore 7 main thread reads 1 the sum is 13 Press any key to continue