CSCI-541 Programming Skills: Efficient Design in Modern C++
Project 2 - Beehive

Due Date: End of day, Tuesday, April 30th, 2019

Revision History:

Table of Contents:

Introduction

Goals

The goal of this lab is for students to gain experience with fundamental concurrency topics in modern C++ such as:

Overview

The bees in the beehive are buzzing! If you recall from science class, a bee in a typical colony has one of three distinct roles:

Simulation

At the start of the simulation there will be one queen, any number of drones and workers, and no resources in the beehive. These are the details of the time it takes for each type of bee to perform a single task.

Design

You are responsible for coming up with a reasonable design for this project, and part of your grade will reflect it. These are the guidelines you should follow:

Starter Code

You are being provided with a suggested structure for the project, along with makefiles that support both CLion and Unix. You are free to change this structure however you wish, but make sure you modify the makefiles so they can properly build. Remember, in the end your project must submit to try and compile on the CS machines to be considered a valid submission for grading.

Access the starter code here. If you are developing with CLion remember to move the src/CMakelist.txt file to the top level of your project.

Project Structure

Your project structure should look like the following once you have the starter code. Note that there are three directories intended to define their own namespaces, bee, util and world. Make sure you put the source files in the right location.

Implementation

Command Line

The program can be run on the command line as:

    $ bee_main seed seconds drones nectar_workers pollen_workers

If the number of arguments are correct, they are guaranteed to be valid integers. The seed is the value that should be provided to the random number generator.

If the number of arguments is incorrect, display a usage message and exit the program, i.e.:

    Usage: bee_main seed seconds drones nectar_workers pollen_workers

Input

This program has no user input outside of the simulation numbers provided on the command line. Your program should not prompt for any input while running and should run the simulation to completion.

Output

Look here for a bunch of sample runs that show the format of the messages you should create. These are all good things to test your code with to make sure you are running correctly. Of course there is no guarantee that the output for any of these will be the same as yours, based on the random number generator and the very nature of threads in general.

Output Detail

Before the simulation starts you should display the command line arguments to standard output in the format:

Seed: #
Simulation time: # seconds
Starting drones: #
Starting nectar workers: #
Starting pollen workers: 4#

When the simulation is over you should display the following statistics of the simulation to standard output:

STATISTICS
==========
Bees born: #
Bees perished: #
    {bee}
    ...
Nectar remaining #
Pollen remaining #
Nectar gathered #
Pollen gathered #

When the simulation is running all messages will start with a tag that indicates which component of the system the message came from.

Bee: *B*

When a new bee is born a message should be displayed. The queen is always the first bee:

    *B* QUEEN #1 is born

You can create the drones and workers in whatever order your want. The solution creates all the drones before the workers, and all the nectar workers before all the pollen workers. Notice that the workers display additional information incuding the resource and how much of that resource they will continually gather, e.g. RESOURCE(#).

    *B* DRONE #2 is born
    ...
    *B* NECTAR(1) WORKER #4 is born
    ...
    *B* POLLEN(5) WORKER #8 is born
Beehive: *BH*

After the bee's have been created, and when the beehive is about to become active, you should display a message to standard out. This message should come before any bee thread messages.

    *BH* Beehive begins buzzing!

Likewise, when the simulation is over and you have joined on all the bee threads, the last thing you should display before the statistics is:

    *BH* Beehive stops buzzing!

If there is additional bee thread output after this message, you have a problem in your design and you are not correctly joining on all the bee threads when the beehive becomes inactive.

When a bee perishes, you should display a message to standard output, e.g.:

    *BH* DRONE #3 perished!
    ...
    *BH* NECTAR(1) WORKER #4 perished!
    ...
    *BH* POLLEN(2) WORKER #10

When a worker bee deposits a resource into the beehive, you should display a message to standard output:

    *BH* NECTAR(6) WORKER #7 deposits resources
    ...
    *BH* POLLEN(5) WORKER #10 deposits resources
Flower Field: *FF*

When a worker bee requests entry into the flower field, you should display a message to standard output:

    *FF* NECTAR(2) WORKER #9 enters field
    ...
    *FF* POLLEN(1) WORKER #13 enters field

Likewise, when a worker bee leaves the flower field, you should display a message to standard output:

    *FF* POLLEN(2) WORKER #13 leaves field
    ...
    *FF* NECTAR(1) WORKER #9 leaves field
Queen: *Q*

Each time the queen successfully mates you should display a message to standard output showing the drone she mated with:

    *QC* Queen mates with DRONE #6

After mating and all the new bees have been created for this task, the queen displays to standard output how many new bees were created:

    *Q* Queen birthed 4 children
Queens Chamber: *QC*

When a drone enters the chamber you should display a message to standard output:

    *QC* DRONE #15 enters chamber

Likewise when a drone leaves the chamber you should display a message to standard output:

    *QC* DRONE #15 leaves chamber
Worker: *W*

Every time a worker returns from the field you should display a message to standard output that they are going to attempt to "refuel":

    *W* NECTAR(1) WORKER #6 is refueling
    ...
    *W* POLLEN(1) WORKER #13 is refueling

Implementation Details

Custom Random Number Generator

You are being provided with a util::random class that you should use to seed the random number generator at the start.

Thread Safe Logger

You are being provided with a util::logger class that you should use for all the threaded output.

A "Java-like" C++ Thread Class

You are being provided with a util::my_thread class that you can use for your bees to inherit from. Using this class is totally optional and is not necessary.

Main Program

The main program should be small. It should be responsible at most for the following things:

Beehive

The beehive is the central class in the simulation. It is responsible for doing the following things:

Flower Field

The flower field is a monitor that the worker bees use in order to keep track of how many workers are currently "in the field". There is a limit of 10 workers at once in the field, and they must obey this. If the limit is not reached, they can gather, otherwise they must wait and get notified by another worker bee who has finished gathering. The order the bees gather from the field is random and unpredictable.

Queen's Chamber

The Queen's chamber is a more complicated monitor than the flower field. It is used by both the Queen and the drone bees in order to facilitate reproduction of new bees. Unlike the flower field, the drones must line up in order when they enter the queen's chamber. If the queen is not ready to mate, the drones must wait. When the queen is ready to mate, she will notify all of the drones that she is ready, and the drone that is at the front of the line will unblock and come out of the line to mate with the queen. After mating the drone will perish. The queen will create between 1 and 5 new bees randomly, as long as there are enough resources.

At the end of the simulation, there may be drones still waiting in the Queen's chamber. It is the queen's job to dismiss each drone individually, until there are no more drones waiting in line inside her chamber.

Valgrind and Threads

If you are testing for memory management using valgrind on the CS machines, you should force the testing to run on a single CPU. Otherwise you will inevitably run into hangs. To do this run the following command:

    $ taskset --cpu-list 1 valgrind bee_main # # # # #

Thread Sanitizer

This handy tool from Google is built into GCC and you can use it to detect things like race conditions in your code. The downside of using this is that valgrind will not work, so use it only to debug and then remove it. To enable it, you should add the following two extra flags at the end for CXXFLAGS in all the Unix makefiles:

    CXXFLAGS = -g -gdwarf-2 -Wall -Wextra -Weffc++ -pedantic -std=c++17 -pthread -fsanitize=thread -O2

Road Map

Here is the suggested road map for how you should develop things:

  1. Implement the bee and worker.
  2. Have the beehive create the worker bees and be able to start and join on them.
  3. Implement the flower field.
  4. Connect the flower field to the workers and flesh out the worker's run method so that they do their job correctly.
  5. Implement routines in the beehive that allow depositing of the resources. At this point you should see the resources being stored and everything should add up correctly.
  6. Implement queen and drone bees.
  7. Have the beehive create both the queen and the drones and be able to start and join on them.
  8. Implement the queen's chamber.
  9. Connect the queen's chamber to queen and drone bees.
  10. Write the drone's run method. Test that the drone's can enter the chamber and they wait until the queen is ready.
  11. Implement the queen's run method. To begin with you don't have to worry about creating new bees. Just make sure that you can run the simulation and at the end she can dismiss each of the drone's so that no threads are left running with the simulation ends.
  12. Finally, focus on finishing the main loop of the queen's run method. When the conditions are met the queen should mate with the correct drone and a random number of new bees should be created and successfully started. Since all the bees are stored in the beehive, there should be a thread safe routine that allows for new bees to be added to the beehive, after the simulation has started.

Submission

You must have all your code on the CS machines in order to submit to try. You should be able to build already with the supplied makefiles. These are the steps you should follow:

Grading

The grade breakdown for this projet is as follows: