rename ns-unknown.h/cc ns-unknown-manager.h/cc
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Fri, 11 May 2007 18:42:39 +0200
changeset 578 e305018537c9
parent 577 a700b8761829
child 579 7e31a7f75fee
rename ns-unknown.h/cc ns-unknown-manager.h/cc
SConstruct
src/applications/application-list.h
src/core/component-manager.cc
src/core/component-manager.h
src/core/interface.cc
src/core/interface.h
src/core/ns-unknown-manager.cc
src/core/ns-unknown-manager.h
src/core/ns-unknown.cc
src/core/ns-unknown.h
src/internet-node/i-arp-private.h
src/internet-node/i-ipv4-private.h
src/internet-node/ipv4-l4-demux.h
src/internet-node/l3-demux.h
src/node/i-ipv4.h
src/node/i-udp.h
src/node/node.h
--- a/SConstruct	Fri May 11 10:11:06 2007 +0200
+++ b/SConstruct	Fri May 11 18:42:39 2007 +0200
@@ -25,12 +25,12 @@
     'test.cc',
     'random-variable.cc',
     'rng-stream.cc',
-    'ns-unknown.cc',
+    'interface.cc',
     'uid-manager.cc',
     'default-value.cc',
     'command-line.cc',
     'type-name.cc',
-    'ns-unknown-manager.cc',
+    'component-manager.cc',
     ])
 env = Environment()
 if env['PLATFORM'] == 'posix' or env['PLATFORM'] == 'darwin' or env['PLATFORM'] == 'cygwin':
@@ -58,11 +58,11 @@
     'test.h',
     'random-variable.h',
     'rng-stream.h',
-    'ns-unknown.h',
+    'interface.h',
     'default-value.h',
     'command-line.h',
     'type-name.h',
-    'ns-unknown-manager.h',
+    'component-manager.h',
     ])
 
 def config_core (env, config):
--- a/src/applications/application-list.h	Fri May 11 10:11:06 2007 +0200
+++ b/src/applications/application-list.h	Fri May 11 18:42:39 2007 +0200
@@ -25,7 +25,7 @@
 #define __APPLICATION_LIST_H__
 
 #include "application.h"
-#include "ns3/ns-unknown.h"
+#include "ns3/interface.h"
 #include "ns3/ptr.h"
 #include <vector>
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/component-manager.cc	Fri May 11 18:42:39 2007 +0200
@@ -0,0 +1,243 @@
+/* -*- 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 <mathieu.lacage@sophia.inria.fr>
+ */
+#include "component-manager.h"
+#include "uid-manager.h"
+#include "singleton.h"
+
+namespace ns3 {
+
+// we redefine a UidManager type for the class id singleton below.
+// otherwise, we would have to share the same id singleton instance
+// with the Iids.
+class CidManager : public UidManager
+{};
+
+ClassId::ClassId (std::string name)
+  : m_classId (Singleton<CidManager>::Get ()->Allocate (name))
+{}
+
+ClassId::ClassId (uint32_t classId)
+  : m_classId (classId)
+{}
+
+std::string 
+ClassId::GetName (void)
+{
+  return Singleton<CidManager>::Get ()->LookupByUid (m_classId);
+}
+
+bool operator == (const ClassId &a, const ClassId &b)
+{
+  return a.m_classId == b.m_classId;
+}
+
+Ptr<NsUnknown>
+NsUnknownManager::Create (ClassId classId)
+{
+  Callback<Ptr<NsUnknown> > callback = DoGetCallback<empty,empty,empty,empty,empty> (classId);
+  return callback ();
+}
+
+CallbackBase *
+NsUnknownManager::Lookup (ClassId classId)
+{
+  List *list = Singleton<List>::Get ();
+  for (List::const_iterator i = list->begin (); i != list->end (); i++)
+    {
+      if (i->first == classId)
+	{
+	  return i->second;
+	}
+    }
+  return 0;
+}
+
+ClassId 
+NsUnknownManager::LookupByName (std::string name)
+{
+  return ClassId (Singleton<CidManager>::Get ()->LookupByName (name));
+}
+
+ClassId
+NsUnknownManager::Register (std::string name, CallbackBase *callback)
+{
+  ClassId classId = ClassId (name);
+  List *list = Singleton<List>::Get ();
+  list->push_back (std::make_pair (classId, callback));
+  return classId;
+}
+
+
+} // namespace ns3
+
+#ifdef RUN_SELF_TESTS
+
+#include "test.h"
+#include "interface.h"
+
+namespace {
+
+
+class B : public ns3::NsUnknown
+{
+public:
+  static const ns3::Iid iid;
+  B ();
+};
+
+const ns3::Iid B::iid ("IB");
+
+B::B ()
+  : NsUnknown (B::iid)
+{}
+
+
+class A : public ns3::NsUnknown
+{
+public:
+  static const ns3::ClassId cidZero;
+  static const ns3::ClassId cidOneBool;
+  static const ns3::ClassId cidOneUi32;
+  static const ns3::Iid iid;
+
+  A ();
+  A (bool);
+  A (uint32_t);
+
+  bool m_zeroInvoked;
+  bool m_oneBoolInvoked;
+  bool m_oneUi32Invoked;
+
+  bool m_bool;
+  int m_ui32;
+};
+
+const ns3::ClassId A::cidZero = ns3::NsUnknownManager::RegisterConstructor <A> ("A");
+const ns3::ClassId A::cidOneBool = ns3::NsUnknownManager::RegisterConstructor <A,bool> ("ABool");
+const ns3::ClassId A::cidOneUi32 = ns3::NsUnknownManager::RegisterConstructor <A,uint32_t> ("AUi32");
+const ns3::Iid A::iid ("IA");
+
+A::A ()
+  : NsUnknown (A::iid),
+    m_zeroInvoked (true),
+    m_oneBoolInvoked (false),
+    m_oneUi32Invoked (false)
+{
+  ns3::Ptr<B> b = ns3::MakeNewObject<B> ();
+  AddInterface (b);
+}
+
+A::A (bool bo)
+  : NsUnknown (A::iid),
+    m_zeroInvoked (false),
+    m_oneBoolInvoked (true),
+    m_oneUi32Invoked (false),
+    m_bool (bo)
+{
+  ns3::Ptr<B> b = ns3::MakeNewObject<B> ();
+  AddInterface (b);
+}
+
+A::A (uint32_t i)
+  : NsUnknown (A::iid),
+    m_zeroInvoked (false),
+    m_oneBoolInvoked (false),
+    m_oneUi32Invoked (true),
+    m_ui32 (i)
+{
+  ns3::Ptr<B> b = ns3::MakeNewObject<B> ();
+  AddInterface (b);
+}
+
+}
+
+namespace ns3 {
+
+class NsUnknownManagerTest : public Test
+{
+public:
+  NsUnknownManagerTest ();
+  virtual bool RunTests (void);
+};
+
+NsUnknownManagerTest::NsUnknownManagerTest ()
+  : Test ("NsUnknownManager")
+{}
+bool 
+NsUnknownManagerTest::RunTests (void)
+{
+  bool ok = true;
+
+  Ptr<A> a = 0;
+  a = NsUnknownManager::Create<A> (A::cidZero, A::iid);
+  if (a == 0 ||
+      !a->m_zeroInvoked)
+    {
+      ok = false;
+    }
+
+  a = NsUnknownManager::Create<A,bool> (A::cidOneBool, A::iid, true);
+  if (a == 0 ||
+      !a->m_oneBoolInvoked ||
+      !a->m_bool)
+    {
+      ok = false;
+    }
+
+  a = NsUnknownManager::Create<A,bool> (A::cidOneBool, A::iid, false);
+  if (a == 0 ||
+      !a->m_oneBoolInvoked ||
+      a->m_bool)
+    {
+      ok = false;
+    }
+
+  a = NsUnknownManager::Create<A,uint32_t> (A::cidOneUi32, A::iid, 10);
+  if (a == 0 ||
+      !a->m_oneUi32Invoked ||
+      a->m_ui32 != 10)
+    {
+      ok = false;
+    }
+
+  a = NsUnknownManager::Create<A> (A::cidOneUi32, A::iid, (uint32_t)10);
+  if (a == 0 ||
+      !a->m_oneUi32Invoked ||
+      a->m_ui32 != 10)
+    {
+      ok = false;
+    }
+
+  Ptr<B> b = NsUnknownManager::Create<B,uint32_t> (A::cidOneUi32, B::iid, 10);
+  if (b == 0)
+    {
+      ok = false;
+    }
+
+  return ok;
+}
+
+
+static NsUnknownManagerTest g_unknownManagerTest;
+
+} // namespace ns3
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/component-manager.h	Fri May 11 18:42:39 2007 +0200
@@ -0,0 +1,279 @@
+/* -*- 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 <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef NS_UNKNOWN_MANAGER_H
+#define NS_UNKNOWN_MANAGER_H
+
+#include <string>
+#include <vector>
+#include <stdint.h>
+#include "callback.h"
+#include "interface.h"
+#include "fatal-error.h"
+#include "ptr.h"
+
+namespace ns3 {
+
+/**
+ * \brief Unique Identifier for class constructors.
+ *
+ * Instances of this type must be allocated through
+ * the ns3::Ns3UnknownManager::RegisterConstructor methods
+ */
+class ClassId
+{
+public:
+  /**
+   * \returns the symbolic name associated to this class id
+   *
+   * This name is the name which was associated to this class id
+   * by the ns3::Ns3UnknownManager::RegisterConstructor methods.
+   * This name is also the name which is expected to be input
+   * to ns3::UnknownManager::LookupByName.
+   */
+  std::string GetName (void);
+private:
+  ClassId (std::string name);
+  ClassId (uint32_t classId);
+  friend class NsUnknownManager;
+  friend bool operator == (const ClassId &a, const ClassId &b);
+  uint32_t m_classId;
+};
+
+/**
+ * \brief Create any NsUnknown
+ *
+ * This class keeps track of a set of ClassId, each
+ * of which uniquely identifies the constructor of an
+ * object which derives from the NsUnknown base class.
+ * This class can also create an instance of any of
+ * the objects tracked through any of their tracked
+ * constructor/ClassId.
+ */
+class NsUnknownManager
+{
+public:
+  /**
+   * \param name the symbolic name to lookup
+   * \returns the ClassId associated to the input name.
+   */
+  static ClassId LookupByName (std::string name);
+
+  /**
+   * \param classId class id of the constructor to invoke.
+   * \return a pointer to the instance created.
+   *
+   * Create an instance of the object identified by its
+   * ClassId. This method invokes the default constructor.
+   */
+  static Ptr<NsUnknown> Create (ClassId classId);
+
+  /**
+   * \param classId class id of the constructor to invoke.
+   * \param a1 argument to pass to the constructor.
+   * \return a pointer to the instance created.
+   * \overload Create (ClassId)
+   *
+   * Create an instance of the object identified by its
+   * ClassId.
+   */
+  template <typename T1>
+  static Ptr<NsUnknown> Create (ClassId classId, T1 a1);
+
+  /**
+   * \param classId class id of the constructor to invoke.
+   * \param a1 first argument to pass to the constructor.
+   * \param a2 second argument to pass to the constructor.
+   * \return a pointer to the instance created.
+   * \overload Create (ClassId)
+   *
+   * Create an instance of the object identified by its
+   * ClassId.
+   */
+  template <typename T1, typename T2>
+  static Ptr<NsUnknown> Create (ClassId classId, T1 a1, T2 a2);
+
+  /**
+   * \param classId class id of the constructor to invoke.
+   * \param iid interface id to query for
+   * \return a pointer to the instance created.
+   * \overload Create (ClassId)
+   *
+   * Create an instance of the object identified by its
+   * ClassId, call QueryInterface on it, and return the 
+   * result.
+   */
+  template <typename T>
+  static Ptr<T> Create (ClassId classId, Iid iid);
+
+  template <typename T, typename T1>
+  static Ptr<T> Create (ClassId classId, Iid iid, T1 a1);
+
+  template <typename T, typename T1, typename T2>
+  static Ptr<T> Create (ClassId classId, Iid iid, T1 a1, T2 a2);
+
+  /**
+   * \param name the symbolic name to associate to this
+   *        constructor
+   * \returns a ClassId which uniquely identifies this constructor.
+   */
+  template <typename T>
+  static ClassId RegisterConstructor (std::string name)
+  {
+    static Callback<Ptr<NsUnknown> > callback = 
+      MakeCallback (&NsUnknownManager::MakeObjectZero<T>);
+    return NsUnknownManager::Register (name, &callback);
+  }
+
+  /**
+   * \param name the symbolic name to associate to this
+   *        constructor
+   * \returns a ClassId which uniquely identifies this constructor.
+   * \overload ClassId RegisterConstructor (std::string)
+   */
+  template <typename T, typename T1>
+  static ClassId RegisterConstructor (std::string name)
+  {
+    static Callback<Ptr<NsUnknown> ,T1> callback = MakeCallback (&NsUnknownManager::MakeObjectOne<T,T1>);
+    return NsUnknownManager::Register (name, &callback);
+  }
+
+  /**
+   * \param name the symbolic name to associate to this
+   *        constructor
+   * \returns a ClassId which uniquely identifies this constructor.
+   * \overload ClassId RegisterConstructor (std::string)
+   */
+  template <typename T, typename T1, typename T2>
+  static ClassId RegisterConstructor (std::string name)
+  {
+    static Callback<Ptr<NsUnknown>,T1,T2> callback = MakeCallback (&NsUnknownManager::MakeObjectTwo<T,T1,T2>);
+    return NsUnknownManager::Register (name, &callback);
+  }
+private:
+  static ClassId Register (std::string name, CallbackBase *callback);
+
+  template <typename T1, typename T2,
+            typename T3, typename T4,
+            typename T5>
+  static Callback<Ptr<NsUnknown>,T1,T2,T3,T4,T5> DoGetCallback (ClassId classId);
+
+  template <typename T>
+  static Ptr<NsUnknown> MakeObjectZero (void);
+
+  template <typename T, typename T1>
+  static Ptr<NsUnknown> MakeObjectOne (T1 a1);
+
+  template <typename T, typename T1, typename T2>
+  static Ptr<NsUnknown> MakeObjectTwo (T1 a1, T2 a2);
+
+  typedef std::vector<std::pair<ClassId, CallbackBase *> > List;
+  static List *GetList (void);
+  static CallbackBase *Lookup (ClassId classId);
+};
+
+} // namespace ns3 
+
+
+namespace ns3 {
+
+template <typename T1, typename T2,
+          typename T3, typename T4,
+          typename T5>
+Callback<Ptr<NsUnknown>,T1,T2,T3,T4,T5>
+NsUnknownManager::DoGetCallback (ClassId classId)
+{
+  CallbackBase *callback = Lookup (classId);
+  if (callback == 0)
+    {
+      NS_FATAL_ERROR ("Invalid Class Id.");
+    }
+  Callback<Ptr<NsUnknown>, T1,T2,T3,T4,T5> reference;
+  reference.Assign (*callback);
+  return reference;
+}
+
+
+template <typename T1>
+Ptr<NsUnknown>
+NsUnknownManager::Create (ClassId classId, T1 a1)
+{
+  Callback<Ptr<NsUnknown>, T1> callback = DoGetCallback<T1,empty,empty,empty,empty> (classId);
+  return callback (a1);
+}
+
+template <typename T1, typename T2>
+Ptr<NsUnknown> 
+NsUnknownManager::Create (ClassId classId, T1 a1, T2 a2)
+{
+  Callback<Ptr<NsUnknown> , T1,T2> callback = DoGetCallback<T1,T2,empty,empty,empty> (classId);
+  return callback (a1, a2);
+}
+
+template <typename T>
+Ptr<T>
+NsUnknownManager::Create (ClassId classId, Iid iid)
+{
+  Ptr<NsUnknown> obj = Create (classId);
+  Ptr<T> i = obj->QueryInterface<T> (iid);
+  return i;
+}
+
+template <typename T, typename T1>
+Ptr<T>
+NsUnknownManager::Create (ClassId classId, Iid iid, T1 a1)
+{
+  Ptr<NsUnknown> obj = Create (classId, a1);
+  Ptr<T> i = obj->QueryInterface<T> (iid);
+  return i;
+}
+
+template <typename T, typename T1, typename T2>
+Ptr<T>
+NsUnknownManager::Create (ClassId classId, Iid iid, T1 a1, T2 a2)
+{
+  Ptr<NsUnknown> obj = Create (classId, a1, a2);
+  Ptr<T> i = obj->QueryInterface<T> (iid);
+  return i;
+}
+
+
+template <typename T>
+Ptr<NsUnknown> 
+NsUnknownManager::MakeObjectZero (void)
+{
+  return MakeNewObject<T> ();
+}
+template <typename T, typename T1>
+Ptr<NsUnknown> 
+NsUnknownManager::MakeObjectOne (T1 a1)
+{
+  return MakeNewObject<T> (a1);
+}
+template <typename T, typename T1, typename T2>
+Ptr<NsUnknown> 
+NsUnknownManager::MakeObjectTwo (T1 a1, T2 a2)
+{
+  return MakeNewObject<T> (a1, a2);
+}
+
+} // namespace ns3
+
+#endif /* NS_UNKNOWN_MANAGER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/interface.cc	Fri May 11 18:42:39 2007 +0200
@@ -0,0 +1,386 @@
+/* -*- 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 <mathieu.lacage@sophia.inria.fr>
+ */
+#include "interface.h"
+#include "singleton.h"
+#include "uid-manager.h"
+#include <string>
+#include <list>
+#include <stdint.h>
+#include "assert.h"
+#include "debug.h"
+
+NS_DEBUG_COMPONENT_DEFINE ("NsUnknown");
+
+namespace ns3 {
+
+class IidManager : public UidManager
+{};
+
+Iid::Iid (std::string name)
+  : m_iid (Singleton<IidManager>::Get ()->Allocate (name))
+{}
+
+bool operator == (const Iid &a, const Iid &b)
+{
+  return a.m_iid == b.m_iid;
+}
+
+
+class NsUnknownImpl
+{
+public:
+  NsUnknownImpl (Iid iid, NsUnknown *interface);
+  ~NsUnknownImpl ();
+  void Ref (void);
+  void RefAll (NsUnknownImpl *other);
+  void Unref (void);
+  void UnrefAll (void);
+  NsUnknown *PeekQueryInterface (Iid iid) const;
+  void DoDisposeAll (void);
+  void AddInterface (NsUnknown * interface);
+  void AddSelfInterface (Iid iid, NsUnknown *interface);
+private:
+  typedef std::list<std::pair<Iid,NsUnknown *> > List;
+  uint32_t m_ref;
+  List m_list;
+  bool m_disposed;
+};
+
+NsUnknownImpl::NsUnknownImpl (Iid iid, NsUnknown * interface)
+  : m_ref (1),
+    m_disposed (false)
+{
+  NS_DEBUG ("new " << this << " ref=" << m_ref);
+  m_list.push_back (std::make_pair (iid, interface));
+}
+NsUnknownImpl::~NsUnknownImpl ()
+{
+  for (List::const_iterator i = m_list.begin ();
+       i != m_list.end (); i++)
+    {
+      i->second->UnrefInternal ();
+    }
+  m_list.clear ();
+}
+void 
+NsUnknownImpl::Ref (void)
+{
+  m_ref++;
+  NS_DEBUG ("inc " << this << " ref=" << m_ref);
+}
+void 
+NsUnknownImpl::RefAll (NsUnknownImpl *other)
+{
+  m_ref += other->m_ref;
+  NS_DEBUG ("inc all " << this << " o=" << other->m_ref << " ref=" << m_ref);
+}
+void 
+NsUnknownImpl::Unref (void)
+{
+  NS_ASSERT (m_ref > 0);
+  m_ref--;
+  NS_DEBUG ("dec " << this << " ref=" << m_ref);
+  if (m_ref == 0)
+    {
+      delete this;
+    }
+}
+void
+NsUnknownImpl::UnrefAll (void)
+{
+  NS_ASSERT (m_ref > 0);
+  m_ref = 0;
+  delete this;
+  NS_DEBUG ("dec all " << this);
+}
+void
+NsUnknownImpl::DoDisposeAll (void)
+{
+  NS_ASSERT (!m_disposed);
+  for (List::const_iterator i = m_list.begin ();
+       i != m_list.end (); i++)
+    {
+      NsUnknown *interface = i->second;
+      interface->DoDispose ();
+    }
+  m_disposed = true;
+}
+NsUnknown *
+NsUnknownImpl::PeekQueryInterface (Iid iid) const
+{
+  for (List::const_iterator i = m_list.begin ();
+       i != m_list.end (); i++)
+    {
+      if (i->first == iid)
+	{
+	  return i->second;
+	}
+    }
+  return 0;
+}
+void 
+NsUnknownImpl::AddInterface (NsUnknown *interface)
+{
+  for (List::const_iterator i = interface->m_impl->m_list.begin ();
+       i != interface->m_impl->m_list.end (); i++)
+    {
+      // XXX here, we should check that we have only one 
+      // instance of each interface
+      i->second->RefInternal ();
+      m_list.push_back (std::make_pair (i->first, i->second));
+    }
+}
+void 
+NsUnknownImpl::AddSelfInterface (Iid iid, NsUnknown *interface)
+{
+  interface->RefInternal ();
+  m_list.push_back (std::make_pair (iid, interface));
+}
+
+
+NsUnknown::NsUnknown (Iid iid)
+  : m_impl (new NsUnknownImpl (iid, this)),
+    m_ref (1)
+{}
+NsUnknown::~NsUnknown ()
+{
+  m_impl = 0;
+  m_ref = -1;
+}
+void 
+NsUnknown::Ref (void) const
+{
+  m_impl->Ref ();
+}
+void 
+NsUnknown::Unref (void) const
+{
+  m_impl->Unref ();
+}
+
+void 
+NsUnknown::Dispose (void)
+{
+  m_impl->DoDisposeAll ();
+}
+
+void 
+NsUnknown::DoDispose (void)
+{
+  // we do not do anything by default.
+}
+
+void
+NsUnknown::RefInternal (void)
+{
+  m_ref++;
+}
+
+void
+NsUnknown::UnrefInternal (void)
+{
+  NS_ASSERT (m_ref != 0);
+  m_ref--;
+  if (m_ref == 0)
+    {
+      delete this;
+    }
+}
+
+Ptr<NsUnknown>
+NsUnknown::DoQueryInterface (Iid iid) const
+{
+  return m_impl->PeekQueryInterface (iid);
+}
+
+void 
+NsUnknown::AddInterface (Ptr<NsUnknown> interface)
+{
+  NsUnknown *p = PeekPointer (interface);
+  m_impl->AddInterface (p);
+  m_impl->RefAll (p->m_impl);
+  p->m_impl->UnrefAll ();
+  p->m_impl = m_impl;
+}
+
+void
+NsUnknown::AddSelfInterface (Iid iid, Ptr<NsUnknown> interface)
+{
+  m_impl->AddSelfInterface (iid, PeekPointer (interface));
+}
+
+
+}//namespace ns3
+
+#ifdef RUN_SELF_TESTS
+
+#include "test.h"
+
+namespace {
+
+class A : public ns3::NsUnknown
+{
+public:
+  static const ns3::Iid iid;
+  A ()
+    : NsUnknown (A::iid)
+  {}
+};
+class B : public ns3::NsUnknown
+{
+public:
+  static const ns3::Iid iid;
+  B ()
+    : NsUnknown (B::iid)
+  {}
+};
+class BaseA : public ns3::NsUnknown
+{
+public:
+  static const ns3::Iid iid;
+  BaseA ()
+    : NsUnknown (BaseA::iid)
+  {}
+};
+class BaseB : public ns3::NsUnknown
+{
+public:
+  static const ns3::Iid iid;
+  BaseB ()
+    : NsUnknown (BaseB::iid)
+  {}
+};
+class Base : public ns3::NsUnknown
+{
+public:
+  static const ns3::Iid iid;
+  Base ()
+    : NsUnknown (Base::iid)
+  {}
+};
+class Derived : public Base
+{
+public:
+  static const ns3::Iid iid;
+  Derived ()
+  {
+    AddSelfInterface (Derived::iid, this);
+  }
+};
+
+const ns3::Iid A::iid ("A");
+const ns3::Iid B::iid ("B");
+const ns3::Iid BaseA::iid ("BaseA");
+const ns3::Iid BaseB::iid ("BaseB");
+const ns3::Iid Base::iid ("Base");
+const ns3::Iid Derived::iid ("Derived");
+
+}//namespace
+
+
+namespace ns3 {
+
+class InterfaceTest : public Test
+{
+public:
+  InterfaceTest ();
+  virtual bool RunTests (void);
+};
+
+InterfaceTest::InterfaceTest ()
+  : Test ("NsUnknown")
+{}
+bool 
+InterfaceTest::RunTests (void)
+{
+  bool ok = true;
+
+  //DerivedAB *derivedAB;
+
+
+  Ptr<A> a = MakeNewObject<A> ();
+
+  a = MakeNewObject<A> ();
+  Ptr<A> a1 = a->QueryInterface<A> (A::iid);
+  if (a1 == 0 || a1 != a)
+    {
+      ok = false;
+    }
+  a1 = a->QueryInterface<A> (A::iid);
+  if (a1 == 0 || a1 != a)
+    {
+      ok = false;
+    }
+
+  Ptr<B> b = MakeNewObject<B> ();
+  Ptr<B> b1 = b->QueryInterface<B> (B::iid);
+  if (b1 == 0 || b1 != b)
+    {
+      ok = false;
+    }
+  
+  a = MakeNewObject<A> ();
+  a->AddInterface (b);
+  b1 = b->QueryInterface<B> (B::iid);
+  if (b1 == 0 || b1 != b)
+    {
+      ok = false;
+    }
+  a1 = b->QueryInterface<A> (A::iid);
+  if (a1 == 0 || a1 != a)
+    {
+      ok = false;
+    }
+  a1 = a->QueryInterface<A> (A::iid);
+  if (a1 == 0 || a1 != a)
+    {
+      ok = false;
+    }
+  b1 = a->QueryInterface<B> (B::iid);
+  if (b1 == 0 || b1 != b)
+    {
+      ok = false;
+    }
+
+  Ptr<Derived> derived = MakeNewObject<Derived> ();
+  Ptr<Base> base = derived->QueryInterface<Base> (Base::iid);
+  if (base == 0)
+    {
+      ok = false;
+    }
+  Ptr<Derived> derived1 = base->QueryInterface<Derived> (Derived::iid);
+  if (derived1 == 0 || derived1 != derived)
+    {
+      ok = false;
+    }
+
+  // the following cannot work and it is on purpose
+  // delete derived;
+
+  return ok;
+}
+
+
+static InterfaceTest g_interface_test;
+
+}// namespace ns3
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/interface.h	Fri May 11 18:42:39 2007 +0200
@@ -0,0 +1,128 @@
+/* -*- 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 <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef INTERFACE_H
+#define INTERFACE_H
+
+#include <string>
+#include "ptr.h"
+
+namespace ns3 {
+
+class NsUnknownImpl;
+
+class Iid
+{
+public:
+  Iid (std::string name);
+private:
+  friend bool operator == (const Iid &a, const Iid &b);
+  uint32_t m_iid;
+};
+
+/**
+ * \brief COM-like IUnknown
+ *
+ * This class should be used as a base class for every object which
+ * wishes to provide a COM-like QueryInterface API. Multiple 
+ * inheritance where this base class is at the top of the dreaded 
+ * "diamond" shape is not allowed.
+ */
+class NsUnknown
+{
+public:
+  virtual ~NsUnknown ();
+  void Ref (void) const;
+  void Unref (void) const;
+
+  /**
+   * \param iid the NsUnknown id of the requested interface
+   */
+  template <typename T>
+  Ptr<T> QueryInterface (Iid iid) const;
+
+  /**
+   * \param interface another interface
+   * 
+   * Aggregate together the two interfaces. After this call,
+   * the two interface objects are tied together: each of them
+   * will be able to perform QI on each other and their lifetimes
+   * will be found by the same reference count.
+   */
+  void AddInterface (Ptr<NsUnknown> interface);
+
+  void Dispose (void);
+protected:
+  /**
+   * \param iid the Interface Id of the interface defined by a direct subclass
+   * of this base class
+   *
+   * If you are a direct subclass of this class, you _must_ register
+   * the name of your interface with this constructor.
+   */
+  NsUnknown (Iid iid);
+  /**
+   * \param iid the Interface id of the interface
+   * \param a pointer to the interface object
+   *
+   * If you are not a direct subclass of the ns3::NsUnknown base class,
+   * and if you want to register yourself as another accessible interface
+   * (typically, your subclass has added API), you need to call
+   * this method to associate an interface id to your interface.
+   */
+  void AddSelfInterface (Iid iid, Ptr<NsUnknown> interface);
+protected:
+  /**
+   * Subclasses who want to handle the "dispose" event should
+   * override this method. They are also responsible for
+   * "chaining up" to their parent class' DoDispose method
+   * once they have done their own "dispose".
+   */
+  virtual void DoDispose (void);
+private:
+  friend class NsUnknownImpl;
+  NsUnknown ();
+  Ptr<NsUnknown> DoQueryInterface (Iid iid) const;
+  void RefInternal (void);
+  void UnrefInternal (void);
+  NsUnknownImpl *m_impl;
+  uint32_t m_ref;
+};
+
+}//namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+Ptr<T>
+NsUnknown::QueryInterface (Iid iid) const
+{
+  Ptr<NsUnknown> found = DoQueryInterface (iid);
+  if (found != 0)
+    {
+      return Ptr<T> (dynamic_cast<T *> (PeekPointer (found)));
+    }
+  return 0;
+}
+
+
+}//namespace ns3
+
+#endif /* INTERFACE_H */
--- a/src/core/ns-unknown-manager.cc	Fri May 11 10:11:06 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,243 +0,0 @@
-/* -*- 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 <mathieu.lacage@sophia.inria.fr>
- */
-#include "ns-unknown-manager.h"
-#include "uid-manager.h"
-#include "singleton.h"
-
-namespace ns3 {
-
-// we redefine a UidManager type for the class id singleton below.
-// otherwise, we would have to share the same id singleton instance
-// with the Iids.
-class CidManager : public UidManager
-{};
-
-ClassId::ClassId (std::string name)
-  : m_classId (Singleton<CidManager>::Get ()->Allocate (name))
-{}
-
-ClassId::ClassId (uint32_t classId)
-  : m_classId (classId)
-{}
-
-std::string 
-ClassId::GetName (void)
-{
-  return Singleton<CidManager>::Get ()->LookupByUid (m_classId);
-}
-
-bool operator == (const ClassId &a, const ClassId &b)
-{
-  return a.m_classId == b.m_classId;
-}
-
-Ptr<NsUnknown>
-NsUnknownManager::Create (ClassId classId)
-{
-  Callback<Ptr<NsUnknown> > callback = DoGetCallback<empty,empty,empty,empty,empty> (classId);
-  return callback ();
-}
-
-CallbackBase *
-NsUnknownManager::Lookup (ClassId classId)
-{
-  List *list = Singleton<List>::Get ();
-  for (List::const_iterator i = list->begin (); i != list->end (); i++)
-    {
-      if (i->first == classId)
-	{
-	  return i->second;
-	}
-    }
-  return 0;
-}
-
-ClassId 
-NsUnknownManager::LookupByName (std::string name)
-{
-  return ClassId (Singleton<CidManager>::Get ()->LookupByName (name));
-}
-
-ClassId
-NsUnknownManager::Register (std::string name, CallbackBase *callback)
-{
-  ClassId classId = ClassId (name);
-  List *list = Singleton<List>::Get ();
-  list->push_back (std::make_pair (classId, callback));
-  return classId;
-}
-
-
-} // namespace ns3
-
-#ifdef RUN_SELF_TESTS
-
-#include "test.h"
-#include "ns-unknown.h"
-
-namespace {
-
-
-class B : public ns3::NsUnknown
-{
-public:
-  static const ns3::Iid iid;
-  B ();
-};
-
-const ns3::Iid B::iid ("IB");
-
-B::B ()
-  : NsUnknown (B::iid)
-{}
-
-
-class A : public ns3::NsUnknown
-{
-public:
-  static const ns3::ClassId cidZero;
-  static const ns3::ClassId cidOneBool;
-  static const ns3::ClassId cidOneUi32;
-  static const ns3::Iid iid;
-
-  A ();
-  A (bool);
-  A (uint32_t);
-
-  bool m_zeroInvoked;
-  bool m_oneBoolInvoked;
-  bool m_oneUi32Invoked;
-
-  bool m_bool;
-  int m_ui32;
-};
-
-const ns3::ClassId A::cidZero = ns3::NsUnknownManager::RegisterConstructor <A> ("A");
-const ns3::ClassId A::cidOneBool = ns3::NsUnknownManager::RegisterConstructor <A,bool> ("ABool");
-const ns3::ClassId A::cidOneUi32 = ns3::NsUnknownManager::RegisterConstructor <A,uint32_t> ("AUi32");
-const ns3::Iid A::iid ("IA");
-
-A::A ()
-  : NsUnknown (A::iid),
-    m_zeroInvoked (true),
-    m_oneBoolInvoked (false),
-    m_oneUi32Invoked (false)
-{
-  ns3::Ptr<B> b = ns3::MakeNewObject<B> ();
-  AddInterface (b);
-}
-
-A::A (bool bo)
-  : NsUnknown (A::iid),
-    m_zeroInvoked (false),
-    m_oneBoolInvoked (true),
-    m_oneUi32Invoked (false),
-    m_bool (bo)
-{
-  ns3::Ptr<B> b = ns3::MakeNewObject<B> ();
-  AddInterface (b);
-}
-
-A::A (uint32_t i)
-  : NsUnknown (A::iid),
-    m_zeroInvoked (false),
-    m_oneBoolInvoked (false),
-    m_oneUi32Invoked (true),
-    m_ui32 (i)
-{
-  ns3::Ptr<B> b = ns3::MakeNewObject<B> ();
-  AddInterface (b);
-}
-
-}
-
-namespace ns3 {
-
-class NsUnknownManagerTest : public Test
-{
-public:
-  NsUnknownManagerTest ();
-  virtual bool RunTests (void);
-};
-
-NsUnknownManagerTest::NsUnknownManagerTest ()
-  : Test ("NsUnknownManager")
-{}
-bool 
-NsUnknownManagerTest::RunTests (void)
-{
-  bool ok = true;
-
-  Ptr<A> a = 0;
-  a = NsUnknownManager::Create<A> (A::cidZero, A::iid);
-  if (a == 0 ||
-      !a->m_zeroInvoked)
-    {
-      ok = false;
-    }
-
-  a = NsUnknownManager::Create<A,bool> (A::cidOneBool, A::iid, true);
-  if (a == 0 ||
-      !a->m_oneBoolInvoked ||
-      !a->m_bool)
-    {
-      ok = false;
-    }
-
-  a = NsUnknownManager::Create<A,bool> (A::cidOneBool, A::iid, false);
-  if (a == 0 ||
-      !a->m_oneBoolInvoked ||
-      a->m_bool)
-    {
-      ok = false;
-    }
-
-  a = NsUnknownManager::Create<A,uint32_t> (A::cidOneUi32, A::iid, 10);
-  if (a == 0 ||
-      !a->m_oneUi32Invoked ||
-      a->m_ui32 != 10)
-    {
-      ok = false;
-    }
-
-  a = NsUnknownManager::Create<A> (A::cidOneUi32, A::iid, (uint32_t)10);
-  if (a == 0 ||
-      !a->m_oneUi32Invoked ||
-      a->m_ui32 != 10)
-    {
-      ok = false;
-    }
-
-  Ptr<B> b = NsUnknownManager::Create<B,uint32_t> (A::cidOneUi32, B::iid, 10);
-  if (b == 0)
-    {
-      ok = false;
-    }
-
-  return ok;
-}
-
-
-static NsUnknownManagerTest g_unknownManagerTest;
-
-} // namespace ns3
-
-#endif /* RUN_SELF_TESTS */
--- a/src/core/ns-unknown-manager.h	Fri May 11 10:11:06 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,279 +0,0 @@
-/* -*- 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 <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef NS_UNKNOWN_MANAGER_H
-#define NS_UNKNOWN_MANAGER_H
-
-#include <string>
-#include <vector>
-#include <stdint.h>
-#include "callback.h"
-#include "ns-unknown.h"
-#include "fatal-error.h"
-#include "ptr.h"
-
-namespace ns3 {
-
-/**
- * \brief Unique Identifier for class constructors.
- *
- * Instances of this type must be allocated through
- * the ns3::Ns3UnknownManager::RegisterConstructor methods
- */
-class ClassId
-{
-public:
-  /**
-   * \returns the symbolic name associated to this class id
-   *
-   * This name is the name which was associated to this class id
-   * by the ns3::Ns3UnknownManager::RegisterConstructor methods.
-   * This name is also the name which is expected to be input
-   * to ns3::UnknownManager::LookupByName.
-   */
-  std::string GetName (void);
-private:
-  ClassId (std::string name);
-  ClassId (uint32_t classId);
-  friend class NsUnknownManager;
-  friend bool operator == (const ClassId &a, const ClassId &b);
-  uint32_t m_classId;
-};
-
-/**
- * \brief Create any NsUnknown
- *
- * This class keeps track of a set of ClassId, each
- * of which uniquely identifies the constructor of an
- * object which derives from the NsUnknown base class.
- * This class can also create an instance of any of
- * the objects tracked through any of their tracked
- * constructor/ClassId.
- */
-class NsUnknownManager
-{
-public:
-  /**
-   * \param name the symbolic name to lookup
-   * \returns the ClassId associated to the input name.
-   */
-  static ClassId LookupByName (std::string name);
-
-  /**
-   * \param classId class id of the constructor to invoke.
-   * \return a pointer to the instance created.
-   *
-   * Create an instance of the object identified by its
-   * ClassId. This method invokes the default constructor.
-   */
-  static Ptr<NsUnknown> Create (ClassId classId);
-
-  /**
-   * \param classId class id of the constructor to invoke.
-   * \param a1 argument to pass to the constructor.
-   * \return a pointer to the instance created.
-   * \overload Create (ClassId)
-   *
-   * Create an instance of the object identified by its
-   * ClassId.
-   */
-  template <typename T1>
-  static Ptr<NsUnknown> Create (ClassId classId, T1 a1);
-
-  /**
-   * \param classId class id of the constructor to invoke.
-   * \param a1 first argument to pass to the constructor.
-   * \param a2 second argument to pass to the constructor.
-   * \return a pointer to the instance created.
-   * \overload Create (ClassId)
-   *
-   * Create an instance of the object identified by its
-   * ClassId.
-   */
-  template <typename T1, typename T2>
-  static Ptr<NsUnknown> Create (ClassId classId, T1 a1, T2 a2);
-
-  /**
-   * \param classId class id of the constructor to invoke.
-   * \param iid interface id to query for
-   * \return a pointer to the instance created.
-   * \overload Create (ClassId)
-   *
-   * Create an instance of the object identified by its
-   * ClassId, call QueryInterface on it, and return the 
-   * result.
-   */
-  template <typename T>
-  static Ptr<T> Create (ClassId classId, Iid iid);
-
-  template <typename T, typename T1>
-  static Ptr<T> Create (ClassId classId, Iid iid, T1 a1);
-
-  template <typename T, typename T1, typename T2>
-  static Ptr<T> Create (ClassId classId, Iid iid, T1 a1, T2 a2);
-
-  /**
-   * \param name the symbolic name to associate to this
-   *        constructor
-   * \returns a ClassId which uniquely identifies this constructor.
-   */
-  template <typename T>
-  static ClassId RegisterConstructor (std::string name)
-  {
-    static Callback<Ptr<NsUnknown> > callback = 
-      MakeCallback (&NsUnknownManager::MakeObjectZero<T>);
-    return NsUnknownManager::Register (name, &callback);
-  }
-
-  /**
-   * \param name the symbolic name to associate to this
-   *        constructor
-   * \returns a ClassId which uniquely identifies this constructor.
-   * \overload ClassId RegisterConstructor (std::string)
-   */
-  template <typename T, typename T1>
-  static ClassId RegisterConstructor (std::string name)
-  {
-    static Callback<Ptr<NsUnknown> ,T1> callback = MakeCallback (&NsUnknownManager::MakeObjectOne<T,T1>);
-    return NsUnknownManager::Register (name, &callback);
-  }
-
-  /**
-   * \param name the symbolic name to associate to this
-   *        constructor
-   * \returns a ClassId which uniquely identifies this constructor.
-   * \overload ClassId RegisterConstructor (std::string)
-   */
-  template <typename T, typename T1, typename T2>
-  static ClassId RegisterConstructor (std::string name)
-  {
-    static Callback<Ptr<NsUnknown>,T1,T2> callback = MakeCallback (&NsUnknownManager::MakeObjectTwo<T,T1,T2>);
-    return NsUnknownManager::Register (name, &callback);
-  }
-private:
-  static ClassId Register (std::string name, CallbackBase *callback);
-
-  template <typename T1, typename T2,
-            typename T3, typename T4,
-            typename T5>
-  static Callback<Ptr<NsUnknown>,T1,T2,T3,T4,T5> DoGetCallback (ClassId classId);
-
-  template <typename T>
-  static Ptr<NsUnknown> MakeObjectZero (void);
-
-  template <typename T, typename T1>
-  static Ptr<NsUnknown> MakeObjectOne (T1 a1);
-
-  template <typename T, typename T1, typename T2>
-  static Ptr<NsUnknown> MakeObjectTwo (T1 a1, T2 a2);
-
-  typedef std::vector<std::pair<ClassId, CallbackBase *> > List;
-  static List *GetList (void);
-  static CallbackBase *Lookup (ClassId classId);
-};
-
-} // namespace ns3 
-
-
-namespace ns3 {
-
-template <typename T1, typename T2,
-          typename T3, typename T4,
-          typename T5>
-Callback<Ptr<NsUnknown>,T1,T2,T3,T4,T5>
-NsUnknownManager::DoGetCallback (ClassId classId)
-{
-  CallbackBase *callback = Lookup (classId);
-  if (callback == 0)
-    {
-      NS_FATAL_ERROR ("Invalid Class Id.");
-    }
-  Callback<Ptr<NsUnknown>, T1,T2,T3,T4,T5> reference;
-  reference.Assign (*callback);
-  return reference;
-}
-
-
-template <typename T1>
-Ptr<NsUnknown>
-NsUnknownManager::Create (ClassId classId, T1 a1)
-{
-  Callback<Ptr<NsUnknown>, T1> callback = DoGetCallback<T1,empty,empty,empty,empty> (classId);
-  return callback (a1);
-}
-
-template <typename T1, typename T2>
-Ptr<NsUnknown> 
-NsUnknownManager::Create (ClassId classId, T1 a1, T2 a2)
-{
-  Callback<Ptr<NsUnknown> , T1,T2> callback = DoGetCallback<T1,T2,empty,empty,empty> (classId);
-  return callback (a1, a2);
-}
-
-template <typename T>
-Ptr<T>
-NsUnknownManager::Create (ClassId classId, Iid iid)
-{
-  Ptr<NsUnknown> obj = Create (classId);
-  Ptr<T> i = obj->QueryInterface<T> (iid);
-  return i;
-}
-
-template <typename T, typename T1>
-Ptr<T>
-NsUnknownManager::Create (ClassId classId, Iid iid, T1 a1)
-{
-  Ptr<NsUnknown> obj = Create (classId, a1);
-  Ptr<T> i = obj->QueryInterface<T> (iid);
-  return i;
-}
-
-template <typename T, typename T1, typename T2>
-Ptr<T>
-NsUnknownManager::Create (ClassId classId, Iid iid, T1 a1, T2 a2)
-{
-  Ptr<NsUnknown> obj = Create (classId, a1, a2);
-  Ptr<T> i = obj->QueryInterface<T> (iid);
-  return i;
-}
-
-
-template <typename T>
-Ptr<NsUnknown> 
-NsUnknownManager::MakeObjectZero (void)
-{
-  return MakeNewObject<T> ();
-}
-template <typename T, typename T1>
-Ptr<NsUnknown> 
-NsUnknownManager::MakeObjectOne (T1 a1)
-{
-  return MakeNewObject<T> (a1);
-}
-template <typename T, typename T1, typename T2>
-Ptr<NsUnknown> 
-NsUnknownManager::MakeObjectTwo (T1 a1, T2 a2)
-{
-  return MakeNewObject<T> (a1, a2);
-}
-
-} // namespace ns3
-
-#endif /* NS_UNKNOWN_MANAGER_H */
--- a/src/core/ns-unknown.cc	Fri May 11 10:11:06 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,386 +0,0 @@
-/* -*- 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 <mathieu.lacage@sophia.inria.fr>
- */
-#include "ns-unknown.h"
-#include "singleton.h"
-#include "uid-manager.h"
-#include <string>
-#include <list>
-#include <stdint.h>
-#include "assert.h"
-#include "debug.h"
-
-NS_DEBUG_COMPONENT_DEFINE ("NsUnknown");
-
-namespace ns3 {
-
-class IidManager : public UidManager
-{};
-
-Iid::Iid (std::string name)
-  : m_iid (Singleton<IidManager>::Get ()->Allocate (name))
-{}
-
-bool operator == (const Iid &a, const Iid &b)
-{
-  return a.m_iid == b.m_iid;
-}
-
-
-class NsUnknownImpl
-{
-public:
-  NsUnknownImpl (Iid iid, NsUnknown *interface);
-  ~NsUnknownImpl ();
-  void Ref (void);
-  void RefAll (NsUnknownImpl *other);
-  void Unref (void);
-  void UnrefAll (void);
-  NsUnknown *PeekQueryInterface (Iid iid) const;
-  void DoDisposeAll (void);
-  void AddInterface (NsUnknown * interface);
-  void AddSelfInterface (Iid iid, NsUnknown *interface);
-private:
-  typedef std::list<std::pair<Iid,NsUnknown *> > List;
-  uint32_t m_ref;
-  List m_list;
-  bool m_disposed;
-};
-
-NsUnknownImpl::NsUnknownImpl (Iid iid, NsUnknown * interface)
-  : m_ref (1),
-    m_disposed (false)
-{
-  NS_DEBUG ("new " << this << " ref=" << m_ref);
-  m_list.push_back (std::make_pair (iid, interface));
-}
-NsUnknownImpl::~NsUnknownImpl ()
-{
-  for (List::const_iterator i = m_list.begin ();
-       i != m_list.end (); i++)
-    {
-      i->second->UnrefInternal ();
-    }
-  m_list.clear ();
-}
-void 
-NsUnknownImpl::Ref (void)
-{
-  m_ref++;
-  NS_DEBUG ("inc " << this << " ref=" << m_ref);
-}
-void 
-NsUnknownImpl::RefAll (NsUnknownImpl *other)
-{
-  m_ref += other->m_ref;
-  NS_DEBUG ("inc all " << this << " o=" << other->m_ref << " ref=" << m_ref);
-}
-void 
-NsUnknownImpl::Unref (void)
-{
-  NS_ASSERT (m_ref > 0);
-  m_ref--;
-  NS_DEBUG ("dec " << this << " ref=" << m_ref);
-  if (m_ref == 0)
-    {
-      delete this;
-    }
-}
-void
-NsUnknownImpl::UnrefAll (void)
-{
-  NS_ASSERT (m_ref > 0);
-  m_ref = 0;
-  delete this;
-  NS_DEBUG ("dec all " << this);
-}
-void
-NsUnknownImpl::DoDisposeAll (void)
-{
-  NS_ASSERT (!m_disposed);
-  for (List::const_iterator i = m_list.begin ();
-       i != m_list.end (); i++)
-    {
-      NsUnknown *interface = i->second;
-      interface->DoDispose ();
-    }
-  m_disposed = true;
-}
-NsUnknown *
-NsUnknownImpl::PeekQueryInterface (Iid iid) const
-{
-  for (List::const_iterator i = m_list.begin ();
-       i != m_list.end (); i++)
-    {
-      if (i->first == iid)
-	{
-	  return i->second;
-	}
-    }
-  return 0;
-}
-void 
-NsUnknownImpl::AddInterface (NsUnknown *interface)
-{
-  for (List::const_iterator i = interface->m_impl->m_list.begin ();
-       i != interface->m_impl->m_list.end (); i++)
-    {
-      // XXX here, we should check that we have only one 
-      // instance of each interface
-      i->second->RefInternal ();
-      m_list.push_back (std::make_pair (i->first, i->second));
-    }
-}
-void 
-NsUnknownImpl::AddSelfInterface (Iid iid, NsUnknown *interface)
-{
-  interface->RefInternal ();
-  m_list.push_back (std::make_pair (iid, interface));
-}
-
-
-NsUnknown::NsUnknown (Iid iid)
-  : m_impl (new NsUnknownImpl (iid, this)),
-    m_ref (1)
-{}
-NsUnknown::~NsUnknown ()
-{
-  m_impl = 0;
-  m_ref = -1;
-}
-void 
-NsUnknown::Ref (void) const
-{
-  m_impl->Ref ();
-}
-void 
-NsUnknown::Unref (void) const
-{
-  m_impl->Unref ();
-}
-
-void 
-NsUnknown::Dispose (void)
-{
-  m_impl->DoDisposeAll ();
-}
-
-void 
-NsUnknown::DoDispose (void)
-{
-  // we do not do anything by default.
-}
-
-void
-NsUnknown::RefInternal (void)
-{
-  m_ref++;
-}
-
-void
-NsUnknown::UnrefInternal (void)
-{
-  NS_ASSERT (m_ref != 0);
-  m_ref--;
-  if (m_ref == 0)
-    {
-      delete this;
-    }
-}
-
-Ptr<NsUnknown>
-NsUnknown::DoQueryInterface (Iid iid) const
-{
-  return m_impl->PeekQueryInterface (iid);
-}
-
-void 
-NsUnknown::AddInterface (Ptr<NsUnknown> interface)
-{
-  NsUnknown *p = PeekPointer (interface);
-  m_impl->AddInterface (p);
-  m_impl->RefAll (p->m_impl);
-  p->m_impl->UnrefAll ();
-  p->m_impl = m_impl;
-}
-
-void
-NsUnknown::AddSelfInterface (Iid iid, Ptr<NsUnknown> interface)
-{
-  m_impl->AddSelfInterface (iid, PeekPointer (interface));
-}
-
-
-}//namespace ns3
-
-#ifdef RUN_SELF_TESTS
-
-#include "test.h"
-
-namespace {
-
-class A : public ns3::NsUnknown
-{
-public:
-  static const ns3::Iid iid;
-  A ()
-    : NsUnknown (A::iid)
-  {}
-};
-class B : public ns3::NsUnknown
-{
-public:
-  static const ns3::Iid iid;
-  B ()
-    : NsUnknown (B::iid)
-  {}
-};
-class BaseA : public ns3::NsUnknown
-{
-public:
-  static const ns3::Iid iid;
-  BaseA ()
-    : NsUnknown (BaseA::iid)
-  {}
-};
-class BaseB : public ns3::NsUnknown
-{
-public:
-  static const ns3::Iid iid;
-  BaseB ()
-    : NsUnknown (BaseB::iid)
-  {}
-};
-class Base : public ns3::NsUnknown
-{
-public:
-  static const ns3::Iid iid;
-  Base ()
-    : NsUnknown (Base::iid)
-  {}
-};
-class Derived : public Base
-{
-public:
-  static const ns3::Iid iid;
-  Derived ()
-  {
-    AddSelfInterface (Derived::iid, this);
-  }
-};
-
-const ns3::Iid A::iid ("A");
-const ns3::Iid B::iid ("B");
-const ns3::Iid BaseA::iid ("BaseA");
-const ns3::Iid BaseB::iid ("BaseB");
-const ns3::Iid Base::iid ("Base");
-const ns3::Iid Derived::iid ("Derived");
-
-}//namespace
-
-
-namespace ns3 {
-
-class InterfaceTest : public Test
-{
-public:
-  InterfaceTest ();
-  virtual bool RunTests (void);
-};
-
-InterfaceTest::InterfaceTest ()
-  : Test ("NsUnknown")
-{}
-bool 
-InterfaceTest::RunTests (void)
-{
-  bool ok = true;
-
-  //DerivedAB *derivedAB;
-
-
-  Ptr<A> a = MakeNewObject<A> ();
-
-  a = MakeNewObject<A> ();
-  Ptr<A> a1 = a->QueryInterface<A> (A::iid);
-  if (a1 == 0 || a1 != a)
-    {
-      ok = false;
-    }
-  a1 = a->QueryInterface<A> (A::iid);
-  if (a1 == 0 || a1 != a)
-    {
-      ok = false;
-    }
-
-  Ptr<B> b = MakeNewObject<B> ();
-  Ptr<B> b1 = b->QueryInterface<B> (B::iid);
-  if (b1 == 0 || b1 != b)
-    {
-      ok = false;
-    }
-  
-  a = MakeNewObject<A> ();
-  a->AddInterface (b);
-  b1 = b->QueryInterface<B> (B::iid);
-  if (b1 == 0 || b1 != b)
-    {
-      ok = false;
-    }
-  a1 = b->QueryInterface<A> (A::iid);
-  if (a1 == 0 || a1 != a)
-    {
-      ok = false;
-    }
-  a1 = a->QueryInterface<A> (A::iid);
-  if (a1 == 0 || a1 != a)
-    {
-      ok = false;
-    }
-  b1 = a->QueryInterface<B> (B::iid);
-  if (b1 == 0 || b1 != b)
-    {
-      ok = false;
-    }
-
-  Ptr<Derived> derived = MakeNewObject<Derived> ();
-  Ptr<Base> base = derived->QueryInterface<Base> (Base::iid);
-  if (base == 0)
-    {
-      ok = false;
-    }
-  Ptr<Derived> derived1 = base->QueryInterface<Derived> (Derived::iid);
-  if (derived1 == 0 || derived1 != derived)
-    {
-      ok = false;
-    }
-
-  // the following cannot work and it is on purpose
-  // delete derived;
-
-  return ok;
-}
-
-
-static InterfaceTest g_interface_test;
-
-}// namespace ns3
-
-#endif /* RUN_SELF_TESTS */
--- a/src/core/ns-unknown.h	Fri May 11 10:11:06 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/* -*- 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 <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef INTERFACE_H
-#define INTERFACE_H
-
-#include <string>
-#include "ptr.h"
-
-namespace ns3 {
-
-class NsUnknownImpl;
-
-class Iid
-{
-public:
-  Iid (std::string name);
-private:
-  friend bool operator == (const Iid &a, const Iid &b);
-  uint32_t m_iid;
-};
-
-/**
- * \brief COM-like IUnknown
- *
- * This class should be used as a base class for every object which
- * wishes to provide a COM-like QueryInterface API. Multiple 
- * inheritance where this base class is at the top of the dreaded 
- * "diamond" shape is not allowed.
- */
-class NsUnknown
-{
-public:
-  virtual ~NsUnknown ();
-  void Ref (void) const;
-  void Unref (void) const;
-
-  /**
-   * \param iid the NsUnknown id of the requested interface
-   */
-  template <typename T>
-  Ptr<T> QueryInterface (Iid iid) const;
-
-  /**
-   * \param interface another interface
-   * 
-   * Aggregate together the two interfaces. After this call,
-   * the two interface objects are tied together: each of them
-   * will be able to perform QI on each other and their lifetimes
-   * will be found by the same reference count.
-   */
-  void AddInterface (Ptr<NsUnknown> interface);
-
-  void Dispose (void);
-protected:
-  /**
-   * \param iid the Interface Id of the interface defined by a direct subclass
-   * of this base class
-   *
-   * If you are a direct subclass of this class, you _must_ register
-   * the name of your interface with this constructor.
-   */
-  NsUnknown (Iid iid);
-  /**
-   * \param iid the Interface id of the interface
-   * \param a pointer to the interface object
-   *
-   * If you are not a direct subclass of the ns3::NsUnknown base class,
-   * and if you want to register yourself as another accessible interface
-   * (typically, your subclass has added API), you need to call
-   * this method to associate an interface id to your interface.
-   */
-  void AddSelfInterface (Iid iid, Ptr<NsUnknown> interface);
-protected:
-  /**
-   * Subclasses who want to handle the "dispose" event should
-   * override this method. They are also responsible for
-   * "chaining up" to their parent class' DoDispose method
-   * once they have done their own "dispose".
-   */
-  virtual void DoDispose (void);
-private:
-  friend class NsUnknownImpl;
-  NsUnknown ();
-  Ptr<NsUnknown> DoQueryInterface (Iid iid) const;
-  void RefInternal (void);
-  void UnrefInternal (void);
-  NsUnknownImpl *m_impl;
-  uint32_t m_ref;
-};
-
-}//namespace ns3
-
-namespace ns3 {
-
-template <typename T>
-Ptr<T>
-NsUnknown::QueryInterface (Iid iid) const
-{
-  Ptr<NsUnknown> found = DoQueryInterface (iid);
-  if (found != 0)
-    {
-      return Ptr<T> (dynamic_cast<T *> (PeekPointer (found)));
-    }
-  return 0;
-}
-
-
-}//namespace ns3
-
-#endif /* INTERFACE_H */
--- a/src/internet-node/i-arp-private.h	Fri May 11 10:11:06 2007 +0200
+++ b/src/internet-node/i-arp-private.h	Fri May 11 18:42:39 2007 +0200
@@ -21,7 +21,7 @@
 #ifndef I_ARP_PRIVATE_H
 #define I_ARP_PRIVATE_H
 
-#include "ns3/ns-unknown.h"
+#include "ns3/interface.h"
 #include "ns3/ipv4-address.h"
 
 namespace ns3 {
--- a/src/internet-node/i-ipv4-private.h	Fri May 11 10:11:06 2007 +0200
+++ b/src/internet-node/i-ipv4-private.h	Fri May 11 18:42:39 2007 +0200
@@ -21,7 +21,7 @@
 #ifndef I_IPV4_PRIVATE_H
 #define I_IPV4_PRIVATE_H
 
-#include "ns3/ns-unknown.h"
+#include "ns3/interface.h"
 #include "ns3/ipv4-address.h"
 #include "ns3/ptr.h"
 #include <stdint.h>
--- a/src/internet-node/ipv4-l4-demux.h	Fri May 11 10:11:06 2007 +0200
+++ b/src/internet-node/ipv4-l4-demux.h	Fri May 11 18:42:39 2007 +0200
@@ -26,7 +26,7 @@
 #define IPV4_L4_DEMUX_H
 
 #include <list>
-#include "ns3/ns-unknown.h"
+#include "ns3/interface.h"
 #include "ns3/ptr.h"
 
 namespace ns3 {
--- a/src/internet-node/l3-demux.h	Fri May 11 10:11:06 2007 +0200
+++ b/src/internet-node/l3-demux.h	Fri May 11 18:42:39 2007 +0200
@@ -28,7 +28,7 @@
 #define L3_DEMUX_H
 
 #include <map>
-#include "ns3/ns-unknown.h"
+#include "ns3/interface.h"
 #include "ns3/ptr.h"
 
 namespace ns3 {
--- a/src/node/i-ipv4.h	Fri May 11 10:11:06 2007 +0200
+++ b/src/node/i-ipv4.h	Fri May 11 18:42:39 2007 +0200
@@ -23,7 +23,7 @@
 
 #include <stdint.h>
 #include "ns3/ipv4-address.h"
-#include "ns3/ns-unknown.h"
+#include "ns3/interface.h"
 
 namespace ns3 {
 
--- a/src/node/i-udp.h	Fri May 11 10:11:06 2007 +0200
+++ b/src/node/i-udp.h	Fri May 11 18:42:39 2007 +0200
@@ -21,7 +21,7 @@
 #ifndef I_UDP_H
 #define I_UDP_H
 
-#include "ns3/ns-unknown.h"
+#include "ns3/interface.h"
 #include "ns3/ptr.h"
 
 namespace ns3 {
--- a/src/node/node.h	Fri May 11 10:11:06 2007 +0200
+++ b/src/node/node.h	Fri May 11 18:42:39 2007 +0200
@@ -27,7 +27,7 @@
 
 #include <vector>
 
-#include "ns3/ns-unknown.h"
+#include "ns3/interface.h"
 
 namespace ns3 {