diff --git a/SConstruct b/SConstruct index 7161fe8a2..57cbe7b12 100644 --- a/SConstruct +++ b/SConstruct @@ -21,6 +21,7 @@ core.add_sources([ 'debug.cc', 'assert.cc', 'ptr.cc', + 'object.cc', 'test.cc', 'random-variable.cc', 'rng-stream.cc', @@ -44,6 +45,7 @@ core.add_inst_headers([ 'reference-list.h', 'callback.h', 'ptr.h', + 'object.h', 'debug.h', 'assert.h', 'fatal-error.h', @@ -66,8 +68,6 @@ def config_core (env, config): return retval core.add_config (config_core) - - # # The Simu module # diff --git a/examples/simple-p2p.cc b/examples/simple-p2p.cc index ea68b6b8c..dc4dbc64d 100644 --- a/examples/simple-p2p.cc +++ b/examples/simple-p2p.cc @@ -201,7 +201,8 @@ PrintRoutingTable (InternetNode *a, std::string name) int main (int argc, char *argv[]) { -#if 0 +#if 1 + DebugComponentEnable("Object"); DebugComponentEnable("Queue"); DebugComponentEnable("DropTailQueue"); DebugComponentEnable("Channel"); @@ -302,4 +303,8 @@ int main (int argc, char *argv[]) // or containers or smart pointers Simulator::Destroy (); + + ch1->Unref (); + ch2->Unref (); + ch3->Unref (); } diff --git a/src/core/object.cc b/src/core/object.cc new file mode 100644 index 000000000..1009b0188 --- /dev/null +++ b/src/core/object.cc @@ -0,0 +1,66 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 INRIA + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ +#include "object.h" +#include "debug.h" + +NS_DEBUG_COMPONENT_DEFINE ("Object"); + +namespace ns3 { + +Object::Object () + : m_count (1) +{ +} + +Object::~Object () +{ +} + +void +Object::Ref (void) +{ + NS_DEBUG("Object::Ref (): this == 0x" << this); + m_count++; + NS_DEBUG("Object::Ref (): m_count bumped to " << m_count); +} + +void +Object::Unref (void) +{ + NS_DEBUG("Object::Unref (): this == 0x" << this); + m_count--; + NS_DEBUG("Object::Ref (): m_count dropped to " << m_count); + + if (m_count == 0) + { + NS_DEBUG("Object::Unref (): delete"); + delete this; + } +} + +bool +Object::IsSingle (void) +{ + NS_DEBUG("Object::IsSingle (): m_count == " << m_count); + return m_count == 1; +} + +}//namespace ns3 diff --git a/src/core/object.h b/src/core/object.h new file mode 100644 index 000000000..a662e6e45 --- /dev/null +++ b/src/core/object.h @@ -0,0 +1,42 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2007 INRIA + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mathieu Lacage + */ +#ifndef OBJECT_H +#define OBJECT_H + +#include + +namespace ns3 { + +class Object +{ +public: + Object (); + virtual ~Object (); + void Ref (void); + void Unref (void); + bool IsSingle (void); +private: + uint32_t m_count; +}; + +}//namespace ns3 + +#endif /* OBJECT_H */ diff --git a/src/devices/p2p/p2p-net-device.cc b/src/devices/p2p/p2p-net-device.cc index cd6d7f235..fb6938d9f 100644 --- a/src/devices/p2p/p2p-net-device.cc +++ b/src/devices/p2p/p2p-net-device.cc @@ -32,13 +32,15 @@ NS_DEBUG_COMPONENT_DEFINE ("PointToPointNetDevice"); namespace ns3 { -PointToPointNetDevice::PointToPointNetDevice(Node* node) +PointToPointNetDevice::PointToPointNetDevice (Node* node) : - NetDevice(node, MacAddress("00:00:00:00:00:00")), - m_txMachineState(READY), - m_bps (DataRate(0xffffffff)), - m_channel(0), - m_queue(0) + NetDevice(node, MacAddress ("00:00:00:00:00:00")), + m_txMachineState (READY), + m_bps (DataRate (0xffffffff)), + m_tInterframeGap (Seconds(0)), + m_channel (0), + m_queue (0), + m_rxTrace () { NS_DEBUG ("PointToPointNetDevice::PointToPointNetDevice (" << node << ")"); @@ -53,6 +55,67 @@ PointToPointNetDevice::PointToPointNetDevice(Node* node) PointToPointNetDevice::~PointToPointNetDevice() { NS_DEBUG ("PointToPointNetDevice::~PointToPointNetDevice ()"); + + if (m_channel) + { + m_channel->Unref (); + m_channel = 0; + } +} + +// +// Copy constructor for PointToPointNetDevice. +// +// We use the underlying NetDevice copy constructor to get the base class +// copied. These just remain as is (e.g. you get the same name, the same +// MAC address). If you need to fix them up, YOU, the copier need to do +// that. +// +// The things we need to be careful of are the channel, the queue and the +// trace callback. If the channel pointer is non-zero, we copy the pointer +// and add a reference. If the queue is non-zero, we copy it using the queue +// assignment operator. We don't mess with the trace -- we just reset it. +// We're assuming that the tracing will be set up after the topology creation +// phase and this won't actually matter. +// +PointToPointNetDevice::PointToPointNetDevice (const PointToPointNetDevice& nd) +: + NetDevice(nd), + m_txMachineState(READY), + m_bps (nd.m_bps), + m_tInterframeGap (nd.m_tInterframeGap), + m_channel(0), + m_queue(0), + m_rxTrace () +{ + NS_DEBUG ("PointToPointNetDevice::PointToPointNetDevice (" << &nd << ")"); + + if (nd.m_channel) + { + m_channel = nd.m_channel; + m_channel->Ref (); + } + + if (nd.m_queue) + { + m_queue = nd.m_queue; + } + +} + +// +// Assignment operator for PointToPointNetDevice. +// +// This uses the non-obvious trick of taking the source net device passed by +// value instead of by reference. This causes the copy constructor to be +// invoked (where the real work is done -- see above). All we have to do +// here is to return the newly constructed net device. +// + PointToPointNetDevice& +PointToPointNetDevice::operator= (const PointToPointNetDevice nd) +{ + NS_DEBUG ("PointToPointNetDevice::operator= (" << &nd << ")"); + return *this; } void @@ -236,7 +299,14 @@ PointToPointNetDevice::Attach (PointToPointChannel* ch) { NS_DEBUG ("PointToPointNetDevice::Attach (" << &ch << ")"); + if (m_channel) + { + m_channel->Unref (); + m_channel = 0; + } + m_channel = ch; + m_channel->Ref (); m_channel->Attach(this); m_bps = m_channel->GetDataRate (); diff --git a/src/devices/p2p/p2p-net-device.h b/src/devices/p2p/p2p-net-device.h index a42ba3946..c276dbf6f 100644 --- a/src/devices/p2p/p2p-net-device.h +++ b/src/devices/p2p/p2p-net-device.h @@ -43,17 +43,16 @@ public: RX, }; - PointToPointNetDevice(Node* node); + PointToPointNetDevice (Node* node); + PointToPointNetDevice (const PointToPointNetDevice& nd); + virtual ~PointToPointNetDevice(); + PointToPointNetDevice& operator= (PointToPointNetDevice nd); + void SetDataRate(DataRate bps); void SetInterframeGap(Time t); -private: - // Don't let the compiler slip in copy and assignment construction - PointToPointNetDevice(const PointToPointNetDevice&); - PointToPointNetDevice&operator=(const PointToPointNetDevice&); - public: bool Attach(PointToPointChannel* ch); void AddQueue(Queue*); diff --git a/src/node/channel.h b/src/node/channel.h index f3f95fa2d..2033fd880 100644 --- a/src/node/channel.h +++ b/src/node/channel.h @@ -24,6 +24,7 @@ #include #include +#include "ns3/object.h" namespace ns3 { @@ -35,12 +36,11 @@ class NetDevice; * A channel is a logical path over which information flows. The path can * be as simple as a short piece of wire, or as complicated as space-time. */ -class Channel +class Channel : public Object { public: Channel (); Channel (std::string name); - virtual ~Channel (); void SetName(std::string); std::string GetName(void); @@ -49,6 +49,7 @@ public: virtual NetDevice *GetDevice (uint32_t i) const = 0; protected: + virtual ~Channel (); std::string m_name; private: