Writing Simulations with MiniscSim

How to Write Simulations with MiniscSim

Event-based Simulation

This section refers to the atikokan version of the source.

In this approach, the interface (API) of the appplication to the scheduler is expressed through Events. These events are objects, which are given to the scheduler with the Schedule function. This call specifies the event to schedule, and when to schedule it. The scheduler, at the specified simulation time, dispatches the event, by calling the Event::Happen() function.

This looks pretty simple in C++. You can declare a class FishEat, which is an event, calling the Eatfunction of a Fish object, and then schedule this new kind of event:

class Fish {
...
  void Eat(Worm& w);
};
...
class FishEat: public Event {
public:
  FishEat (Fish * f, Worm& wrm):pFish(f),myWorm(wrm){}
  Happen() { pFish->Eat(myWorm);}
private:
  Fish * pFish;
  Worm& myWorm;
};
...
Worm Dennis; Fish Nemo;
...
FishEat Lunch (&Nemo,Dennis);
S.Schedule (&Lunch,SimTime(1130));

Or, you can simply schedule a function call. Although this is less interesting, seeing that the function can't take any parameters. For some purposes, its still useful, e.g.

void Krasch(){ ... /* bring down system */...)
...
Scheduler Vindoss();
...
Vindoss.Schedule (Krasch,SimTime(1700));
...

How many of these event-based classes do you need ? That depends on how many different functions you want to call, on how many different kinds of objects. Notice that if above you derive different subclasses from Fish, they can use the same FishEat event, provided that Eat is either the same for all of them, or it is a virtual function (which is why the first argument of the FishEat constructor is a pointer, not a reference).

Caveat

The scheduler doesn't help you in managing your event objects, other than making the function calls you want. Used as in the example, the event object data members are set when the constructor is called, and used when the scheduler calls Happen. You can change the values between those times if you want. It can make for interesting, timing dependent behaviour, and that might be just want you want the simulation for. Or, it could be a bug you have a hard time tracking down.

You also have to manage allocation and deallocation of event objects yourself. So if you do something funky, like S.Schedule(new FishEat(&Nemo,Dennis)) you can introduce memory leaks quite conveniently, so be careful.

Entity-based Simulation

Note that this describes the original release. The "atikokan" version is described above.

We will have some number of initial starting points for this interface, to consider some alternative approaches. They have (meaningless) names, so they can be correlated with file releases. Generally speaking, it can help if you read the header files of the code release. Here are hints about how to use the first one:

In a first version, we have Entities. These are persistent things, like an individual fish in a aquarium simulation, or a single computer in a network simulation. Or a trade union in an economic simulation. These occasionally wake up and do something.

To model this, there is a base class Entity, and you derive your own class from Entity, and implement a Entity::Wakeup function. Then, you allocate a Scheduler (or more than one), and schedule waking up the entities with calls to Scheduler::WakeupAt. Call one of the Scheduler::Run methods to start the scheduler, and it will wake up entities at it has been told.


What do the entities do when they wake up? Mostly, that's up to the application, the scheduler doesn't care. However, a useful thing to do is schedule one's next wakeup, with a Scheduler::WakeupAt(this,time) call. Or Scheduler::WakeupIn(...) works similarly.


Entities can wake up other entities, not just themselves.


Anyone can call Entity::Wakeup, not just a scheduler.


An entity can contain a scheduler, but it cannot be one directly. This has not been tested, so your mileage may vary.