[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Consider that you have two simulation models A and B, and you wish to have them pass information between them during the simulation. One way that you can do that is that you can make A and B each explicitly knowledgable about the other, so that they can invoke methods on each other.
class A { public: void ReceiveInput ( // parameters ); ... } (in another source file:) class B { public: void ReceiveInput ( // parameters); void DoSomething (void); ... private: A* a_instance; // pointer to an A } void B::DoSomething() { // Tell a_instance that something happened a_instance->ReceiveInput ( // parameters); ... }
This certainly works, but it has the drawback that it introduces a dependency on A and B to know about the other at compile time (this makes it harder to have independent compilation units in the simulator) and is not generalized; if in a later usage scenario, B needs to talk to a completely different C object, the source code for B needs to be changed to add a "c_instance" and so forth. It is easy to see that this is a brute force mechanism of communication that can lead to programming cruft in the models.
This is not to say that objects should not know about one another if there is a hard dependency between them, but that often the model can be made more flexible if its interactions are less constrained at compile time.
This is not an abstract problem for network simulation research, but rather it has been a source of problems in previous simulators, when researchers want to extend or modify the system to do different things (as they are apt to do in research). Consider, for example, a user who wants to add an IPsec security protocol sublayer between TCP and IP:
------------ ----------- | TCP | | TCP | ------------ ----------- | becomes -> | ----------- ----------- | IP | | IPsec | ----------- ----------- | ----------- | IP | -----------
If the simulator has made assumptions, and hard coded into the code, that IP always talks to a transport protocol above, the user may be forced to hack the system to get the desired interconnections.
An alternative that provides this flexibility is to use a level of indirection that is commonly known in programming as a callback. A callback function is not invoked explicitly by the caller but is rather delegated to another function that receives the callback function's address and can call it.
You may be familiar with function pointers in C or C++; these can be used to implement callbacks. For more information on introductory callbacks, an online reference is: Declaring Function Pointers and Implementing Callbacks and Callback (computer science)- Wikipedia.
The callback API in ns-3
is designed to minimize the overall
coupling between various pieces of of the simulator
by making each module depend on the callback API
itself rather than depend on other modules. It acts as a sort of
third-party to which work is delegated and which forwards this
work to the proper target module. This callback API, being based
on C++ templates,
is type-safe; that is, it performs static type checks to enforce
proper signature compatibility between callers and callees. It
is therefore more type-safe to use than traditional function
pointers, but the syntax may look imposing at first. This section
is designed to walk you through the callback system so that you
can be comfortable using it in ns-3
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] |
This document was generated on July, 20 2008 using texi2html 1.76.