(Latest Revision: 11/23/2006)
(Thu Nov 23 20:56 2006: changed some wording regarding what to turn in.)

CS 3750 Second Concurrent Programming Assignment


Due Friday, December 2: psuedo-code description of the algorithm for your solution. Put a hardcopy in front of me at the start of class.

Due Friday, December 9: One shell archive file (only one) containing items 1-2.
  1. the completed program source code (only your code - do not send me a copy of sem.cpp or sem.h)
  2. one or more script(s) documenting thoughtful, adequate, intelligent testing

Step 1

Read the file conc.strp.cpp. It shows how you can spawn threads and use semaphores to synchronize their activities. The file also illustrates the use of a random number generator.

After studying conc.strp.cpp examine conc.cpp. This file is functionally nearly identical to conc.strp.cpp The differences are firstly that conc.cpp. is set up to write many messages to the screen, secondly that conc.cpp. has some code containing extra calls to sched_yield() that are used to delay threads, and thirdly that conc.cpp. has (commented-out) code that changes an operation that may be implemented atomically into one that will not be atomic (unless the compiler is too determined to "optimize").

All these things are useful for testing the code.

The messages provide a sort of "play-by-play" commentary that allows the programmer to run the program and then figure out what each thread did, and when it did it relative to the time lines of the other threads.

The other coding variations affect timing characteristics thus helping to search for latent, time sensitive errors. You should try to slow down various threads in different runs to help in testing.

Optional Reading

After looking at conc.cpp. you may want to examine sem.h and sem.cpp, which implement counting semaphores that behave precisely according to the specifications for counting semaphores in your text book.

You may also look at pthread_info.html if you want more information about pthreads. There is also some information in our text book.

Step 2.

Do the concurrent programming problem described in the problem description.

For synchronization of concurrent threads, use only the counting semaphores implemented by sem.h and sem.cpp. The one exception is that, just as conc.cpp. does, you are allowed to use the pthread_mutex_t called stdoutLock to lock stdout for printing messages.

In particular, there must be no spinlocks, no busy waiting of any kind used for the synchronization in your program, with the exception of whatever (hidden) busy waiting might be involved in the implementation of the semapore and pthread_mutex_t operations.

When I say that the semaphores must be used to do all the "synchronization" of concurrent threads, I mean any critical section problem or any protocol that controls the chronological order in which threads interleave their actions. If that's not sufficiently clear, ask me about it, because your grade will count heavily on this issue.

Incidentally, all that you have to do for this assignment is write a main program. Let's say the name of your program is packets.cpp protocol.cpp. To interface this program with other modules, please place the following statements at the beginning of packets.cpp: protocol.cpp:
#include <iostream>
#include <sched.h>
#include <time.h>
#include <pthread.h>
#include <string>
#include "sem.h"

using namespace std ;

         /* "Checking" is just a flag that you set to 1 if you want lots of
	    debugging messages and set to 0 otherwise.  The semaphore code in
	    sem.cpp imports "checking".  Therefore the semaphore operations
	    will write lots of messages if you set checking=1.  */

int checking ; 

      /* Use this flag to turn on checking in your main program file. */

int  my_checking ;

      /* In some programs, we use the "stdoutLock" variable declared below to
	 get intelligible printouts from multiple concurrent threads that
	 write to the standard output.  (There has to be something to prevent
	 the output of the threads from interleaving unintelligibly on the
	 standard output, and we can't use semaphores if the semaphore code is
	 writing messages too.)

         To print a message to standard output, a thread first locks standard
	 output, then writes, then unlocks standard output.  See files sem.cpp
	 or conc.cpp for examples of code that write messages in this manner.

         WARNING:  DON'T change how the locking of standard output is done
	 until you've thought a WHOLE lot about the consequences.  In
	 particular, using semaphores to do the job of stdoutLock can cause
	 "infinite recursion" under certain circumstances.  The reason is that
	 the semaphore code itself imports "stdoutLock" and writes messages
	 when the "checking" variable is set to 1. */

pthread_mutex_t stdoutLock ;

Then compile packets.cpp protocol.cpp. with the sem.cpp module by typing the following on the command line:
g++ sem.cpp  packets.cpp -lpthread -lposix4
If you do this, all you have to send me is the main module, packets.cpp protocol.cpp. and I will compile it on a Sun Ultra with my own copies of sem.h, and sem.cpp, in the same directory, so it will work for me if it worked for you. (If you used my template header file, protocol.h, and made changes to it, you'll have to send me a copy of that too.)

Step 3.

E-mail a complete, compilable, source listing with adequate comments (The bottom line on the question of documentation is that I need to be able to read and understand your program!) Send it to john@ishi.csustan.edu before midnight on the due date. I will compile and run the program as a part of the grading procedure.

By the way: Your source file should contain lots of extra code like the code conc.cpp. has for printing extra messages and changing timing. Your program has to do a good job of being self-testing. Rig your program so I can change the value of "my_checking" and recompile to turn your extra messages and other testing features on and off. Keep separate "checking" and "my_checking" flags. The flag called "checking" should control only the checking that happens in sem.cpp.