Program organization suggestions

Here is an assortment of advice about the organization of your assignment three program. It doesn't have much of an overall theme; it's just a collection of various bits of advice.

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

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.

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.


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.

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 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.

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.


[
a3 q&a] [main course page]