(Latest revision 2017/11/05)
[2017/11/05: Clarified that one team member only sends e-mail]

CS 3750 First C++ Concurrent Programming Assignment (prog #1)

  1. Review the sample programming assignment solution, dmnd.cpp and possibly some of the other documents in the sampleAssignment subdirectory of the ThreadInfo subdirectory in the class web space. This material illustrates what you need to know about using function calls from the pthreads package on the CS Lab Macs, and about using the queuing semaphores implemented by the sem.cpp and sem.h files. Make copies of the versions of sem.cpp and sem.h in this assignment space for your own use. (Ask any questions you have about this in class.)

  2. Starting with the skeleton program called sequence.cpp, you must add code that uses queuing semaphores to ensure that the constraints listed at the beginning of the program are enforced.

    As the comment in the program states, threads 0, 1, and 2 may begin executing their (simulated) task any time after the mother creates these threads. Threads 3, 4, and 5 are required to start their tasks only after certain threads have completed their tasks, as detailed in the program comment. You need to add code that uses semaphores to ensure that these timing constraints are enforced.

    Each of the child threads also is required to increment a counter. This is a critical section problem. You need to add code to the program to solve that critical section problem.

    The synchronization that accomplishes the above must be done by employing the semaphore data types implemented by the files sem.cpp and sem.h. You don't get ANY credit unless you achieve the results with semaphores.

    Notice that, in addition to the constraints mentioned above, there is also a need to enforce mutually exclusive access to standard output (the computer screen). Enforcing the constraints above does not guarantee that two threads (say threads 3 and 5) will not try to write their messages to the screen concurrently. This could cause the messages from the two threads to be written to the screen in a jumbled interleaving.

    We want the message of each thread to be written atomically, on its own separate line of the output. This is really an additional critical section problem that has to be solved by the program. However, you don't have to do anything at all about it, because I put code in the skeleton program that takes care of it.

    Solve the problem in a distributed fashion. In other words, if thread X needs to wait until thread Y is in place, then program thread X and Y to communicate with each other. Don't try to program a 'third party' that tells both X and Y what to do and when to do it. Use semaphores. Keep things simple. Any synchronizations you program must guarantee freedom from all forms of indefinite postponement.

    You must use only semaphores to make processes wait for events. In particularly, and importantly, you are not allowed to use a while-loop that keeps iterating until some condition becomes true. You are not allowed to use loops like the ones we studied in Peterson's algorithm, for example. You are also not allowed to use similar loops that repeatedly wait on a semaphore. If a thread needs to wait for some event, it should be able to do that by executing a single wait_sem operation on a sim_semaphore variable.

    If you feel you have to program a "wait-loop," you are thinking about the program in the wrong way, and you should get some help from me and figure out a different approach.

    The program has a "mother" task that creates the six child threads, and you must retain that structure. (Add code only in the manner directed in the comments of the skeleton program.) The group of children must somehow notify the mother thread after all the children have completed their (simulated) tasks. The mother has to make sure all the children have finished with their messages before the mother exits.

  3. Figure out a protocol that allows the mother and threads to cooperate to do the job indicated above. Once you have decided on the protocol, write it down in pseudo-code form and e-mail it to me by the first due date. You should send me a copy of the sequence.cpp skeleton program with your pseudo code inserted in the appropriate places - where the "real code" will go later.

    By the second due date, send a complete, compilable, listing of sequence.cpp 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!) Also, place copies of test scripts in a separate file, and e-mail that to me too.

    (Remember: I don't accept attachments to e-mails. So don't send me any of those. Send a shell archive as inline text - more about how to do that further on.)

    (Beware: since some errors in concurrent programs are timing-dependent, you will need to think of some novel ways to test your program. The sample assignment solution and the skeleton version of sequence.cpp have code that illustrates this idea. If you want, you can ask questions in class to work on more ideas.)

    Please do not send me copies of sem.h or sem.cpp. I have those. I will use my copies to compile with your program for testing.

    Double Please: Do not send me copies of your compiled code. I don't want it and it will snarl up my e-mail.

    Just send me your source code, only the main module: sequence.cpp I will compile it on a CS Lab Mac with my own Makefile and copies of sem.h, sem.cpp. Your program should work for me if it worked for you.

    For this assignment, you may work in teams of two (2) people, but you don't have to if you don't want to. If you work in a team, make sure that both names are in your comments! If you don't understand something, ask me questions. Don't expect "magic enlightenment." :-)

More Discussion of the Assignment

When you think about doing this assignment, imagine that the mother thread and each child thread can run on a separate CPU of a tightly-coupled multiprocessor. The program may or may not actually use multiple cores or CPUs. The point of this exercise is for you to write a program that will work on *any* computing system on which multiple processes can execute concurrently while sharing variables.

A tightly-coupled multiprocessing system can be diagrammed this way:
  CPU     CPU     CPU      CPU     CPU     CPU   CPU    MEMORY
    |       |       |        |       |       |     |    |
 ------------------------------------------------------------ BUS
       |      |       |     |     |     |     |     |     |
     CPU    CPU     CPU   CPU   CPU   CPU   CPU   CPU   CPU
Here we have a RAM memory being shared over a common bus by several CPUs. It is possible that the different CPUs have radically different effective speeds. Speed can be affected by the inherent power of the CPU, or by the current load on the CPU. Besides that, it is impossible to tell which CPU will be assigned to which thread. And also, each time we run the program, the assignment of threads to CPUs can be different.

In your program, the mother process creates all the children without delay, immediately after the program starts running. (Don't change that!) After creating them, the mother must do nothing to direct the actions of the children. In general it is a bad idea to create "traffic cop" threads that "direct traffic", because the traffic cop too often becomes a bottleneck. When every action has to be approved by a controlling process, events can only happen as fast as the boss can approve them. This would often defeat the purpose of parallel processing.

I gave you a good skeleton program. Just add code in the places indicated, so that the program starts working correctly. Don't rewrite the program in other ways.

The only interactions ANY child is allowed to have with its mother, after its creation, is that a child is allowed to notify the mother after it has completed its task and written its message to standard output.

The children must cooperate among themselves, using semaphores for synchronization, to perform their tasks in a correct order. As to the decision of when a child X performs its task, only X and the children that are required to precede X are allowed to participate in the making of that decision.
The general rules for submitting assignments by e-mail are:

Here is the list of things you have to turn in:

  1. On the first due date e-mail a pseudo-code description of the algorithm for your solution (in-line in a copy of the skeleton program). ["Pseudo-code" is not a synonym for "vague and/or incomprehensible" :-). It means you describe specifically exactly what the code you are going to insert will do, in a step-by-step, algorithmic fashion, but you are not required to obey the syntax of the C++ programming language. You just write the steps in clear English.]

    Use this subject line for the e-mail of the pseudo-code:

    CS3750Prog1Pcode

  2. On the second due date e-mail a shar file containing:


    Use this subject line: CS3750Prog1Final

Note that there are no spaces in the subject lines given. It is important that you do not insert any spaces. My e-mail address is: john@ishi.csustan.edu.


DUE DATES:

For due dates, see the class schedule.