--- 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 {