branch merge
This commit is contained in:
@@ -81,18 +81,21 @@ see @uref{http://www.nsnam.org/docs/manual.pdf}.
|
||||
* Random variables::
|
||||
* Callbacks::
|
||||
* Attributes::
|
||||
* Object model::
|
||||
* RealTime::
|
||||
* Emulation::
|
||||
* Packets::
|
||||
* Sockets APIs::
|
||||
* Node and Internet Stack::
|
||||
* TCP::
|
||||
* Routing overview::
|
||||
* Troubleshooting
|
||||
* Troubleshooting::
|
||||
@end menu
|
||||
|
||||
@include random.texi
|
||||
@include callbacks.texi
|
||||
@include attributes.texi
|
||||
@include objects.texi
|
||||
@include realtime.texi
|
||||
@include emulation.texi
|
||||
@include packets.texi
|
||||
|
||||
281
doc/manual/objects.texi
Normal file
281
doc/manual/objects.texi
Normal file
@@ -0,0 +1,281 @@
|
||||
@c ========================================================================
|
||||
@c ns-3 Object model
|
||||
@c ========================================================================
|
||||
|
||||
@node Object model
|
||||
@chapter Object model
|
||||
|
||||
@command{ns-3} is fundamentally a C++ object system. Objects can
|
||||
be declared and instantiated as usual, per C++ rules. ns-3 also
|
||||
adds some features to traditional C++ objects, as described below,
|
||||
to provide greater functionality and features. This manual chapter
|
||||
is intended to introduce the reader to the ns-3 object model.
|
||||
|
||||
This section describes the C++ class design for ns-3 objects. In brief,
|
||||
several design patterns in use include classic object-oriented design
|
||||
(polymorphic interfaces and implementations), separation of interface
|
||||
and implementation, the non-virtual public interface design pattern,
|
||||
an object aggregation facility, and reference counting
|
||||
for memory management. Those familiar with component models such
|
||||
as COM or Bonobo will recognize elements of the design in the
|
||||
ns-3 object aggregation model, although
|
||||
the ns-3 design is not strictly in accordance with either.
|
||||
|
||||
@node Object-oriented behavior
|
||||
@section Object-oriented behavior
|
||||
|
||||
C++ objects, in general, provide common object-oriented capabilities
|
||||
(abstraction, encapsulation, inheritance, and polymorphism) that are part
|
||||
of classic object-oriented design. ns-3 objects make use of these
|
||||
properties; for instance:
|
||||
|
||||
@verbatim
|
||||
class Address
|
||||
{
|
||||
public:
|
||||
Address ();
|
||||
Address (uint8_t type, const uint8_t *buffer, uint8_t len);
|
||||
Address (const Address & address);
|
||||
Address &operator = (const Address &address);
|
||||
...
|
||||
private:
|
||||
uint8_t m_type;
|
||||
uint8_t m_len;
|
||||
...
|
||||
};
|
||||
@end verbatim
|
||||
|
||||
@node Object base classes
|
||||
@section Object base classes
|
||||
|
||||
There are two special base classes used in ns-3. Classes that inherit
|
||||
from these base classes can instantiate objects with special properties.
|
||||
These base classes are:
|
||||
@itemize @bullet
|
||||
@item @code{class Object}
|
||||
@item @code{class ObjectBase}
|
||||
@item @code{class RefCountBase}
|
||||
@end itemize
|
||||
It is not required that ns-3 objects inherit from these class, but
|
||||
those that do get special properties. Classes deriving from
|
||||
@code{class Object} get the following properties.
|
||||
@itemize @bullet
|
||||
@item the ns-3 type and attribute system (see @ref{Attributes})
|
||||
@item a smart-pointer reference counting system (class Ptr)
|
||||
@item an object aggregation system
|
||||
@end itemize
|
||||
|
||||
Classes that derive from @code{class ObjectBase} get the first two
|
||||
properties above, but do not get smart pointers. Classes that
|
||||
derive from @code{class RefCountBase} get only the smart-pointer
|
||||
reference counting system.
|
||||
|
||||
In practice, @code{class Object} is the variant of the three above that
|
||||
the ns-3 developer will most commonly encounter.
|
||||
|
||||
@node Memory management and class Ptr
|
||||
@section Memory management and class Ptr
|
||||
|
||||
Memory management in a C++ program is a complex process, and is
|
||||
often done incorrectly or inconsistently. We have settled on
|
||||
a reference counting design described as follows.
|
||||
|
||||
All objects using reference counting maintain an internal reference
|
||||
count to determine when an object can safely delete itself.
|
||||
Each time that a pointer is obtained to an interface, the object's
|
||||
reference count is incremented by calling @code{Ref()}.
|
||||
It is the obligation of the
|
||||
user of the pointer to explicitly @code{Unref()} the pointer when done.
|
||||
When the reference count falls to zero, the object is deleted.
|
||||
|
||||
@itemize @bullet
|
||||
@item When the client code obtains a pointer from the object itself
|
||||
through object creation, or via QueryInterface, it does not have
|
||||
to increment the reference count.
|
||||
@item When client code obtains a pointer from another source (e.g.,
|
||||
copying a pointer) it must call @code{Ref()} to increment the
|
||||
reference count.
|
||||
@item All users of the object pointer must call @code{Unref()} to
|
||||
release the reference.
|
||||
@end itemize
|
||||
|
||||
The burden for calling @code{Unref()} is somewhat relieved by the
|
||||
use of the reference counting smart pointer class described below.
|
||||
|
||||
Users using a low-level API who wish to explicitly allocate
|
||||
non-reference-counted objects on the heap, using operator new,
|
||||
are responsible for deleting such objects.
|
||||
|
||||
Packet objects are handled differently (without reference
|
||||
counting); their design is described in @ref{Packets}.
|
||||
|
||||
@subsection Reference counting smart pointer (Ptr)
|
||||
|
||||
Calling @code{Ref()} and @code{Unref()} all the time would be cumbersome,
|
||||
so ns-3 provides a smart pointer @code{class Ptr} similar to
|
||||
@code{Boost::intrusive_ptr}.
|
||||
This smart-pointer class assumes that the underlying type provides
|
||||
a pair of Ref and Unref methods that are expected to increment and
|
||||
decrement the internal refcount of the object instance.
|
||||
|
||||
This implementation allows you to manipulate the smart pointer
|
||||
as if it was a normal pointer: you can compare it with zero,
|
||||
compare it against other pointers, assign zero to it, etc.
|
||||
|
||||
It is possible to extract the raw pointer from this
|
||||
smart pointer with the GetPointer and PeekPointer methods.
|
||||
|
||||
If you want to store a newed object into a smart pointer,
|
||||
we recommend you to use the CreateObject template functions
|
||||
to create the object and store it in a smart pointer to avoid
|
||||
memory leaks. These functions are really small convenience
|
||||
functions and their goal is just is save you a small
|
||||
bit of typing.
|
||||
|
||||
@node CreateObject and Create
|
||||
@subsection CreateObject and Create
|
||||
|
||||
Objects in C++ may be statically, dynamically, or automatically created.
|
||||
This holds true for ns-3 also, but some objects in the system
|
||||
have some additional frameworks
|
||||
available. Specifically, reference counted objects are usually
|
||||
allocated using a templated Create or CreateObject method, as follows.
|
||||
|
||||
For objects deriving from @code{class Object}:
|
||||
@verbatim
|
||||
Ptr<WifiNetDevice> device = CreateObject<WifiNetDevice> ();
|
||||
@end verbatim
|
||||
|
||||
For objects deriving from @code{class RefCountBase}, or other
|
||||
objects that support usage of smart pointer (e.g., the ns-3 Packet class),
|
||||
a templated helper function is available and recommended to be used:
|
||||
@verbatim
|
||||
ns3::Ptr<B> b = ns3::Create<B> ();
|
||||
@end verbatim
|
||||
This is simply a wrapper around operator new that correctly handles
|
||||
the reference counting system.
|
||||
|
||||
@node Aggregation
|
||||
@subsection Aggregation
|
||||
|
||||
The ns-3 object aggregation system is motivated in strong part by
|
||||
a recognition that a common use case for ns-2 has been the use of
|
||||
inheritance and polymorphism to extend protocol models. For instance,
|
||||
specialized versions of TCP such as RenoTcpAgent derive from (and override
|
||||
functions from) class TcpAgent.
|
||||
|
||||
However, two problems that have arisen in the ns-2 model are downcasts
|
||||
and ``weak base class.'' Downcasting refers to the procedure of using
|
||||
a base class pointer to an object and querying it at run time to
|
||||
find out type information, used to explicitly cast the pointer to
|
||||
a subclass pointer so that the subclass API can be used.
|
||||
Weak base class refers to the problems that arise when a class
|
||||
cannot be effectively reused (derived from) because it lacks necessary
|
||||
functionality, leading the developer to have to modify the
|
||||
base class and causing proliferation of base class API calls, some
|
||||
of which may not be semantically correct for all subclasses.
|
||||
|
||||
ns-3 is using a version of the query interface design pattern
|
||||
to avoid these problems. This design is based on elements of the
|
||||
@uref{http://en.wikipedia.org/wiki/Component_Object_Model,,Component Object Model}
|
||||
and @uref{http://en.wikipedia.org/wiki/Bonobo_(component_model),,GNOME Bonobo}
|
||||
although full binary-level compatibility of replaceable components
|
||||
is not supported and we have tried to simplify the syntax and impact
|
||||
on model developers.
|
||||
|
||||
@subsubsection Aggregation example
|
||||
|
||||
@code{class Node} is a good example of the use of aggregation in ns-3.
|
||||
Note that there are not derived classes of Nodes in ns-3 such as
|
||||
class InternetNode. Instead, components (protocols) are aggregated to
|
||||
a node. Let's look at how some Ipv4 protocols are added to a node.
|
||||
|
||||
@verbatim
|
||||
static void
|
||||
AddIpv4Stack(Ptr<Node> node)
|
||||
{
|
||||
Ptr<Ipv4L3Protocol> ipv4 = CreateObject<Ipv4L3Protocol> ();
|
||||
ipv4->SetNode (node);
|
||||
node->AggregateObject (ipv4);
|
||||
Ptr<Ipv4Impl> ipv4Impl = CreateObject<Ipv4Impl> ();
|
||||
ipv4Impl->SetIpv4 (ipv4);
|
||||
node->AggregateObject (ipv4Impl);
|
||||
}
|
||||
@end verbatim
|
||||
|
||||
Note that the Ipv4 protocols are created using @code{CreateObject()}.
|
||||
Then, they are aggregated to the node. In this manner, the Node base
|
||||
class does not need to be edited to allow users with a base class Node
|
||||
pointer to access the Ipv4 interface; users may ask the node for a pointer
|
||||
to its Ipv4 interface at runtime. How this is done is seen in the next
|
||||
subsection.
|
||||
|
||||
@subsubsection GetObject example
|
||||
GetObject is a type-safe way to achieve a safe downcasting
|
||||
and to allow interfaces to be found on an object.
|
||||
|
||||
Consider a node pointer @code{m_node} that points to a Node object
|
||||
with an implementation of IPv4. The client code wishes to configure
|
||||
a default route. To do so, it must access an object within
|
||||
the node that has an interface to the IP forwarding configuration.
|
||||
It performs the following:
|
||||
@verbatim
|
||||
Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
|
||||
@end verbatim
|
||||
|
||||
If the node in fact does not have an Ipv4 object aggregated to it, then
|
||||
the method will return null. Therefore, it is good practice to check
|
||||
the return value from such a function call. If successful, the user can
|
||||
now use the Ptr to the Ipv4 object that was previously aggregated to
|
||||
the node.
|
||||
|
||||
@subsubsection Summary
|
||||
To summarize, two benefits that we expect to leverage from this are as follows:
|
||||
@itemize @bullet
|
||||
@item @strong{Encapsulation:} By separating interface from implementation,
|
||||
it permits
|
||||
implementors to replace elements of the protocol stack while remaining
|
||||
compliant with client code that supports the same interface. For
|
||||
example, one type of node may include native ns-3 models of protocols,
|
||||
while another may be a port of a Linux stack, and both may be accessed
|
||||
by the same base class node pointer.
|
||||
@item @strong{Aggregation:} AggregateObject allows for aggregation of
|
||||
objects at
|
||||
run time. For instance, an existing Node object may have an ``Energy Model''
|
||||
object aggregated to it at run time (without modifying
|
||||
and recompiling the node class). An existing model (such as a wireless
|
||||
net device) can then later "GetObject" for the energy model and act
|
||||
appropriately if the interface has been either built in to the underlying
|
||||
Node object or aggregated to it at run time.
|
||||
@end itemize
|
||||
|
||||
We hope that this mode of programming will require much less
|
||||
need for developers to modify the @code base classes or libraries.
|
||||
|
||||
@node Downcasting
|
||||
@section Downcasting
|
||||
|
||||
A question that has arisen several times is, "If I have a base class
|
||||
pointer (Ptr) to an object and I want the derived class pointer, should
|
||||
I downcast (via C++ dynamic cast) to get the derived pointer, or should
|
||||
I use the object aggregation system to @code{GetObject<> ()} to find
|
||||
a Ptr to the interface to the subclass API?"
|
||||
|
||||
The answer to this is that in many situations, both techniques will work.
|
||||
ns-3 provides a templated function for making the syntax of Object
|
||||
dynamic casting much more user friendly:
|
||||
@verbatim
|
||||
template <typename T1, typename T2>
|
||||
Ptr<T1>
|
||||
DynamicCast (Ptr<T2> const&p)
|
||||
{
|
||||
return Ptr<T1> (dynamic_cast<T1 *> (PeekPointer (p)));
|
||||
}
|
||||
@end verbatim
|
||||
|
||||
DynamicCast works when the programmer has a base type pointer and is
|
||||
testing against a subclass pointer. GetObject works when looking for
|
||||
different objects aggregated, but also works with subclasses, in the same
|
||||
way as DynamicCast. If unsure, the programmer should use GetObject, as it
|
||||
works in all cases. If the programmer knows the class hierarchy of the
|
||||
object under consideration, it is more direct to just use DynamicCast.
|
||||
Reference in New Issue
Block a user