None of this is mandatory. It is optional suggestions, especially for those who are having trouble getting started.
Think of the typical case, not the initial case. (Although startup issues are discussed near the end of this document.) For example, don't think of figuring out when all the hosts are first going to transmit when you're starting to work on your program. Think of being in the middle, of having finished processing one event and starting the next. Then after you have dealt with the typical case, figure out an appropriate initialization.
In general, we tend to get a lot of questions about handling particular cases which are not actually special cases. Don't focus on particular strange cases, not at first. Once you've written your code for the typical case, figure out whether or not a given strange situation really is a special case, or if it is already handled by your general code. Often you will find out that it is already handled, and should not be special-cased.
"time" is a C library function, so it is not a good variable name.
I suggest names such as "when" and "now".
Combined names such as "curtime" or "simtime" are also reasonable.
When host communication concludes, the host object has to schedule
another such event. It's not possible to schedule more than one of the
communication
activities in advance because we don't know when the communication will manage
to get through until it does.
So the completion has to cause the next item
to be scheduled, as usual in a simulation. The time at which the next
communication
is scheduled is a certain duration (usually but not always random) after
the completion of the previous one.
The event queue will not empty.
Generally it will contain one pending event for each host.
Unlike in the gas station simulation, I suggest you always queue events, never
attempt to execute them immediately as the gas station program does.
Some people are hesitant to have a separate class for each host communication
type because of the plethora of .h and .cpp files which would result.
This is not a concern! You can put many classes in one .h/.cpp file pair in
C++. I have a pair of files called host.cpp and host.h which
define FOUR classes: a "host" class, and three host subclasses
which are derived from that non-specific-host class.
The total comes to only several dozen lines and they're all quite related
so it's quite reasonable to put this all in one .h/.cpp file pair.
You can use the "quit pseudo-event" strategy to terminate your simulation at
the desired time. There are other possibilities too.
To send a multi-packet message, I suggest re-submitting that host into the
event queue for each packet. Don't attempt to do the multiple packets in a
loop inside one of the class members.
Thus you will need some instance variables to keep track of where you are.
You actually won't need to keep the total message size!
Keep track of the number of bytes left to send.
When it's time to transmit, and the network is clear, and you don't have a
collision, then the number of bytes in the current transmission is either
When the communication completes successfully, don't bother setting the number
of bytes to send to zero; choose your next communication and set all your
instance variables to represent that, including the start time, and resubmit
yourself into the queue.
In the host-pair cases (peers, and client-server pairs), it's probably best to
have just one object representing the pair.
You may need an extra instance variable keeping track of whose turn it is,
but this is far easier than arranging some sort of coordination between the
multiple simulation objects.
Time values in your simulation need to be of type long, not int,
as the minimum maximum value of an int is 32767, which is too small.
The ethernet speed of one byte per microsecond makes byte-times and
microseconds interchangeable, which should simplify some matters.
Your time values (whether absolute time or intervals) should all be kept in
microseconds for simplicity.
If, to take an extreme example, you display no statistical information at
all, then you won't observe any differences between the different delay
strategies. Obviously
you're not going to do this, but it's likely that your initial
statistics-gathering will prove inadequate.
This is fine.
The whole point of the program is to be an experimentation testbed.
So I suggest you
start by storing and displaying something which seems to be a reasonable
amount of data. Once you've completed your program and it seems to work,
you'll inspect the data a bit more closely to determine whether your program
really is working or if it has bugs. If you find that you're not sure,
you might think of other statistical information to include to provide
evidence that your program is working. You can add more record-keeping as
seems advisable, under the circumstances.
Then, you'll start playing with the different types of hosts and the
different delay formulas. There's actually a pretty good chance at this point that
you'll observe that your statistics aren't giving you enough of the story,
even though you've got them at the point where they strongly suggest that
your program is functional. For example, your statistical information may
suggest that a particular delay strategy is better than a particular other
delay strategy
for a particular type of host, but not give you a good idea as to why.
If you start trying to guess why, you will probably come up with other ideas
about other information worth recording, and you can add that to your program.
If the operation of your program really simulates the situation described
in the handout, then it should be a straightforward matter to add these
additional statistics-gathering statements at appropriate places, e.g. to
add something like "statistics::ncollisions++;" in the bit where you're already
dealing with a collision. Etc.
The above experimentation is the last part of the assignment, but since it
may uncover major bugs in your program, I recommend against leaving it for
the last minute.
The atypical case we're talking about here is program startup.
At program startup, you'll have to schedule one event for each host to start
off the event queue.
It may not matter much exactly when they're scheduled for; they'll get sorted
out over time, and your simulation should run for long enough that
slightly-odd initial conditions don't greatly affect the statistics.
You want to schedule something or other for time zero, perhaps
everything. Get things started right away. There's no point starting off the
simulation with a large idle time. Or even a small one.
Make the special cases as unspecial as possible.
Don't special-case things which don't need to be treated specially.
It's probably best to update the number of bytes left to send only upon
successful communication completion, because if you have a collision, you have
to start that packet over.
Statistics gathering
You have to decide what numbers to track and to display at program
termination.
You have to track data for two purposes:
In a sense, the point of the simulation is to write the report.
The beginning of the program
Once you have figured out how your program works in the typical case, you can
think about the unusual cases.
This really should be done after you've already thought out the typical cases!
You don't want the unusual cases to drive the design of your program more than
the typical cases.
I think that this is good general advice about computer programming.
Avoid getting bogged down by details before you've completed the big picture.
[a3 q&a]
[main course page]