From b88e90fec39bbcbefa8c108886a9eec4c03220cf Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Wed, 2 Jan 2008 15:54:53 +0100 Subject: [PATCH] add 'factory' support to InterfaceId --- src/core/object.cc | 103 +++++++++++++++++++++++++-- src/core/object.h | 172 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 270 insertions(+), 5 deletions(-) diff --git a/src/core/object.cc b/src/core/object.cc index fac72094e..6a85acf89 100644 --- a/src/core/object.cc +++ b/src/core/object.cc @@ -38,13 +38,20 @@ class IidManager 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 constructors; }; typedef std::vector::const_iterator Iterator; @@ -89,6 +96,24 @@ IidManager::SetParent (uint16_t uid, uint16_t parent) 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::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 @@ IidManager::GetParent (uint16_t uid) const 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::const_iterator i = information->constructors.begin (); + i != information->constructors.end (); i++) + { + if (i->nArguments == nArguments) + { + return i->cb; + } + } + NS_FATAL_ERROR ("Requested constructor with "<::Get ()->AllocateUid (name); + NS_ASSERT (uid != 0); + m_iid = uid; +} + InterfaceId::InterfaceId (uint16_t iid) : m_iid (iid) @@ -205,6 +252,12 @@ InterfaceId::LookupByName (std::string name) return InterfaceId (uid); } InterfaceId +InterfaceId::SetParent (InterfaceId iid) +{ + Singleton::Get ()->SetParent (m_iid, iid.m_iid); + return *this; +} +InterfaceId InterfaceId::GetParent (void) const { uint16_t parent = Singleton::Get ()->GetParent (m_iid); @@ -217,6 +270,29 @@ InterfaceId::GetName (void) const return name; } +void +InterfaceId::DoAddConstructor (CallbackBase cb, uint32_t nArguments) +{ + Singleton::Get ()->AddConstructor (m_iid, cb, nArguments); +} + +CallbackBase +InterfaceId::LookupConstructor (uint32_t nArguments) +{ + CallbackBase constructor = Singleton::Get ()->GetConstructor (m_iid, nArguments); + return constructor; +} + +Ptr +InterfaceId::CreateObject (void) +{ + CallbackBase cb = LookupConstructor (0); + Callback > realCb; + realCb.Assign (cb); + Ptr object = realCb (); + return object; +} + bool operator == (InterfaceId a, InterfaceId b) { return a.m_iid == b.m_iid; @@ -486,7 +562,9 @@ class BaseA : public ns3::Object { 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 (); return iid; } BaseA () @@ -509,7 +587,9 @@ class DerivedA : public BaseA { 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 (); return iid; } DerivedA (int v) @@ -534,7 +614,9 @@ class BaseB : public ns3::Object { 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 (); return iid; } BaseB () @@ -557,7 +639,9 @@ class DerivedB : public BaseB { 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 (); return iid; } DerivedB (int v) @@ -739,6 +823,17 @@ ObjectTest::RunTests (void) NS_TEST_ASSERT (m_derivedATrace); baseB->TraceDisconnect ("/$DerivedA/*", MakeCallback (&ObjectTest::BaseATrace, this)); + // Test the object creation code of InterfaceId + Ptr a = BaseA::iid ().CreateObject (); + NS_TEST_ASSERT_EQUAL (a->QueryInterface (), a); + NS_TEST_ASSERT_EQUAL (a->QueryInterface (DerivedA::iid ()), 0); + NS_TEST_ASSERT_EQUAL (a->QueryInterface (), 0); + a = DerivedA::iid ().CreateObject (10); + NS_TEST_ASSERT_EQUAL (a->QueryInterface (), a); + NS_TEST_ASSERT_EQUAL (a->QueryInterface (DerivedA::iid ()), a); + NS_TEST_ASSERT_UNEQUAL (a->QueryInterface (), 0); + + return result; } diff --git a/src/core/object.h b/src/core/object.h index f366e9344..b40a58ca3 100644 --- a/src/core/object.h +++ b/src/core/object.h @@ -25,11 +25,14 @@ #include #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 @@ public: * \returns the name of this interface. */ std::string GetName (void) const; + + InterfaceId (std::string); + + InterfaceId SetParent (InterfaceId iid); + template + InterfaceId AddConstructor (void); + template + InterfaceId AddConstructor (void); + template + InterfaceId AddConstructor (void); + template + InterfaceId AddConstructor (void); + template + InterfaceId AddConstructor (void); + template + InterfaceId AddConstructor (void); + + + Ptr CreateObject (void); + template + Ptr CreateObject (T1 a1); + template + Ptr CreateObject (T1 a1, T2 a2); + template + Ptr CreateObject (T1 a1, T2 a2, T3 a3); + template + Ptr CreateObject (T1 a1, T2 a2, T3 a3, T4 a4); + template + Ptr 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 @@ Ptr CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7); namespace ns3 { + +template +InterfaceId +InterfaceId::AddConstructor (void) +{ + struct Maker { + static Ptr Create (void) { + return ns3::CreateObject (); + } + }; + CallbackBase cb = MakeCallback (&Maker::Create); + DoAddConstructor (cb, 0); + return *this; +} +template +InterfaceId +InterfaceId::AddConstructor (void) +{ + struct Maker { + static Ptr Create (T1 a1) { + return ns3::CreateObject (a1); + } + }; + CallbackBase cb = MakeCallback (&Maker::Create); + DoAddConstructor (cb, 1); + return *this; +} +template +InterfaceId +InterfaceId::AddConstructor (void) +{ + struct Maker { + static Ptr Create (T1 a1, T2 a2) { + return ns3::CreateObject (a1, a2); + } + }; + CallbackBase cb = MakeCallback (&Maker::Create); + DoAddConstructor (cb, 2); + return *this; +} +template +InterfaceId +InterfaceId::AddConstructor (void) +{ + struct Maker { + static Ptr Create (T1 a1, T2 a2, T3 a3) { + return ns3::CreateObject (a1, a2, a3); + } + }; + CallbackBase cb = MakeCallback (&Maker::Create); + DoAddConstructor (cb, 3); + return *this; +} +template +InterfaceId +InterfaceId::AddConstructor (void) +{ + struct Maker { + static Ptr Create (T1 a1, T2 a2, T3 a3, T4 a4) { + return ns3::CreateObject (a1, a2, a3, a4); + } + }; + CallbackBase cb = MakeCallback (&Maker::Create); + DoAddConstructor (cb, 4); + return *this; +} +template +InterfaceId +InterfaceId::AddConstructor (void) +{ + struct Maker { + static Ptr Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) { + return ns3::CreateObject (a1, a2, a3, a4, a5); + } + }; + CallbackBase cb = MakeCallback (&Maker::Create); + DoAddConstructor (cb, 5); + return *this; +} + +template +Ptr +InterfaceId::CreateObject (T1 a1) +{ + CallbackBase cb = LookupConstructor (1); + Callback,T1> realCb; + realCb.Assign (cb); + Ptr object = realCb (a1); + return object; +} +template +Ptr +InterfaceId::CreateObject (T1 a1, T2 a2) +{ + CallbackBase cb = LookupConstructor (2); + Callback,T1,T2> realCb; + realCb.Assign (cb); + Ptr object = realCb (a1,a2); + return object; +} +template +Ptr +InterfaceId::CreateObject (T1 a1, T2 a2, T3 a3) +{ + CallbackBase cb = LookupConstructor (3); + Callback,T1,T2,T3> realCb; + realCb.Assign (cb); + Ptr object = realCb (a1,a2,a3); + return object; +} +template +Ptr +InterfaceId::CreateObject (T1 a1, T2 a2, T3 a3, T4 a4) +{ + CallbackBase cb = LookupConstructor (4); + Callback,T1,T2,T3,T4> realCb; + realCb.Assign (cb); + Ptr object = realCb (a1,a2,a3,a4); + return object; +} + template +Ptr +InterfaceId::CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) +{ + CallbackBase cb = LookupConstructor (5); + Callback,T1,T2,T3,T4,T5> realCb; + realCb.Assign (cb); + Ptr object = realCb (a1,a2,a3,a4,a5); + return object; +} + + + void Object::Ref (void) const {