CSE 532S Half-Sync/Half-Async and Leader/Followers Studio

Please complete the required studio exercises listed below, along with the (optional) enrichment exercises if they interest you.

As you work through the exercises, please record your answers in a file, and upon completion please upload a file with your answers to the assignment page for this studio in Canvas.

Please make sure that the name of each person who worked on these exercises is listed at the top of your reply message, and that you number your answers so they are easy for us to match up with the appropriate exercise.


    Required Exercises

  1. As the answer to the first exercise, list the names of the people who worked together on this studio.

  2. Create a new empty directory for this studio (for example named something like hsha_lf).

    Add a main C++ source code file (which should be named something like hsha_lf.cpp) with a main function whose signature looks like the standard (i.e., portable between Windows and Linux) main function entry point for C++: int main (int, char * [])

    Write a simple function that takes an unsigned integer and returns a boolean result that is true if the value that was passed is a prime number, or false if it is not.

    In your main function, call the function you wrote with different values, some of which are prime and some of which are not, and for each of them print out a message saying what the number was and whether or not it is prime.

    Build and run your program, and as the answer to this exercise, please show your code and the output your program produced.

  3. Write a simple synchronization wrapper class for an output stream, with a constructor that takes a reference to an output stream and uses it to initialize a private member variable of the same type, a mutex or other lock that is also a private member variable, and a print method that takes a reference to a const string, acquires the lock, prints the string out to the output stream, and releases the lock.

    Using code from one or more of the previous studios, implement a thread pool (with at least several threads, though you may want to experiment with varying the number of threads) whose threads each can repeatedly (1) take an unsigned integer, (2) use the function you wrote to determine whether or not the number is prime, and (3) use the synchronization wrapper to print out (in a thread safe manner) to the standard output stream a message with the number and whether or not it is prime (hint: an input string stream can make it easy to convert the number and a string into a string).

    Modify your main program so that for each of the unsigned integers, instead of calling the function and printing out the message it hands off the number to a waiting thread from the pool, which then performs the work in parallel with the other threads in the pool which are handling other numbers. Build and run your program, and as the answer to this exercise, please show your code and the output your program produced.

  4. Modify your program so that when a thread is given a number it first checks whether or not the number is 0, 1, or an even number, and if so immediately prints out the appropriate message for that number and obtains the next number from the main thread. Otherwise it should take the number, go off and compute whether or not it is prime, and print the appropriate message - while another thread becomes the leader. Please also have the leader thread use the synchronous wrapper to print out a message with its thread id indicating when it first becomes the leader (before reading its first number) and when it is just about to cede the leader role to another thread.

    Note that this may require you to modify how threads are ordered to wait for the next number, i.e., each thread will become the leader when it first asks for a number and will continue to be the leader until it gets an odd number greater than 2, before any other thread should be able to become the leader.

    In your main function, hand off many numbers to the thread pool, of varying sizes and kinds (some even, some odd, some large, some small), so that the leader role is exercised to a reasonable extent by each thread that becomes the leader but leaders also change reasonably often.

    Build and run your program, and as the answer to this exercise, please show your code and a representative sample of the output your program produced which indicates.

  5. Modify your main function so that instead of producing the numbers itself, it reads them from the standard input stream (cin), and then immediately hands each one off to the thread pool.

    Build and run your program, and try running it both by typing numbers in one (or a few) at a time in the terminal window (hitting enter feeds the line to cin) and by streaming a file (e.g., populated with the numbers that main used in the previous exercise) to the program's standard input. As the answer to this exercise, please describe what you saw in terms of (1) how responsive the program was when you typed in the numbers manually, and (2) how rapid the program's throughput was when you streamed the numbers from a file, both relative to each other and to what you observed in the previous exercise.

    Enrichment Exercises (Optional)

  6. Modify your solution to the previous exercise so that (unless you did so already in the previous exercises), the thread waiting and leader election protocol involves a condition variable and a pluggable leader election condition (e.g., setting a thread id to 0 when a new leader is needed, etc.). Build and run your program and as the answer to this exercise please show your code, and describe your design.

  7. Implement a termination protocol so that the user can type in "quit" instead of a number, and have the threads be safely interrupted and terminate, after which the main thread exits cleanly. Build and run your program and as the answer to this exercise please show your code, and describe your design.