add 'factory' support to InterfaceId
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Wed, 02 Jan 2008 15:54:53 +0100
changeset 2237 7745a8c76396
parent 2236 a3a52c5ca2b4
child 2238 05affd9d0dc1
add 'factory' support to InterfaceId
src/core/object.cc
src/core/object.h
--- a/src/core/object.cc	Wed Jan 02 13:40:37 2008 +0100
+++ b/src/core/object.cc	Wed Jan 02 15:54:53 2008 +0100
@@ -38,13 +38,20 @@
 public:
   uint16_t AllocateUid (std::string name);
   void SetParent (uint16_t uid, uint16_t parent);
+  void AddConstructor (uint16_t uid, ns3::CallbackBase callback, uint32_t nArguments);
   uint16_t GetUid (std::string name) const;
   std::string GetName (uint16_t uid) const;
   uint16_t GetParent (uint16_t uid) const;
+  ns3::CallbackBase GetConstructor (uint16_t uid, uint32_t nArguments);
 private:
+  struct ConstructorInformation {
+    ns3::CallbackBase cb;
+    uint32_t nArguments;
+  };
   struct IidInformation {
     std::string name;
     uint16_t parent;
+    std::vector<struct ConstructorInformation> constructors;
   };
   typedef std::vector<struct IidInformation>::const_iterator Iterator;
 
@@ -89,6 +96,24 @@
   struct IidInformation *information = LookupInformation (uid);
   information->parent = parent;
 }
+void 
+IidManager::AddConstructor (uint16_t uid, ns3::CallbackBase callback, uint32_t nArguments)
+{
+  struct IidInformation *information = LookupInformation (uid);
+  struct ConstructorInformation constructor;
+  constructor.cb = callback;
+  constructor.nArguments = nArguments;
+  for (std::vector<struct ConstructorInformation>::const_iterator i = information->constructors.begin ();
+       i != information->constructors.end (); i++)
+    {
+      if (i->nArguments == nArguments)
+        {
+          NS_FATAL_ERROR ("registered two constructors on the same type with the same number of arguments.");
+          break;
+        }
+    }
+  information->constructors.push_back (constructor);
+}
 
 uint16_t 
 IidManager::GetUid (std::string name) const
@@ -117,6 +142,21 @@
   struct IidInformation *information = LookupInformation (uid);
   return information->parent;
 }
+ns3::CallbackBase 
+IidManager::GetConstructor (uint16_t uid, uint32_t nArguments)
+{
+  struct IidInformation *information = LookupInformation (uid);
+  for (std::vector<struct ConstructorInformation>::const_iterator i = information->constructors.begin ();
+       i != information->constructors.end (); i++)
+    {
+      if (i->nArguments == nArguments)
+        {
+          return i->cb;
+        } 
+    }
+  NS_FATAL_ERROR ("Requested constructor with "<<nArguments<<" arguments not found");
+  return ns3::CallbackBase ();
+}
 
 } // anonymous namespace
 
@@ -191,6 +231,13 @@
  *         The InterfaceId class
  *********************************************************************/
 
+InterfaceId::InterfaceId (std::string name)
+{
+  uint16_t uid = Singleton<IidManager>::Get ()->AllocateUid (name);
+  NS_ASSERT (uid != 0);
+  m_iid = uid;
+}
+
 
 InterfaceId::InterfaceId (uint16_t iid)
   : m_iid (iid)
@@ -205,6 +252,12 @@
   return InterfaceId (uid);
 }
 InterfaceId 
+InterfaceId::SetParent (InterfaceId iid)
+{
+  Singleton<IidManager>::Get ()->SetParent (m_iid, iid.m_iid);
+  return *this;
+}
+InterfaceId 
 InterfaceId::GetParent (void) const
 {
   uint16_t parent = Singleton<IidManager>::Get ()->GetParent (m_iid);
@@ -217,6 +270,29 @@
   return name;
 }
 
+void
+InterfaceId::DoAddConstructor (CallbackBase cb, uint32_t nArguments)
+{
+  Singleton<IidManager>::Get ()->AddConstructor (m_iid, cb, nArguments);
+}
+
+CallbackBase
+InterfaceId::LookupConstructor (uint32_t nArguments)
+{
+  CallbackBase constructor = Singleton<IidManager>::Get ()->GetConstructor (m_iid, nArguments);
+  return constructor;
+}
+
+Ptr<Object> 
+InterfaceId::CreateObject (void)
+{
+  CallbackBase cb = LookupConstructor (0);
+  Callback<Ptr<Object> > realCb;
+  realCb.Assign (cb);
+  Ptr<Object> object = realCb ();
+  return object;
+}
+
 bool operator == (InterfaceId a, InterfaceId b)
 {
   return a.m_iid == b.m_iid;
@@ -486,7 +562,9 @@
 {
 public:
   static ns3::InterfaceId iid (void) {
-    static ns3::InterfaceId iid = ns3::MakeInterfaceId ("BaseA", Object::iid ());
+    static ns3::InterfaceId iid = ns3::InterfaceId ("BaseA")
+      .SetParent (Object::iid ())
+      .AddConstructor<BaseA> ();
     return iid;
   }
   BaseA ()
@@ -509,7 +587,9 @@
 {
 public:
   static ns3::InterfaceId iid (void) {
-    static ns3::InterfaceId iid = ns3::MakeInterfaceId ("DerivedA", BaseA::iid ());
+    static ns3::InterfaceId iid = ns3::InterfaceId ("DerivedA")
+      .SetParent (BaseA::iid ())
+      .AddConstructor<DerivedA,int> ();
     return iid;
   }
   DerivedA (int v)
@@ -534,7 +614,9 @@
 {
 public:
   static ns3::InterfaceId iid (void) {
-    static ns3::InterfaceId iid = ns3::MakeInterfaceId ("BaseB", Object::iid ());
+    static ns3::InterfaceId iid = ns3::InterfaceId ("BaseB")
+      .SetParent (Object::iid ())
+      .AddConstructor<BaseB> ();
     return iid;
   }
   BaseB ()
@@ -557,7 +639,9 @@
 {
 public:
   static ns3::InterfaceId iid (void) {
-    static ns3::InterfaceId iid = ns3::MakeInterfaceId ("DerivedB", BaseB::iid ());
+    static ns3::InterfaceId iid = ns3::InterfaceId ("DerivedB")
+      .SetParent (BaseB::iid ())
+      .AddConstructor<DerivedB,int> ();
     return iid;
   }
   DerivedB (int v)
@@ -739,6 +823,17 @@
   NS_TEST_ASSERT (m_derivedATrace);
   baseB->TraceDisconnect ("/$DerivedA/*", MakeCallback (&ObjectTest::BaseATrace, this));
 
+  // Test the object creation code of InterfaceId
+  Ptr<Object> a = BaseA::iid ().CreateObject ();
+  NS_TEST_ASSERT_EQUAL (a->QueryInterface<BaseA> (), a);
+  NS_TEST_ASSERT_EQUAL (a->QueryInterface<BaseA> (DerivedA::iid ()), 0);
+  NS_TEST_ASSERT_EQUAL (a->QueryInterface<DerivedA> (), 0);
+  a = DerivedA::iid ().CreateObject (10);
+  NS_TEST_ASSERT_EQUAL (a->QueryInterface<BaseA> (), a);
+  NS_TEST_ASSERT_EQUAL (a->QueryInterface<BaseA> (DerivedA::iid ()), a);
+  NS_TEST_ASSERT_UNEQUAL (a->QueryInterface<DerivedA> (), 0);
+
+
   return result;
 }
 
--- a/src/core/object.h	Wed Jan 02 13:40:37 2008 +0100
+++ b/src/core/object.h	Wed Jan 02 15:54:53 2008 +0100
@@ -25,11 +25,14 @@
 #include <string>
 #include "ptr.h"
 #include "trace-resolver.h"
+#include "callback.h"
+#include "empty.h"
 
 namespace ns3 {
 
 class TraceContext;
 class CallbackBase;
+class Object;
 
 /**
  * \brief a unique identifier for an interface.
@@ -65,13 +68,47 @@
    * \returns the name of this interface.
    */
   std::string GetName (void) const;
+
+  InterfaceId (std::string);
+
+  InterfaceId SetParent (InterfaceId iid);
+  template <typename T>
+  InterfaceId AddConstructor (void);
+  template <typename T, typename T1>
+  InterfaceId AddConstructor (void);
+  template <typename T, typename T1, typename T2>
+  InterfaceId AddConstructor (void);
+  template <typename T, typename T1, typename T2, typename T3>
+  InterfaceId AddConstructor (void);
+  template <typename T, typename T1, typename T2, typename T3, typename T4>
+  InterfaceId AddConstructor (void);
+  template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
+  InterfaceId AddConstructor (void);
+
+
+  Ptr<Object> CreateObject (void);
+  template <typename T1>
+  Ptr<Object> CreateObject (T1 a1);
+  template <typename T1, typename T2>
+  Ptr<Object> CreateObject (T1 a1, T2 a2);
+  template <typename T1, typename T2, typename T3>
+  Ptr<Object> CreateObject (T1 a1, T2 a2, T3 a3);
+  template <typename T1, typename T2, typename T3, typename T4>
+  Ptr<Object> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4);
+  template <typename T1, typename T2, typename T3, typename T4, typename T5>
+  Ptr<Object> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
+
   ~InterfaceId ();
 private:
-  InterfaceId (uint16_t iid);
   friend InterfaceId MakeInterfaceId (std::string name, InterfaceId parent);
   friend InterfaceId MakeObjectInterfaceId (void);
   friend bool operator == (InterfaceId a, InterfaceId b);
   friend bool operator != (InterfaceId a, InterfaceId b);
+
+  InterfaceId (uint16_t iid);
+  void DoAddConstructor (CallbackBase callback, uint32_t nArguments);
+  CallbackBase LookupConstructor (uint32_t nArguments);
+  
   uint16_t m_iid;
 };
 
@@ -245,6 +282,139 @@
 
 namespace ns3 {
 
+
+template <typename T>
+InterfaceId 
+InterfaceId::AddConstructor (void)
+{
+  struct Maker {
+    static Ptr<Object> Create (void) {
+      return ns3::CreateObject<T> ();
+    }
+  };
+  CallbackBase cb = MakeCallback (&Maker::Create);
+  DoAddConstructor (cb, 0);
+  return *this;
+}
+template <typename T, typename T1>
+InterfaceId 
+InterfaceId::AddConstructor (void)
+{
+  struct Maker {
+    static Ptr<Object> Create (T1 a1) {
+      return ns3::CreateObject<T> (a1);
+    }
+  };
+  CallbackBase cb = MakeCallback (&Maker::Create);
+  DoAddConstructor (cb, 1);
+  return *this;
+}
+template <typename T, typename T1, typename T2>
+InterfaceId 
+InterfaceId::AddConstructor (void)
+{
+  struct Maker {
+    static Ptr<Object> Create (T1 a1, T2 a2) {
+      return ns3::CreateObject<T> (a1, a2);
+    }
+  };
+  CallbackBase cb = MakeCallback (&Maker::Create);
+  DoAddConstructor (cb, 2);
+  return *this;
+}
+template <typename T, typename T1, typename T2, typename T3>
+InterfaceId 
+InterfaceId::AddConstructor (void)
+{
+  struct Maker {
+    static Ptr<Object> Create (T1 a1, T2 a2, T3 a3) {
+      return ns3::CreateObject<T> (a1, a2, a3);
+    }
+  };
+  CallbackBase cb = MakeCallback (&Maker::Create);
+  DoAddConstructor (cb, 3);
+  return *this;
+}
+template <typename T, typename T1, typename T2, typename T3, typename T4>
+InterfaceId 
+InterfaceId::AddConstructor (void)
+{
+  struct Maker {
+    static Ptr<Object> Create (T1 a1, T2 a2, T3 a3, T4 a4) {
+      return ns3::CreateObject<T> (a1, a2, a3, a4);
+    }
+  };
+  CallbackBase cb = MakeCallback (&Maker::Create);
+  DoAddConstructor (cb, 4);
+  return *this;
+}
+template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
+InterfaceId 
+InterfaceId::AddConstructor (void)
+{
+  struct Maker {
+    static Ptr<Object> Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) {
+      return ns3::CreateObject<T> (a1, a2, a3, a4, a5);
+    }
+  };
+  CallbackBase cb = MakeCallback (&Maker::Create);
+  DoAddConstructor (cb, 5);
+  return *this;
+}
+
+template <typename T1>
+Ptr<Object> 
+InterfaceId::CreateObject (T1 a1)
+{
+  CallbackBase cb = LookupConstructor (1);
+  Callback<Ptr<Object>,T1> realCb;
+  realCb.Assign (cb);
+  Ptr<Object> object = realCb (a1);
+  return object;
+}
+template <typename T1, typename T2>
+Ptr<Object> 
+InterfaceId::CreateObject (T1 a1, T2 a2)
+{
+  CallbackBase cb = LookupConstructor (2);
+  Callback<Ptr<Object>,T1,T2> realCb;
+  realCb.Assign (cb);
+  Ptr<Object> object = realCb (a1,a2);
+  return object;
+}
+template <typename T1, typename T2, typename T3>
+Ptr<Object> 
+InterfaceId::CreateObject (T1 a1, T2 a2, T3 a3)
+{
+  CallbackBase cb = LookupConstructor (3);
+  Callback<Ptr<Object>,T1,T2,T3> realCb;
+  realCb.Assign (cb);
+  Ptr<Object> object = realCb (a1,a2,a3);
+  return object;
+}
+template <typename T1, typename T2, typename T3, typename T4>
+Ptr<Object> 
+InterfaceId::CreateObject (T1 a1, T2 a2, T3 a3, T4 a4)
+{
+  CallbackBase cb = LookupConstructor (4);
+  Callback<Ptr<Object>,T1,T2,T3,T4> realCb;
+  realCb.Assign (cb);
+  Ptr<Object> object = realCb (a1,a2,a3,a4);
+  return object;
+}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5>
+Ptr<Object> 
+InterfaceId::CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
+{
+  CallbackBase cb = LookupConstructor (5);
+  Callback<Ptr<Object>,T1,T2,T3,T4,T5> realCb;
+  realCb.Assign (cb);
+  Ptr<Object> object = realCb (a1,a2,a3,a4,a5);
+  return object;
+}
+
+
+
 void
 Object::Ref (void) const
 {