CS 451 - Spring 2011
Project 2+3 - Air Traffic
Controller Simulator
Helpful Hints
Version 1.2 (see bottom of the page for changelog)
INPUT
- Rate
R: rate at which the aircraft generator generates new
aircraft.
- Average
Landing
Time
ALT: time it takes an aircraft to land. This is the time
the
aircraft will reserve a runway when it lands. Each aircraft determines
its actual LT using the formula: LT = random (0, 2*ALT).
- Average
Take-off
Time
ATT: time it takes an aircraft to take-off. This is the
time
the aircraft will reserve a runway when it takes off. Each
aircraft determines its actual TT using the formula: LT = random (0,
2*ATT).
- Average
Arrival
Time
AAT: This is on average, the time in the future a
newly generated aircraft will arrive at the airport and will need to
land. Each aircraft will determine this time after it becomes active
according to the following formula: Tnow + random (0, 2*AAT). The
aircraft needs to find a slot that starts at least at this time or
later when picking a schedule. Thus, the slot will start at time AAT or
later, and will block the runway for time LT.
- Average
Departure
Time
ADT: This
is on average, the time in the future a newly generated aircraft will
depart from the airport. Each aircraft will
determine this time after it becomes active according to the following
formula: Tnow + random (0, 2*ADT)
- Halting
time
HT: This is the time the simulation will end. You may want to
start with allowing just a few aircraft to debug, but for the final run
you should use at least 1000 aircraft.
- (Wind change rate: I am still considering
this part of the project, I may remove it. You can skip it for now.)
Note that our time unit in this project
is minutes. However, this should make no difference to your program,
you may treat these as just "time units" if you like.
INITIALIZATION
Your program should start by performing
the necessary initialization steps. For example, it should read
all the input parameters, spawn the necessary proceses, create any
resources required for inter-process communication (e.g., shared mem,
mailboxes, sockets). You should figure out a way to convey that
information to the newly created processes. Examples include a reserved
shared memory space or a directory server (a new process) running on a
fixed port on the machine.
Finally, your program should enter an infinite loop serving
events. (This works nicely if the main process becomes the event
handler, but clearly it is not necessary)
PROCESSES
Here is a brief, high-level description
if the processes we would like you to implement.
Process AircraftGenerator
{
receive event;
demultiplex event (e.g.,
using a case statement)
case: generate_aircraft
generate
Tinterval
random
(0,
2*Rate)
fork
aircraft
process;
schedule
an
aircraft
generation
event at time Tnow + Tinterval
case: halt
(note
that
no
more
aircraft need to be generated so
do
not
add
more
generation events)
wait for next event
}
Process Aircraft
{
receive event;
case: new aircraft
read
variables
interval
and
action
Decide
action:
is
aircraft
is landing or taking off
lock schedule; // schedule must
be locked before reading Tnow
Pick AT or DT As described above
in the INPUT section
find
slot
and
register with scheduler
insert
event
in
the
event_queue
case:
arrived
print
arrival
message
and
time
update
global
stats
exit
case: departed
print
departure
message
and
time
update
global
stats
exit
}
Process Event_handler
{
external event_q; //
pointer to the head of the queue
global
Tnow; // variable that holds
the current time
while (1)
{
if
event_q
=
NULL
break;
lock
schedule
// don't advance time while an aircraft is
scheduling itself
new_event
=
next
event
from the head of the queue
Tnew_event
=
time
new_event
is supposed to happen
make
Tnow
=
Tnew_event
deliver new_event to
approriate
process
}
calculate and prinf global
stats (see output section);
exit;
}
Event Handling
Your event handling should include the following operations. These functions MUST lock the event queue
before
inserting/removing an event! You can accomplish this by putting
a lock around the event queue pointer.
- int
insert_event (ev, ts):
this inserts event ev with timestamp ts in the queue. Note that events
in the queue are time sorted, so this function needs to traverse the
queue
in order to put the event at the appropriate place. May return an error if
insertion fails
- event ev
= remove_head(): this removes and returns the event at the head
of the queue and makes event_q point to the next event
- void
dump_evq (): this dumps the contents of the event queue in
sequence
Event Format
The event format should contain at least
the following items:
- Timestamp when the event should occur
- A pointer to the process that should
receive the event
- Any parameters/flags that should also be
delivered to the receiving process
The implementation of the pointer to the
process that should receive an event is your responsibility. Your
program should clearly include a process identifier and a method to
notify the process that an event was received. For example, if you
choose to use sockets the pointer might be the socket the process is
listening on. In that case your process should block reading from that
socket. If you use shared memory you can write the event (or a pointer
to it) at a specific location in the shared block and then wake up the
process.
We ask that you create a common data structure for an event. Thus, all
events will share a type variable, and the contents might change based
on
the
type (in C unions are good for implementing
such data structures). The event structure definition should go in your
header file.
DATA STRUCURES: The Schedule
This is the actual data structure holding
the current schedule. It should be implemented in a way that is
accessible by all processes (shared memory is probably best). You
should provide all the functions or methods needed to access the
schedule, and all the necessary locking mechanisms that need to
accompany it. Examples include:
- slot get_slot (interval):
this will return a free slot from the schedule. You should make sure
all the locking is done appropriately before the slot is returned. The
return structure specifies the actual interval and the runway the slot
was assigned to.
- void
dump_schedule (): this dumps the contents of the schedule. You
should use this after each change in the schedule.
A note
on the schedule structure:
The schedule is a shared data structure that needs to be locked when
accessed. While we could have
a single process controlling access to the data, this is not desirable
because it delays other aircraft. For example, imagine an
aircraft needs a more complex calculation before it can get a slot in
the schedule (we are not doing it now, but it is possible under more
complex conditions). If that aircraft holds the schedule locked for a
long time, it may delay other aircraft from getting scheduled. Thus,
implementing the schedule as a shared structure that only gets locked
when needed is a more robust design.
OUTPUT
While
executing, your program should print a message when events are
scheduled and when they occur. For example:
$ + <event
name>
<timestamp> <originating process
or thread> //event added to the queue
$ - <event
name>
<timestamp> <originating process
or thread> // event removed from the queue
If the event is an aircraft being
scheduled, you may also want to dump the contents of the schedule:
$
RWY: <Ivl, aircraft#, action>, <Ivl, aircraft#, action>, ...
$ RWY: <Ivl, aircraft#, action>,
<Ivl, aircraft#, action>, ...
For example, assuming there are six aircraft in the schedule, three per
runway (A: arrival, D: departure):
$
36L: <0,5, 1, D>, <7,12, 2, D>, <15,20, 3, A>
$ 36R: <0,5, 4, D>, <5,10, 5,
A>, <11,16, 6, D>
At the end of the simulation
your program should print the following simulation statistics:
Total
simulation
time (note this may be different that
specified, since we wait for the event_q to drain)
# of aircraft generated
# of aircraft arrived
# of aircraft departed
Average waiting time for arriving aircraft
Average waiting time for departing
aircraft
Average delay for arriving
aircraft //delay = scheduled - actual time
Average delay for departing aircraft
You
should run your simulation with different combination of aircraft
generation rates and take-off and landing times. The goal is to see
what happens when you make the airport busier. Run your simulation with
at least five combinations of input.
You should also experiment with the simulation running time as follows.
Select a time that seems sufficiently long to you and run the
simulation. Note the results. Now run the simulation again by
increasing the running time by say 10%. If the results change
significantly, then double the simulation time and repeat until you see
very little change. When the results do not change
significantly, you have reached steady
state conditions. Now
you can do a binary search by reducing and increasing the simulation
time appropriately, to determine the point where steady state
conditions begin. This is the time the simulation
needs to warm up. Note that
time in your report. Then do one more run
with simulation time at least 10 times the warm up time.
PROGRAMMING NOTES
My preference is to implement everything
as a separate process. However, as long as you have some
processes, you may implement part of the project as threads. For
example, you may implement aircraft as threads. I would like to see the
event handler, aircraft generator and any other processes you design
into your program implemented as processes.
If you use sockets:
The nice thing about sockets is that you
can run aircraft processes on different machines. If you opt for
socket IPC, you need to have a receiving process on the machine the
event handler runs on to communicate with the aircraft processes. In
this case, you may spawn a thread for each aircraft, whose job is to
relay imformation on behalf of the remote aircraft process. For
example, when an event needs to me delivered to an aircraft process, it
is first delivered to the corresponding thread and then the thread
relays the event to the remote process.
Changelog
4/6/11 - V1.2: Changed pseudocode for
aircraft and event handler - they must lock the schedule
4/5/11 - V1.1: Added AAT and ADT imput
parameters and approriate entries in the aircraft process. Changed
input parameters AT and TT from fixed values to averages (AAT and ATT).
|