Programming Assignment II
Due on Friday, October 17, 2008 @ 11pm
70 points
Hungry Eagles
A family of eagles has one mother eagle, n baby eagles,
and m feeding pots initially empty,
where 0 < m <= n.
Each baby eagle must eat using a feeding pot and each feeding pot can only
serve one baby eagle at any time. Therefore, no more than m
baby eagles can eat at the same time. The mother eagle eats elsewhere and
does not require a feeding pot.
Each baby eagle plays for a while and eats. Before a baby eagle can eat, he
must wait until a feeding pot has food.
After eating, the corresponding feeding pot becomes empty and has to be
refilled by the mother eagle.
The mother eagle is very tired and needs sleep. So, she goes to sleep until a
baby eagle wakes her up. Should this happen, the mother eagle hunts for food
and fill all feeding pots. Then,
she sleeps again. It is possible that when a baby eagle wants to eat
and finds out that all feeding pots are empty. This baby eagle should wake
up the mother eagle. As mentioned in the previous paragraph, the mother eagle
takes some time to hunt for food and fill all feeding pots. Once all feeding
pots are filled, no more than m waiting hungry baby eagles can
eat. Since the mother eagle does not want to wake up too often, she insists
that exactly one baby eagle who found out all feeding pots being empty can
wake her up. More precisely, even though two or more hungry baby eagles may
find out all feeding pots being empty, only one of them can wake her up and
all the others just wait until food will become available.
After providing the t-th meal, the mother eagle retires and sends
all of her baby eagles away to start an independent life. Perhaps, she needs
a vacation, and, therefore, the feeding game ends!
In the system, eagles are simulated by threads. Initially, the
m feeding pots are all empty. Each baby eagle thread
has the following pattern:
while (1) {
Delay(); // play for a while
ready_to_eat(...); // get hungry
Delay(); // eat for a while
finish_eating(...); // finish eating
// do some other thing
}
The mother eagle thread has the following pattern:
while (not time to retire) {
goto_sleep(...); // take a nap
Delay(); // prepare food
food_ready(...); // make food available
Delay(); // do something else
}
Here, functions
ready_to_eat(),
finish_eating(),
goto_sleep() and
food_ready() are functions written
by you. They have the following meaning:
- ready_to_eat()
blocks the caller, a baby eagle, if all
feeding pots are empty. One of the baby eagles who finds out
all feeding pots being empty should wake up the mother eagle.
This function returns only if there is a feeding pot with food
available to this baby eagle.
- finish_eating()
should be called when a baby eagle finishes his meal.
- goto_sleep()
is only called by the mother eagle when she
wants to take a nap.
- food_ready() is called
when the mother eagle has finished
adding food in all m feeding pots.
In this way, all controls and synchronization mechanisms are localized in
these four functions and the eagle threads look very clean.
Write a C++ program using the semaphore capability of
ThreadMentor
to simulate this activities.
Your implementation must correctly handle the following
important situations among others:
- At any time, there are no more than m baby eagles
eating.
- A baby eagle must wait when he wants to eat but has no free
feeding pot and/or all free feeding pots are empty.
- If there is a non-empty feeding pot, a hungry and ready-to-eat
baby eagle can eat.
- No hungry baby eagle will eat using an empty feeding pot.
- At any time, a feeding pot can only be used by one eating baby
eagle.
- Only one baby eagle among all baby eagles who want to eat can
wake up the mother eagle.
- The mother eagle does not do her work until a baby eagle wakes her up.
- While the mother eagle is preparing food, no baby eagle can wake
up the mother again until the mother goes back to take a nap.
- Before all m feeding pots are filled, no hungry
baby eagle can eat.
- Once the feeding pots are refilled, the mother eagle must allow
baby eagles to eat. Then, she goes back to sleep.
- You must terminate your program gracefully. More precisely,
if t feedings are needed, then your program
cannot terminate right after
the mother eagle refills the feeding pots t times.
Instead, your program must wait until all feeding pots become
empty, even though there may be baby eagles waiting for food.
You can only use semaphores and mutex locks.
The use of any other synchronization primitives will risk low or even no
credit.
Input and Output
The input to your program consists of the following:
- The number of feeding pots m,
number of baby eagles n, and
number of feedings t should be taken from the command
line arguments as follows:
prog2 m n t
Thus, prog2 8 15 12 means there are 8 feeding pots, 15 baby
eagles and 12 feedings. If any one of these command line arguments
is 0, the default value 10 should be used. For example,
prog2 3 0 0
means that there are 3 feeding pots, 10 baby eagles
and 10 feedings.
You can assume that command line
arguments satisfy 0 < m <= n <= 20 and t > 0.
- Your program should generate an output similar to the following:
MAIN: There are 10 baby eagles, 5 feeding pots, and 8 feedings.
MAIN: Game starts!!!!!
......
Baby eagle 3 started.
......
Mother eagle started.
......
Baby eagle 6 started.
......
Baby eagle 3 is ready to eat.
......
Mother eagle takes a nap.
......
Baby eagle 5 is ready to eat.
......
Baby eagle 2 sees all feeding pots are empty and wakes up the mother.
Baby eagle 8 is ready to eat.
Mother eagle is awoke by baby eagle 2 and starts preparing food.
Baby eagle 1 is ready to eat.
......
Mother eagle says "Feeding (1)"
......
Baby eagle 5 is eating using feeding pot 3.
......
Mother eagle takes a nap.
......
Baby eagle 3 is eating using feeding pot 1.
......
Baby eagle 5 finishes eating.
......
......
Mother eagle says "Feeding (8)"
Baby eagle 1 is ready to eat.
......
Mother eagle retires after serving 8 feedings. Game ends!!!
Due to the dynamic behavior of multithreaded programs, you will not
be able to generate an output that is exactly identical to the above.
- All output lines from the mother eagle starts on column 1 and
baby eagle i's output lines have an indentation of i
spaces.
- The following output line tells us that baby eagle 3 has started:
Baby eagle 3 started.
- The following output line tells us that baby eagle 5 is ready to eat:
Baby eagle 5 is ready to eat.
- The following output line tells us that baby eagle 5 is eating using
feeding pot 3:
Baby eagle 5 is eating using feeding pot 3.
- The following output line tells us that baby eagle 2 sees all feeding
pots being empty and wakes up the mother eagle.
Baby eagle 2 sees all feeding pots are empty and wakes up the mother.
- The following output line tells us that baby eagle 5 finishes eating:
Baby eagle 5 finishes eating.
- The following output line tells us that the mother eagle has started:
Mother eagle started.
- The following output line tells us that the mother eagle takes
a nap:
Mother eagle takes a nap.
- The following output line tells us that baby eagle 2 wakes up the
mother eagle and the mother starts preparing food:
Mother eagle is awoke by baby eagle 2 and starts preparing food.
- The following output line tells us that the mother eagle has finished
food preparation. The number in () is the feeding count. This is
the third feeding.
Mother eagle says "Feeding (3)"
- The following output line tells us that the required number of
feedings have completed and the mother retires. The feeding
game ends here.
Mother eagle retires after serving 8 feedings. Game ends!!!
- Please note the indentation in the output. For easy grading purpose,
use the above output style. Do not
invent your own output, because our grader does not have enough time
to digest your output.
Submission Guidelines
- All programs must be written in ANSI C++.
- Use the submit command to
submit your work. You can submit as many times as you want, but only
the last one will be graded. A makefile without visual
is required. Name your executable
prog2.
- I will use the following approach to compile and test your
programs:
make <-- make your program
prog2 m n t <-- test your program
I may repeat the above procedure several times with different command
line arguments to see if your program performs correctly.
- Your implementation should fulfill the program specification
as stated. Any deviation from the specification will cause you to
receive zero point.
- You should aim for maximum parallelism. That is, implement your
solution as stated and make sure all required threads will execute
simultaneously. Without doing so, you risk
very low grade.
- No late submission will be graded.
- My rule of grading is deduction based. I assume you always
receive 100%. If you missed something, some points will be
taken off based on the following rules.
Read these rules carefully.
Otherwise, you could receive low or very low grade.
Click here to see how your
program will be graded.
- Your programs must contain enough comments.
Programs without comments or with insufficient
comments will cost you 30%.
- For each program, the first piece should be a program
header to identify yourself like this:
// -----------------------------------------------------------
// NAME : John Smith User ID: xxxxxxxx
// DUE DATE : mm/dd/yyyy
// PROGRAM ASSIGNMENT #
// FILE NAME : xxxx.yyyy.zzzz (your unix file name)
// PROGRAM PURPOSE :
// A couple of lines describing your program briefly
// -----------------------------------------------------------
For each function in your program, include a simple description
like this:
// -----------------------------------------------------------
// FUNCTION xxyyzz : (function name)
// the purpose of this function
// PARAMETER USAGE :
// a list of all parameters and their meaning
// FUNCTION CALLED :
// a list of functions that are called by this one
// -----------------------------------------------------------
Bad programming style and missing headers will cost you 30%.
- Submit a one-page description of your solution, discussing
the following issues:
- The logic of your program
- Why does your program work?
- The meaning, initial value and the use of each
semaphore. Explain why their initial values and uses
are correct. Justify your claim.
- Convince me that
ready_to_eat(),
finish_eating(),
goto_sleep() and
food_ready()
work properly. More precisely, the following points
have to be addressed properly.
Make
sure you will have a convincing argument for each of
these questions. Note that argument such as
"because a semaphore is used to ....., the
indicated situation cannot happen" will not
be counted as a
convincing.
You should explain why the situation will not happen
through the use of a semaphore or semaphores.
Providing arguments like that will receive low or very
low grade.
To enforce
good and convincing arguments for this exercise, the
maximum deduction assigned to your
README
is increased to 50%.
- At any time, there are no more than m baby eagles
eating.
- A baby eagle must wait when he wants to eat but has no free
feeding pot and/or all free feeding pots are all empty.
- If there is a non-empty feeding pot, a hungry and ready-to-eat
baby eagle can eat.
- No hungry baby eagle will eat using an empty feeding pot.
- At any time, a feeding pot can only be used by one eating baby
eagle.
- Only one baby eagle among all baby eagles who want to eat can
wake up the mother eagle.
- The mother eagle does not run until a baby eagle wakes her up.
- While the mother eagle is preparing food, no baby eagle can wake
up the mother again until the mother goes back to take a nap.
- Before all m feeding pots are filled, no hungry
baby eagle can eat.
- Once the feeding pots are refilled, the mother eagle must allow
baby eagles to eat. Then, she goes back to sleep.
- You must terminate your program gracefully. More precisely,
if t feedings are needed, then your program
cannot terminate right after
the mother eagle refills the feeding pots t times.
Instead, your program must wait until all feeding pots become
empty, even though there may be baby eagles waiting for food.
Name this file README
rather than
readme or
Readme.
Spell check this file; otherwise, you may risk lower grade.
Missing
README costs you 50%,
poorly written README costs
you 50%, and submitting a non-text file costs you 30%.
-
Not-compile programs receive 0 point.
By not-compile, I mean any reason that could cause an
unsuccessful compilation, including missing files, incorrect
filenames, syntax errors in your programs, incorrect makefile
and so on. Double check your files before you submit, since I
will not
change your program to make it work.
-
Compile-but-not-run programs receive no more than 50%.
Compile-but-not-run means you have attempted
to solve the problem to certain extent but you failed to
make it working properly. A meaningless or vague program receives
no credit even though it compiles successfully. Another common
problem is that your makefile could successfully process your
source files (i.e., compiled successfully); but, your
makefile does not generate an executable file with the desired
filename (i.e.,
prog2
in this assignment). If this happens, I will consider your
submission as compile-but-not-run.
-
Programs delivering incorrect result, incomplete result,
or incompatible output receive no more than 70%.
- Each race condition, busy waiting, or
deadlock costs you 10%.
-
All deductions mentioned above are cumulative!
This means that even though you have turned in a correct
program, you could get very low grade. For example, if your
submission does not have the necessary program and function
headings (30% off), does not have enough comments (30% off),
compiles but not runs correctly (30% off), and contains a race
condition, then you will receive
60×(100-30-30-30-10)%=0 points.
-
Programs submitted to wrong class and/or wrong sections
will not be graded.
-
Your submission should include the following files:
- File thread.h
that contains all class definitions of your threads.
- File thread.cpp
contains all class implementations of your threads.
- File thread-support.cpp
contains all supporting functions such as
ready_to_eat(),
finish_eating(),
goto_sleep() and
food_ready().
- File thread-main.cpp
contains the main program.
- File Makefile
is a makefile that compiles the above three files
to an executable file
prog2.
Since we will use Solaris
to grade your programs, your makefile should make
sure all paths are correct. Note also that
without following this file structure your program
is likely to fall into the compile-but-not-run
category, and, as a result, you may get low grade.
So, before submission, check if you have the
proper file structure and correct makefile.
Note that your Makefile
should not activate
the visualization system.
- File README.
-
Always start early, because I will not grant any extension if
your home machine, your phone line or the department machine
crashes in the last minute.
- Since the rules are all clearly stated
above, no leniency will be given. So, if you have anything in doubt,
please ask for clarifications.
-
Click here to see how your
program will be graded.