Project 3: Synchronization
This project consists of two synchronization problems.
Problem 1: Caltrain Automation
Caltrain has decided to improve its efficiency by automating not just its trains but also its passengers. From now on, passengers will be robots. Each robot and each train is controlled by a thread. You have been hired to implement synchronization that will guarantee orderly loading of trains. You must define a Station
class that provides three methods:
When a train arrives in the station and has opened its doors, it invokes the method
load_train(int available)
where
available
indicates how many seats are available on the train. The method must not return until the train is satisfactorily loaded (all passengers are in their seats, and either the train is full or all waiting passengers have boarded).When a passenger robot arrives in a station, it first invokes the method
wait_for_train()
This method must not return until a train is in the station (i.e., a call to
load_train
is in progress) and there are enough free seats on the train for this passenger to sit down. Once this method returns, the passenger robot will move the passenger on board the train and into a seat (you do not need to worry about how this mechanism works).Once a passenger is seated, it will call the method
seated()
to let the station know that it’s on board.
Here is some additional information for this problem:
- You may assume that there is never more than one train in a given
Station
at once, and that all trains (and all passengers) are going to the same destination. Any passenger can board any train. - Your code must allow multiple passengers to board simultaneously (it must be possible for several passengers to have called
wait_for_train
, and for that method to have returned for each of the passengers, before any of the passengers callsseated
). - It must be possible to have multiple
Station
objects operating independently (activities in oneStation
should not affect any otherStation
).
Problem 2: Party Introductions
You have been hired by Stanford’s Greek Houses to help manage parties at fraternities and sororities. In particular, you must create a C++ class Party
with a single method that can be used to introduce incoming guests to each other. When a guest arrives at a party, they will invoke the following method on a Party
object:
std::string meet(std::string &my_name, int my_gender, int other_gender);
The my_name
argument gives the name for this guest and my_gender
indicates the guest’s gender. The other_gender
argument indicates that this guest would like to meet someone of that gender. The meet
method must not return until a guest has arrived with matching gender
and other_gender
, and meet
must return the name of the matching guest. In addition:
- Guests must be matched: if A receive’s B’s name, then B must receive A’s name.
- If a suitable match is not immediately available, then
meet
must wait until a match becomes available. In the meantime, it must be possible for non-interfering matches to occur. - Genders are specified with small non-negative integers;
MAX_GENDER
gives the largest possible gender, and you can assume this is relatively small (not more than a dozen or so). Themy_gender
andother_gender
arguments can potentially be the same, of course. - It must be possible to have multiple
Party
objects all operating independently (activities in oneParty
should not affect any otherParty
). - Guests must be matched in order of arrival, where “arrival” means starting execution of
meet
and locking the synchronization mutex.
Developing and Testing
To get started on this project, login to the myth cluster and clone the starter repo with this command:
git clone https://web.stanford.edu/class/cs111/starters/sync.git cs111_p3
This will create a new directory cs111_p3
. Do your work for the project in this directory. The directory will contain files caltrain.cc
and party.cc
with class and method declarations for the two problems: fill in the existing declarations and add any other definitions or methods that you need.
The directory also contains a Makefile
; if you type make
, it will compile your code for both problems. caltrain.cc
will be compiled together with a test program caltrain_test.cc
, and party.cc
will be compiled together with a test program party_test.cc
. You can invoke the command ./run_tests
to run a series of basic tests on your solution. In addition to running tests with run_test
, you should also test your Caltrain solution by invoking the following command:
./caltrain_test random
This runs a randomized test with a large number of waiting passengers and a variety of trains with different capacities. Check the output manually to make sure there are no errors. Try running this test many times, in order to generate a variety of scenarios.
We do not guarantee that the tests we have provided are exhaustive, so passing all of the tests is not necessarily sufficient to ensure a perfect score (CAs may discover other problems in reading through your code).
Complexity Penalty
Synchronization code is hard to get right, so it’s important for it to be clean, simple, and obvious. Unfortunately, submissions for this project often end up long and complicated; such solutions rarely work, and in real life they would be brittle and hard to maintain. If the CAs judge your code to be unnecessarily long and complicated, they will deduct up to 20% of the total score for this. Our solution for caltrain.cc
has 49 lines and our solution for party.c
has 38 lines, not including blank lines and comments. Note: your goal should be simplicity, not just line count; simple programs are usually shorter than complex ones, but the shortest program isn’t always the simplest.
Other Requirements
- Your solutions for both problems must be written in C++.
- You must use the C++ library classes
mutex
andcondition_variable
for synchronization. You should also use thelock_guard
orunique_lock
class to ensure proper release of locks. - You may use other STL container classes (
vector
, etc.) in your solutions, but you may not use any classes that simplify the synchronization issues. If you have any doubt about whether a class is acceptable or not, please check with the course staff. - There must be no busy-waiting in your solutions.
- You must use the monitor style for synchronization, as discussed in lecture. In particular, you may not use more than one
mutex
perCaltrain
orParty
object. - You may assume that there are no spurious wakeups on condition variables.
Submitting Your Work
To submit your solutions, cd
to the directory containing your work, then invoke the command
./submit
If you discover problems or improvements after you have submitted, you may resubmit; only the latest submit will be graded.