rework the Node and NodeList classes to manage reference counts correctly
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Wed, 02 May 2007 13:44:41 +0200
changeset 484 cf7fbb84d74b
parent 483 24c99e8ebaa2
child 485 152927527647
rework the Node and NodeList classes to manage reference counts correctly
SConstruct
examples/simple-p2p.cc
src/node/node-list.cc
src/node/node-list.h
src/node/node.cc
src/node/node.h
--- a/SConstruct	Wed May 02 13:43:41 2007 +0200
+++ b/SConstruct	Wed May 02 13:44:41 2007 +0200
@@ -97,6 +97,7 @@
     'simulator.h',
     'scheduler.h',
     'scheduler-factory.h',
+    'simulation-singleton.h',
     ])
 high_precision_as_double = ARGUMENTS.get('high-precision-as-double', 'n')
 if high_precision_as_double == 'y':
--- a/examples/simple-p2p.cc	Wed May 02 13:43:41 2007 +0200
+++ b/examples/simple-p2p.cc	Wed May 02 13:44:41 2007 +0200
@@ -151,6 +151,11 @@
   n0->GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
   n3->GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.3.1"), 1);
 
+  n0->Unref ();
+  n1->Unref ();
+  n2->Unref ();
+  n3->Unref ();
+
   // Configure tracing of all enqueue, dequeue, and NetDevice receive events
   // Trace output will be sent to the simple-p2p.tr file
 #if 1
@@ -163,16 +168,6 @@
 #endif
 
   Simulator::Run ();
-
-  n0->Dispose ();
-  n1->Dispose ();
-  n2->Dispose ();
-  n3->Dispose ();
-
-  delete n0;
-  delete n1;
-  delete n2;
-  delete n3;
     
   Simulator::Destroy ();
 }
--- a/src/node/node-list.cc	Wed May 02 13:43:41 2007 +0200
+++ b/src/node/node-list.cc	Wed May 02 13:44:41 2007 +0200
@@ -22,62 +22,142 @@
 
 #include "ns3/array-trace-resolver.h"
 #include "ns3/trace-root.h"
+#include "ns3/simulator.h"
+#include "ns3/simulation-singleton.h"
 #include "node-list.h"
 #include "node.h"
 
+namespace {
+static class Initialization 
+{
+public:
+  Initialization ()
+  {
+    ns3::TraceRoot::Register ("nodes", ns3::MakeCallback (&ns3::NodeList::CreateTraceResolver));
+  }
+} g_initialization;
+}
+
 namespace ns3 {
 
-uint32_t NodeList::g_nextId = 0;
+/**
+ * The private node list used by the static-based API
+ */
+class NodeListPriv
+{
+public:
+  NodeListPriv ();
+  ~NodeListPriv ();
+
+  uint32_t Add (Node *node);
+  NodeList::Iterator Begin (void);
+  NodeList::Iterator End (void);
+  TraceResolver *CreateTraceResolver (TraceContext const &context);
+  Node *GetNode (uint32_t n);
+  Node *PeekNode (uint32_t n);
+  uint32_t GetNNodes (void);
+
+private:
+  std::vector<Node *> m_nodes;
+};
+
+NodeListPriv::NodeListPriv ()
+{}
+NodeListPriv::~NodeListPriv ()
+{
+  for (std::vector<Node *>::iterator i = m_nodes.begin ();
+       i != m_nodes.end (); i++)
+    {
+      Node *node = *i;
+      node->Unref ();
+    }
+  m_nodes.erase (m_nodes.begin (), m_nodes.end ());
+}
+
 
-void
+uint32_t
+NodeListPriv::Add (Node *node)
+{
+  uint32_t index = m_nodes.size ();
+  node->Ref ();
+  m_nodes.push_back (node);
+  return index;
+  
+}
+NodeList::Iterator 
+NodeListPriv::Begin (void)
+{
+  return m_nodes.begin ();
+}
+NodeList::Iterator 
+NodeListPriv::End (void)
+{
+  return m_nodes.end ();
+}
+Node *
+NodeListPriv::GetNode (uint32_t n)
+{
+  Node *node = m_nodes[n];
+  node->Ref ();
+  return node;
+}
+uint32_t 
+NodeListPriv::GetNNodes (void)
+{
+  return m_nodes.size ();
+}
+Node *
+NodeListPriv::PeekNode (uint32_t n)
+{
+  return m_nodes[n];
+}
+
+TraceResolver *
+NodeListPriv::CreateTraceResolver (TraceContext const &context)
+{
+  ArrayTraceResolver<Node> *resolver =
+    new ArrayTraceResolver<Node>
+    (context, 
+     MakeCallback (&NodeListPriv::GetNNodes, this),
+     MakeCallback (&NodeListPriv::PeekNode, this));
+  return resolver;
+}
+
+}
+
+/**
+ * The implementation of the public static-based API
+ * which calls into the private implementation through
+ * the simulation singleton.
+ */
+namespace ns3 {
+
+uint32_t
 NodeList::Add (Node *node)
 {
-  GetNodes ()->push_back (node);
-  node->SetId(g_nextId++);
+  return SimulationSingleton<NodeListPriv>::Get ()->Add (node);
 }
 NodeList::Iterator 
 NodeList::Begin (void)
 {
-  return GetNodes ()->begin ();
+  return SimulationSingleton<NodeListPriv>::Get ()->Begin ();
 }
 NodeList::Iterator 
 NodeList::End (void)
 {
-  return GetNodes ()->end ();
+  return SimulationSingleton<NodeListPriv>::Get ()->End ();
 }
-
-std::vector<Node *> *
-NodeList::GetNodes (void)
+TraceResolver *
+NodeList::CreateTraceResolver (TraceContext const &context)
 {
-  static bool firstTime = true;
-  if (firstTime)
-    {
-      TraceRoot::Register ("nodes", MakeCallback (&NodeList::CreateTraceResolver));
-      firstTime = false;
-    }
-  static std::vector<Node *> nodes;
-  return &nodes;
-}
-uint32_t 
-NodeList::GetNNodes (void)
-{
-  return GetNodes ()->size ();
+  return SimulationSingleton<NodeListPriv>::Get ()->CreateTraceResolver (context);
 }
 Node *
 NodeList::GetNode (uint32_t n)
 {
-  return (*GetNodes ())[n];
+  return SimulationSingleton<NodeListPriv>::Get ()->GetNode (n);
 }
 
-TraceResolver *
-NodeList::CreateTraceResolver (TraceContext const &context)
-{
-  ArrayTraceResolver<Node> *resolver =
-    new ArrayTraceResolver<Node>
-    (context, 
-     MakeCallback (&NodeList::GetNNodes),
-     MakeCallback (&NodeList::GetNode));
-  return resolver;
-}
+
 
 }//namespace ns3
--- a/src/node/node-list.h	Wed May 02 13:43:41 2007 +0200
+++ b/src/node/node-list.h	Wed May 02 13:44:41 2007 +0200
@@ -23,13 +23,11 @@
 #define NODE_LIST_H
 
 #include <vector>
-#include <string>
 #include "ns3/array-trace-resolver.h"
 
 namespace ns3 {
 
 class Node;
-class CallbackBase;
 class TraceResolver;
 class TraceContext;
 
@@ -39,18 +37,12 @@
   typedef ArrayTraceResolver<Node>::Index NodeIndex;
   typedef std::vector<Node *>::iterator Iterator;
 
-  static void Add (Node *node);
+  static uint32_t Add (Node *node);
   static Iterator Begin (void);
   static Iterator End (void);
   static TraceResolver *CreateTraceResolver (TraceContext const &context);
 
   static Node *GetNode (uint32_t n);
-
-private:
-  static uint32_t g_nextId;	// becomes Node::m_id
-  static std::vector<Node *> *GetNodes (void);
-  static uint32_t GetNNodes (void);
-  
 };
 
 }//namespace ns3
--- a/src/node/node.cc	Wed May 02 13:43:41 2007 +0200
+++ b/src/node/node.cc	Wed May 02 13:44:41 2007 +0200
@@ -30,13 +30,17 @@
 namespace ns3{
 
 Node::Node()
-  : m_id(0), m_sid(0)
+  : m_id(0), 
+    m_sid(0)
 {
+  m_id = NodeList::Add (this);
 }
 
 Node::Node(uint32_t sid)
-  : m_id(0), m_sid(sid)
+  : m_id(0), 
+    m_sid(sid)
 { 
+  m_id = NodeList::Add (this);
 }
   
 Node::~Node ()
@@ -49,12 +53,6 @@
   return m_id;
 }
 
-void   
-Node::SetId(uint32_t id )
-{
-  m_id = id;
-}
-
 uint32_t 
 Node::GetSystemId (void) const
 {
--- a/src/node/node.h	Wed May 02 13:43:41 2007 +0200
+++ b/src/node/node.h	Wed May 02 13:44:41 2007 +0200
@@ -29,6 +29,7 @@
 #include <list>
 
 #include "ns3/smartset.h"
+#include "ns3/object.h"
 
 namespace ns3 {
 
@@ -47,7 +48,8 @@
 class TraceResolver;
 class NetDevice;
 
-class Node  {
+class Node : public Object
+{
 friend class NodeList;
 friend class SmartSet<Node*>;
 
@@ -71,9 +73,6 @@
 private:
   virtual void DoAddDevice (NetDevice *device) const = 0;
 
-protected:
-  void SetId(uint32_t);            // NodeList::Add() calls this
-
 public:
   // Virtual "Getters" for each capability.
   // These exist to allow owners of a generic Node pointer to get
@@ -90,7 +89,6 @@
   virtual Arp *            GetArp (void) const;
   
 private:
-  static uint32_t       g_nextId;     // Next available ID
   uint32_t    m_id;         // Node id for this node
   uint32_t    m_sid;        // System id for this node
   std::vector<NetDevice *> m_devices;