CS202: HW 4: More concurrency practice

CS202: HW 4: More concurrency practice

These problems should be done on your own. You get credit if you turn in something, and we are not checking the correctness. So these exercises exist purely to reinforce the material, not to evaluate you.

Getting help from AI (besides being ruled out by the course policies) will actually hurt you, since the point of these questions is for you to gain the practice and experience of working through the problems.

You will need that general skill (of absorbing something by practicing it) in life, and in this semester you will need the specific problem-solving skills that are emphasized in these homeworks.

Synchronization: warmup

This problem is based on the following code (which is similar to the problem above):

    int i = 0; 

    /* ADD SOME THINGS HERE */

    void
    foo(void *)
    {
        printf("I am foo!!!\n");
        
        /* ADD SOME CODE HERE */
    }

    void
    boo(void *)
    {
        /* ADD SOME CODE HERE */

        printf("I am boo!!!\n");
    }

    int
    main(int argc, char** argv)
    {
        create_thread(foo);
        create_thread(boo);

        // wait for threads to finish
        // before exiting
        join_thread(foo);
        join_thread(boo);

        exit(0);
    }

Modify the code above to ensure that I am foo!!! prints before I am boo!!!. Use mutexes and condition variables.

Using a mutex doesn’t mean it’s right

Alice and Bob each have an account in a bank. Bob wants to transfer money to Alice. (We write the code below in terms of the synchronization primitives that you will see in Lab 3.)

// assume all the variables are initialized correctly
double alice_balance, bob_balance;
smutex_t mtx;

bool
transferBob2Alice(double trans) {
  if (bob_balance > trans) {
    smutex_lock(&mtx);
    bob_balance = bob_balance - trans;
    alice_balance = alice_balance + trans;
    smutex_unlock(&mtx);
    return true;
  }
  return false;
}

The implementation of function transferBob2Alice is not correct.

  1. What's wrong? (Give a problematic interleaving.)
  2. State the fix in one sentence.

Smokers

Consider a system with three smoker processes and one agent process. Each smoker continuously rolls a cigarette and then smokes it. But to roll and smoke a cigarette, the smoker needs three ingredients: tobacco, paper, and matches. One of the smoker processes has paper, another has tobacco, and the third has matches. The agent has an infinite supply of all three materials.

The agent places two of the ingredients on the table. The smoker who has the remaining ingredient then makes and smokes a cigarette, signaling the agent on completion. The agent then puts out another two of the three ingredients, and the cycle repeats.

Assume the agent calls the procedure

void chooseIngredients(int *paper, int *tobacco, int *match);

to randomly select 2 of the 3 ingredients. The routine randomly sets 2 of the ints to "1" and one of them to "0". You don't have to write this routine.

Write a program to synchronize the agent and smokers:

  1. What synchronization and state variables will you use in this problem? (For each variable, indicate the variable's type, the variable's name, its initial value (if any), and a short comment describing the variable's purpose.)

    Variable Name        Variable Type        Initial Value        Description

  2. Write the routines Agent() and matchSmoker() (the routine for the smoker that has lots of matches). You don't have to write the routines paperSmoker() or tobaccoSmoker(), but your solution should be general enough so that those routines would be simple variations of matchSmoker().

Auction

In this problem you will simulate a simplified auction, encapsulated in a monitor, Auction. Your job is to finish the implementation of Auction. Here is the specification:

  • Auction has NUM_BIDS slots to hold bids; an auction can happen only when all of these slots are full.

  • There are endless buyer threads, each of which makes a bid by calling the Auction::RegisterBid() method. If there are no free slots to hold bids, this method must wait. Otherwise, this method inserts its bid into a free slot (after which the slot is no longer free). After it does so, the method returns; in particular, the method does not wait for the results of the auction.

  • There are one or more auctioneer threads, which each call the Auction::SelectWinner() method. This method simulates a single auction. Per the first bullet, this method can proceed only if all slots are occupied. Otherwise, it waits. When it does proceed, it computes the maximum bid from among all candidate bids in the Auction, clears all of the slots, and returns the maximum bid.

  • You must follow the class’s concurrency commandments.

  • Don’t wake threads unnecessarily.

Hint: Write helper functions, for example to determine whether there are free slots.

Where indicated, fill in the variables and methods for the Auction object. Remember to follow the concurrency commandments.

Auction auction;  // global

class Auction {

    public:
        Auction();  
        ~Auction();
        void RegisterBid(uint32_t amount);
        uint32_t SelectWinner();

    private:
        uint32_t bids[NUM_BIDS]; // bids[i] == 0 means that slot i is free

        // ADD MORE HERE





};


Auction::Auction()
{
    memset(bids, 0, sizeof(bids));

    // FILL THIS IN






}

void
Auction:RegisterBid(uint32_t amount)
{
    // We use 0 to mean "slot free"
    assert(amount > 0); 

    // FILL THIS IN
    





}



uint32_t
Auction:SelectWinner()
{

    // FILL THIS IN







}

Handing in the homework

Use Gradescope; you can enroll in our course with entry code J44YWJ.