add 'factory' support to InterfaceId

This commit is contained in:
Mathieu Lacage
2008-01-02 15:54:53 +01:00
parent 2103459845
commit b88e90fec3
2 changed files with 270 additions and 5 deletions

View File

@@ -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<struct ConstructorInformation> constructors;
};
typedef std::vector<struct IidInformation>::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<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 @@ 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<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 @@ InterfaceIdTraceResolver::TraceAll (std::ostream &os, const TraceContext &contex
* 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 @@ InterfaceId::LookupByName (std::string name)
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 @@ InterfaceId::GetName (void) const
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 @@ 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<BaseA> ();
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<DerivedA,int> ();
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<BaseB> ();
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<DerivedB,int> ();
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<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;
}

View File

@@ -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 @@ public:
* \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 @@ Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7);
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
{