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