1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
3 * Copyright (c) 2007 INRIA, Gustavo Carneiro
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Authors: Gustavo Carneiro <gjcarneiro@gmail.com>,
19 * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
23 #include "singleton.h"
24 #include "trace-resolver.h"
25 #include "attribute.h"
26 #include "trace-source-accessor.h"
32 NS_LOG_COMPONENT_DEFINE ("Object");
34 /*********************************************************************
36 *********************************************************************/
44 uint16_t AllocateUid (std::string name);
45 void SetParent (uint16_t uid, uint16_t parent);
46 void SetTypeName (uint16_t uid, std::string typeName);
47 void SetGroupName (uint16_t uid, std::string groupName);
48 void AddConstructor (uint16_t uid, ns3::CallbackBase callback, uint32_t nArguments);
49 uint16_t GetUid (std::string name) const;
50 std::string GetName (uint16_t uid) const;
51 uint16_t GetParent (uint16_t uid) const;
52 std::string GetTypeName (uint16_t uid) const;
53 std::string GetGroupName (uint16_t uid) const;
54 ns3::CallbackBase GetConstructor (uint16_t uid, uint32_t nArguments);
55 bool HasConstructor (uint16_t uid);
56 uint32_t GetRegisteredN (void);
57 uint16_t GetRegistered (uint32_t i);
58 void AddAttribute (uint16_t uid,
62 ns3::Attribute initialValue,
63 ns3::Ptr<const ns3::AttributeAccessor> spec,
64 ns3::Ptr<const ns3::AttributeChecker> checker);
65 uint32_t GetAttributeListN (uint16_t uid) const;
66 std::string GetAttributeName (uint16_t uid, uint32_t i) const;
67 uint32_t GetAttributeFlags (uint16_t uid, uint32_t i) const;
68 ns3::Attribute GetAttributeInitialValue (uint16_t uid, uint32_t i) const;
69 ns3::Ptr<const ns3::AttributeAccessor> GetAttributeAccessor (uint16_t uid, uint32_t i) const;
70 ns3::Ptr<const ns3::AttributeChecker> GetAttributeChecker (uint16_t uid, uint32_t i) const;
71 void AddTraceSource (uint16_t uid,
74 ns3::Ptr<const ns3::TraceSourceAccessor> accessor);
75 uint32_t GetTraceSourceN (uint16_t uid) const;
76 std::string GetTraceSourceName (uint16_t uid, uint32_t i) const;
77 std::string GetTraceSourceHelp (uint16_t uid, uint32_t i) const;
78 ns3::Ptr<const ns3::TraceSourceAccessor> GetTraceSourceAccessor (uint16_t uid, uint32_t i) const;
81 struct ConstructorInformation {
85 struct AttributeInformation {
89 ns3::Attribute initialValue;
90 ns3::Ptr<const ns3::AttributeAccessor> param;
91 ns3::Ptr<const ns3::AttributeChecker> checker;
93 struct TraceSourceInformation {
96 ns3::Ptr<const ns3::TraceSourceAccessor> accessor;
98 struct IidInformation {
101 std::string typeName;
102 std::string groupName;
103 std::vector<struct ConstructorInformation> constructors;
104 std::vector<struct AttributeInformation> attributes;
105 std::vector<struct TraceSourceInformation> traceSources;
107 typedef std::vector<struct IidInformation>::const_iterator Iterator;
109 struct IidManager::IidInformation *LookupInformation (uint16_t uid) const;
111 std::vector<struct IidInformation> m_information;
114 IidManager::IidManager ()
118 IidManager::AllocateUid (std::string name)
121 for (Iterator i = m_information.begin (); i != m_information.end (); i++)
125 NS_FATAL_ERROR ("Trying to allocate twice the same uid: " << name);
130 struct IidInformation information;
131 information.name = name;
132 information.parent = 0;
133 information.typeName = "";
134 information.groupName = "";
135 m_information.push_back (information);
136 uint32_t uid = m_information.size ();
137 NS_ASSERT (uid <= 0xffff);
141 struct IidManager::IidInformation *
142 IidManager::LookupInformation (uint16_t uid) const
144 NS_ASSERT (uid <= m_information.size ());
145 return const_cast<struct IidInformation *> (&m_information[uid-1]);
149 IidManager::SetParent (uint16_t uid, uint16_t parent)
151 NS_ASSERT (parent <= m_information.size ());
152 struct IidInformation *information = LookupInformation (uid);
153 information->parent = parent;
156 IidManager::SetTypeName (uint16_t uid, std::string typeName)
158 struct IidInformation *information = LookupInformation (uid);
159 information->typeName = typeName;
162 IidManager::SetGroupName (uint16_t uid, std::string groupName)
164 struct IidInformation *information = LookupInformation (uid);
165 information->groupName = groupName;
169 IidManager::AddConstructor (uint16_t uid, ns3::CallbackBase callback, uint32_t nArguments)
171 struct IidInformation *information = LookupInformation (uid);
172 struct ConstructorInformation constructor;
173 constructor.cb = callback;
174 constructor.nArguments = nArguments;
175 for (std::vector<struct ConstructorInformation>::const_iterator i = information->constructors.begin ();
176 i != information->constructors.end (); i++)
178 if (i->nArguments == nArguments)
180 NS_FATAL_ERROR ("registered two constructors on the same type with the same number of arguments.");
184 information->constructors.push_back (constructor);
188 IidManager::GetUid (std::string name) const
191 for (Iterator i = m_information.begin (); i != m_information.end (); i++)
195 NS_ASSERT (j <= 0xffff);
203 IidManager::GetName (uint16_t uid) const
205 struct IidInformation *information = LookupInformation (uid);
206 return information->name;
209 IidManager::GetParent (uint16_t uid) const
211 struct IidInformation *information = LookupInformation (uid);
212 return information->parent;
215 IidManager::GetTypeName (uint16_t uid) const
217 struct IidInformation *information = LookupInformation (uid);
218 return information->typeName;
221 IidManager::GetGroupName (uint16_t uid) const
223 struct IidInformation *information = LookupInformation (uid);
224 return information->groupName;
228 IidManager::GetConstructor (uint16_t uid, uint32_t nArguments)
230 struct IidInformation *information = LookupInformation (uid);
231 for (std::vector<struct ConstructorInformation>::const_iterator i = information->constructors.begin ();
232 i != information->constructors.end (); i++)
234 if (i->nArguments == nArguments)
239 NS_FATAL_ERROR ("Requested constructor with "<<nArguments<<" arguments not found");
240 return ns3::CallbackBase ();
244 IidManager::HasConstructor (uint16_t uid)
246 struct IidInformation *information = LookupInformation (uid);
247 return !information->constructors.empty ();
251 IidManager::GetRegisteredN (void)
253 return m_information.size ();
256 IidManager::GetRegistered (uint32_t i)
262 IidManager::AddAttribute (uint16_t uid,
266 ns3::Attribute initialValue,
267 ns3::Ptr<const ns3::AttributeAccessor> spec,
268 ns3::Ptr<const ns3::AttributeChecker> checker)
270 struct IidInformation *information = LookupInformation (uid);
271 for (std::vector<struct AttributeInformation>::const_iterator j = information->attributes.begin ();
272 j != information->attributes.end (); j++)
276 NS_FATAL_ERROR ("Registered the same attribute twice name=\""<<name<<"\" in TypeId=\""<<information->name<<"\"");
280 struct AttributeInformation param;
284 param.initialValue = initialValue;
286 param.checker = checker;
287 information->attributes.push_back (param);
292 IidManager::GetAttributeListN (uint16_t uid) const
294 struct IidInformation *information = LookupInformation (uid);
295 return information->attributes.size ();
298 IidManager::GetAttributeName (uint16_t uid, uint32_t i) const
300 struct IidInformation *information = LookupInformation (uid);
301 NS_ASSERT (i < information->attributes.size ());
302 return information->attributes[i].name;
305 IidManager::GetAttributeFlags (uint16_t uid, uint32_t i) const
307 struct IidInformation *information = LookupInformation (uid);
308 NS_ASSERT (i < information->attributes.size ());
309 return information->attributes[i].flags;
312 IidManager::GetAttributeInitialValue (uint16_t uid, uint32_t i) const
314 struct IidInformation *information = LookupInformation (uid);
315 NS_ASSERT (i < information->attributes.size ());
316 return information->attributes[i].initialValue;
318 ns3::Ptr<const ns3::AttributeAccessor>
319 IidManager::GetAttributeAccessor (uint16_t uid, uint32_t i) const
321 struct IidInformation *information = LookupInformation (uid);
322 NS_ASSERT (i < information->attributes.size ());
323 return information->attributes[i].param;
325 ns3::Ptr<const ns3::AttributeChecker>
326 IidManager::GetAttributeChecker (uint16_t uid, uint32_t i) const
328 struct IidInformation *information = LookupInformation (uid);
329 NS_ASSERT (i < information->attributes.size ());
330 return information->attributes[i].checker;
334 IidManager::AddTraceSource (uint16_t uid,
337 ns3::Ptr<const ns3::TraceSourceAccessor> accessor)
339 struct IidInformation *information = LookupInformation (uid);
340 struct TraceSourceInformation source;
343 source.accessor = accessor;
344 information->traceSources.push_back (source);
347 IidManager::GetTraceSourceN (uint16_t uid) const
349 struct IidInformation *information = LookupInformation (uid);
350 return information->traceSources.size ();
353 IidManager::GetTraceSourceName (uint16_t uid, uint32_t i) const
355 struct IidInformation *information = LookupInformation (uid);
356 NS_ASSERT (i < information->traceSources.size ());
357 return information->traceSources[i].name;
360 IidManager::GetTraceSourceHelp (uint16_t uid, uint32_t i) const
362 struct IidInformation *information = LookupInformation (uid);
363 NS_ASSERT (i < information->traceSources.size ());
364 return information->traceSources[i].help;
366 ns3::Ptr<const ns3::TraceSourceAccessor>
367 IidManager::GetTraceSourceAccessor (uint16_t uid, uint32_t i) const
369 struct IidInformation *information = LookupInformation (uid);
370 NS_ASSERT (i < information->traceSources.size ());
371 return information->traceSources[i].accessor;
374 } // anonymous namespace
376 /*********************************************************************
377 * The TypeId TraceResolver
378 *********************************************************************/
382 class TypeIdTraceResolver : public TraceResolver
385 TypeIdTraceResolver (Ptr<const Object> aggregate);
386 virtual void Connect (std::string path, CallbackBase const &cb, const TraceContext &context);
387 virtual void Disconnect (std::string path, CallbackBase const &cb);
388 virtual void CollectSources (std::string path, const TraceContext &context,
389 SourceCollection *collection);
390 virtual void TraceAll (std::ostream &os, const TraceContext &context);
392 Ptr<const Object> ParseForInterface (std::string path);
393 Ptr<const Object> m_aggregate;
396 TypeIdTraceResolver::TypeIdTraceResolver (Ptr<const Object> aggregate)
397 : m_aggregate (aggregate)
400 TypeIdTraceResolver::ParseForInterface (std::string path)
402 std::string element = GetElement (path);
403 std::string::size_type dollar_pos = element.find ("$");
408 std::string interfaceName = element.substr (1, std::string::npos);
409 TypeId interfaceId = TypeId::LookupByName (interfaceName);
410 Ptr<Object> interface = m_aggregate->GetObject<Object> (interfaceId);
414 TypeIdTraceResolver::Connect (std::string path, CallbackBase const &cb, const TraceContext &context)
416 Ptr<const Object> interface = ParseForInterface (path);
419 interface->GetTraceResolver ()->Connect (GetSubpath (path), cb, context);
423 TypeIdTraceResolver::Disconnect (std::string path, CallbackBase const &cb)
425 Ptr<const Object> interface = ParseForInterface (path);
428 interface->TraceDisconnect (GetSubpath (path), cb);
432 TypeIdTraceResolver::CollectSources (std::string path, const TraceContext &context,
433 SourceCollection *collection)
435 m_aggregate->DoCollectSources (path, context, collection);
438 TypeIdTraceResolver::TraceAll (std::ostream &os, const TraceContext &context)
440 m_aggregate->DoTraceAll (os, context);
443 /*********************************************************************
445 *********************************************************************/
451 TypeId::TypeId (const char * name)
453 uint16_t uid = Singleton<IidManager>::Get ()->AllocateUid (name);
454 NS_ASSERT (uid != 0);
459 TypeId::TypeId (uint16_t tid)
465 TypeId::LookupByName (std::string name)
467 uint16_t uid = Singleton<IidManager>::Get ()->GetUid (name);
468 NS_ASSERT (uid != 0);
472 TypeId::LookupAttributeByFullName (std::string fullName, struct TypeId::AttributeInfo *info)
474 std::string::size_type pos = fullName.find ("::");
475 if (pos == std::string::npos)
479 std::string tidName = fullName.substr (0, pos);
480 std::string paramName = fullName.substr (pos+2, fullName.size () - (pos+2));
481 TypeId tid = LookupByName (tidName);
482 return tid.LookupAttributeByName (paramName, info);
485 TypeId::GetRegisteredN (void)
487 return Singleton<IidManager>::Get ()->GetRegisteredN ();
490 TypeId::GetRegistered (uint32_t i)
492 return TypeId (Singleton<IidManager>::Get ()->GetRegistered (i));
496 TypeId::LookupAttributeByName (std::string name, struct TypeId::AttributeInfo *info) const
499 TypeId nextTid = *this;
502 for (uint32_t i = 0; i < tid.GetAttributeListN (); i++)
504 std::string paramName = tid.GetAttributeName (i);
505 if (paramName == name)
507 info->accessor = tid.GetAttributeAccessor (i);
508 info->flags = tid.GetAttributeFlags (i);
509 info->initialValue = tid.GetAttributeInitialValue (i);
510 info->checker = tid.GetAttributeChecker (i);
514 nextTid = tid.GetParent ();
515 } while (nextTid != tid);
519 TypeId::LookupAttributeByPosition (uint32_t i, struct TypeId::AttributeInfo *info) const
523 TypeId nextTid = *this;
526 for (uint32_t j = 0; j < tid.GetAttributeListN (); j++)
530 info->accessor = tid.GetAttributeAccessor (j);
531 info->flags = tid.GetAttributeFlags (j);
532 info->initialValue = tid.GetAttributeInitialValue (j);
533 info->checker = tid.GetAttributeChecker (j);
538 nextTid = tid.GetParent ();
539 } while (nextTid != tid);
545 TypeId::SetParent (TypeId tid)
547 Singleton<IidManager>::Get ()->SetParent (m_tid, tid.m_tid);
551 TypeId::SetGroupName (std::string groupName)
553 Singleton<IidManager>::Get ()->SetGroupName (m_tid, groupName);
557 TypeId::SetTypeName (std::string typeName)
559 Singleton<IidManager>::Get ()->SetTypeName (m_tid, typeName);
563 TypeId::GetParent (void) const
565 uint16_t parent = Singleton<IidManager>::Get ()->GetParent (m_tid);
566 return TypeId (parent);
569 TypeId::GetGroupName (void) const
571 std::string groupName = Singleton<IidManager>::Get ()->GetGroupName (m_tid);
575 TypeId::GetTypeName (void) const
577 std::string typeName = Singleton<IidManager>::Get ()->GetTypeName (m_tid);
582 TypeId::GetName (void) const
584 std::string name = Singleton<IidManager>::Get ()->GetName (m_tid);
589 TypeId::HasConstructor (void) const
591 bool hasConstructor = Singleton<IidManager>::Get ()->HasConstructor (m_tid);
592 return hasConstructor;
596 TypeId::DoAddConstructor (CallbackBase cb, uint32_t nArguments)
598 Singleton<IidManager>::Get ()->AddConstructor (m_tid, cb, nArguments);
602 TypeId::AddAttribute (std::string name,
604 Attribute initialValue,
605 Ptr<const AttributeAccessor> param,
606 Ptr<const AttributeChecker> checker)
608 Singleton<IidManager>::Get ()->AddAttribute (m_tid, name, help, ATTR_SGC, initialValue, param, checker);
613 TypeId::AddAttribute (std::string name,
616 Attribute initialValue,
617 Ptr<const AttributeAccessor> param,
618 Ptr<const AttributeChecker> checker)
620 Singleton<IidManager>::Get ()->AddAttribute (m_tid, name, help, flags, initialValue, param, checker);
626 TypeId::LookupConstructor (uint32_t nArguments) const
628 CallbackBase constructor = Singleton<IidManager>::Get ()->GetConstructor (m_tid, nArguments);
633 TypeId::CreateObject (void) const
635 return CreateObject (AttributeList ());
638 TypeId::CreateObject (const AttributeList &attributes) const
640 CallbackBase cb = LookupConstructor (0);
641 Callback<Ptr<Object>,const AttributeList &> realCb;
643 Ptr<Object> object = realCb (attributes);
648 TypeId::GetAttributeListN (void) const
650 uint32_t n = Singleton<IidManager>::Get ()->GetAttributeListN (m_tid);
654 TypeId::GetAttributeName (uint32_t i) const
656 std::string name = Singleton<IidManager>::Get ()->GetAttributeName (m_tid, i);
660 TypeId::GetAttributeFullName (uint32_t i) const
662 return GetName () + "::" + GetAttributeName (i);
665 TypeId::GetAttributeInitialValue (uint32_t i) const
667 Attribute value = Singleton<IidManager>::Get ()->GetAttributeInitialValue (m_tid, i);
670 Ptr<const AttributeAccessor>
671 TypeId::GetAttributeAccessor (uint32_t i) const
673 // Used exclusively by the Object class.
674 Ptr<const AttributeAccessor> param = Singleton<IidManager>::Get ()->GetAttributeAccessor (m_tid, i);
678 TypeId::GetAttributeFlags (uint32_t i) const
680 // Used exclusively by the Object class.
681 uint32_t flags = Singleton<IidManager>::Get ()->GetAttributeFlags (m_tid, i);
684 Ptr<const AttributeChecker>
685 TypeId::GetAttributeChecker (uint32_t i) const
687 // Used exclusively by the Object class.
688 Ptr<const AttributeChecker> checker = Singleton<IidManager>::Get ()->GetAttributeChecker (m_tid, i);
693 TypeId::GetTraceSourceN (void) const
695 return Singleton<IidManager>::Get ()->GetTraceSourceN (m_tid);
698 TypeId::GetTraceSourceName (uint32_t i) const
700 return Singleton<IidManager>::Get ()->GetTraceSourceName (m_tid, i);
703 TypeId::GetTraceSourceHelp (uint32_t i) const
705 return Singleton<IidManager>::Get ()->GetTraceSourceHelp (m_tid, i);
707 Ptr<const TraceSourceAccessor>
708 TypeId::GetTraceSourceAccessor (uint32_t i) const
710 return Singleton<IidManager>::Get ()->GetTraceSourceAccessor (m_tid, i);
714 TypeId::AddTraceSource (std::string name,
716 Ptr<const TraceSourceAccessor> accessor)
718 Singleton<IidManager>::Get ()->AddTraceSource (m_tid, name, help, accessor);
723 Ptr<const TraceSourceAccessor>
724 TypeId::LookupTraceSourceByName (std::string name) const
727 TypeId nextTid = *this;
730 for (uint32_t i = 0; i < tid.GetTraceSourceN (); i++)
732 std::string srcName = tid.GetTraceSourceName (i);
735 return tid.GetTraceSourceAccessor (i);
738 nextTid = tid.GetParent ();
739 } while (nextTid != tid);
743 std::ostream & operator << (std::ostream &os, TypeId tid)
745 os << tid.GetName ();
748 std::istream & operator >> (std::istream &is, TypeId &tid)
750 std::string tidString;
752 tid = TypeId::LookupByName (tidString);
757 VALUE_HELPER_CPP (TypeId);
759 bool operator == (TypeId a, TypeId b)
761 return a.m_tid == b.m_tid;
764 bool operator != (TypeId a, TypeId b)
766 return a.m_tid != b.m_tid;
769 /*********************************************************************
770 * The AttributeList container implementation
771 *********************************************************************/
773 AttributeList::AttributeList ()
776 AttributeList::AttributeList (const AttributeList &o)
778 for (Attrs::const_iterator i = o.m_attributes.begin (); i != o.m_attributes.end (); i++)
781 attr.checker = i->checker;
782 attr.value = i->value.Copy ();
783 m_attributes.push_back (attr);
787 AttributeList::operator = (const AttributeList &o)
790 for (Attrs::const_iterator i = o.m_attributes.begin (); i != o.m_attributes.end (); i++)
793 attr.checker = i->checker;
794 attr.value = i->value.Copy ();
795 m_attributes.push_back (attr);
799 AttributeList::~AttributeList ()
805 AttributeList::Set (std::string name, Attribute value)
807 struct TypeId::AttributeInfo info;
808 TypeId::LookupAttributeByFullName (name, &info);
809 bool ok = DoSet (&info, value);
813 AttributeList::SetWithTid (TypeId tid, std::string name, Attribute value)
815 struct TypeId::AttributeInfo info;
816 tid.LookupAttributeByName (name, &info);
817 bool ok = DoSet (&info, value);
821 AttributeList::SetWithTid (TypeId tid, uint32_t position, Attribute value)
823 struct TypeId::AttributeInfo info;
824 tid.LookupAttributeByPosition (position, &info);
825 bool ok = DoSet (&info, value);
830 AttributeList::DoSetOne (Ptr<const AttributeChecker> checker, Attribute value)
832 // get rid of any previous value stored in this
834 for (Attrs::iterator k = m_attributes.begin (); k != m_attributes.end (); k++)
836 if (k->checker == checker)
838 m_attributes.erase (k);
842 // store the new value.
844 attr.checker = checker;
845 attr.value = value.Copy ();
846 m_attributes.push_back (attr);
849 AttributeList::DoSet (struct TypeId::AttributeInfo *info, Attribute value)
851 if (info->checker == 0)
855 bool ok = info->checker->Check (value);
858 // attempt to convert to string.
859 const StringValue *str = value.DynCast<const StringValue *> ();
864 // attempt to convert back to value.
865 Attribute v = info->checker->Create ();
866 ok = v.DeserializeFromString (str->Get ().Get (), info->checker);
871 ok = info->checker->Check (v);
878 DoSetOne (info->checker, value);
882 AttributeList::Reset (void)
884 m_attributes.clear ();
887 AttributeList::GetGlobal (void)
889 return Singleton<AttributeList>::Get ();
893 AttributeList::LookupAttributeFullNameByChecker (Ptr<const AttributeChecker> checker) const
895 for (uint32_t i = 0; i < TypeId::GetRegisteredN (); i++)
897 TypeId tid = TypeId::GetRegistered (i);
898 for (uint32_t j = 0; j < tid.GetAttributeListN (); j++)
900 if (checker == tid.GetAttributeChecker (j))
902 return tid.GetAttributeFullName (j);
906 NS_FATAL_ERROR ("Could not find requested Accessor.");
912 AttributeList::SerializeToString (void) const
914 std::ostringstream oss;
915 for (Attrs::const_iterator i = m_attributes.begin (); i != m_attributes.end (); i++)
917 std::string name = LookupAttributeFullNameByChecker (i->checker);
918 oss << name << "=" << i->value.SerializeToString (i->checker);
919 if (i != m_attributes.end ())
927 AttributeList::DeserializeFromString (std::string str)
931 std::string::size_type cur;
934 std::string::size_type equal = str.find ("=", cur);
935 if (equal == std::string::npos)
937 // XXX: invalid attribute.
942 std::string name = str.substr (cur, equal-cur);
943 struct TypeId::AttributeInfo info;
944 if (!TypeId::LookupAttributeByFullName (name, &info))
951 std::string::size_type next = str.find ("|", cur);
953 if (next == std::string::npos)
955 value = str.substr (equal+1, str.size () - (equal+1));
960 value = str.substr (equal+1, next - (equal+1));
963 Attribute val = info.checker->Create ();
964 bool ok = val.DeserializeFromString (value, info.checker);
972 DoSetOne (info.checker, val);
976 } while (cur != str.size ());
982 /*********************************************************************
983 * The Object implementation
984 *********************************************************************/
986 NS_OBJECT_ENSURE_REGISTERED (Object);
991 TypeId tid = TypeId ("Object");
997 Object::GetTypeId (void)
999 static TypeId tid = GetObjectIid ();
1006 m_tid (Object::GetTypeId ()),
1008 m_collecting (false),
1016 Object::Construct (const AttributeList &attributes)
1018 // loop over the inheritance tree back to the Object base class.
1021 // loop over all attributes in object type
1022 NS_LOG_DEBUG ("construct tid="<<tid.GetName ()<<", params="<<tid.GetAttributeListN ());
1023 for (uint32_t i = 0; i < tid.GetAttributeListN (); i++)
1025 Ptr<const AttributeAccessor> paramSpec = tid.GetAttributeAccessor (i);
1026 Attribute initial = tid.GetAttributeInitialValue (i);
1027 Ptr<const AttributeChecker> checker = tid.GetAttributeChecker (i);
1028 NS_LOG_DEBUG ("try to construct \""<< tid.GetName ()<<"::"<<
1029 tid.GetAttributeName (i)<<"\"");
1030 if (!(tid.GetAttributeFlags (i) & TypeId::ATTR_CONSTRUCT))
1035 // is this attribute stored in this AttributeList instance ?
1036 for (AttributeList::Attrs::const_iterator j = attributes.m_attributes.begin ();
1037 j != attributes.m_attributes.end (); j++)
1039 if (j->checker == checker)
1041 // We have a matching attribute value.
1042 DoSet (paramSpec, initial, checker, j->value);
1043 NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
1044 tid.GetAttributeName (i)<<"\"");
1051 // is this attribute stored in the global instance instance ?
1052 for (AttributeList::Attrs::const_iterator j = AttributeList::GetGlobal ()->m_attributes.begin ();
1053 j != AttributeList::GetGlobal ()->m_attributes.end (); j++)
1055 if (j->checker == checker)
1057 // We have a matching attribute value.
1058 DoSet (paramSpec, initial, checker, j->value);
1059 NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
1060 tid.GetAttributeName (i)<<"\" from global");
1068 // No matching attribute value so we set the default value.
1069 paramSpec->Set (this, initial);
1070 NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
1071 tid.GetAttributeName (i)<<"\" from initial value.");
1074 tid = tid.GetParent ();
1075 } while (tid != Object::GetTypeId ());
1076 NotifyConstructionCompleted ();
1079 Object::DoSet (Ptr<const AttributeAccessor> spec, Attribute initialValue,
1080 Ptr<const AttributeChecker> checker, Attribute value)
1082 bool ok = checker->Check (value);
1085 // attempt to convert to string
1086 const StringValue *str = value.DynCast<const StringValue *> ();
1091 // attempt to convert back from string.
1092 Attribute v = checker->Create ();
1093 ok = v.DeserializeFromString (str->Get ().Get (), checker);
1098 ok = checker->Check (v);
1105 ok = spec->Set (this, value);
1109 Object::SetAttribute (std::string name, Attribute value)
1111 struct TypeId::AttributeInfo info;
1112 if (!m_tid.LookupAttributeByName (name, &info))
1116 if (!(info.flags & TypeId::ATTR_SET))
1120 return DoSet (info.accessor, info.initialValue, info.checker, value);
1123 Object::GetAttribute (std::string name, std::string &value) const
1125 struct TypeId::AttributeInfo info;
1126 if (!m_tid.LookupAttributeByName (name, &info))
1130 if (!(info.flags & TypeId::ATTR_GET))
1134 Attribute v = info.checker->Create ();
1135 bool ok = info.accessor->Get (this, v);
1138 value = v.SerializeToString (info.checker);
1144 Object::GetAttribute (std::string name) const
1146 struct TypeId::AttributeInfo info;
1147 if (!m_tid.LookupAttributeByName (name, &info))
1149 return Attribute ();
1151 if (!(info.flags & TypeId::ATTR_GET))
1153 return Attribute ();
1155 Attribute value = info.checker->Create ();
1156 bool ok = info.accessor->Get (this, value);
1159 return Attribute ();
1165 Object::TraceSourceConnect (std::string name, const CallbackBase &cb)
1167 Ptr<const TraceSourceAccessor> accessor = m_tid.LookupTraceSourceByName (name);
1172 bool ok = accessor->Connect (this, cb);
1176 Object::TraceSourceConnectWithContext (std::string name, std::string context, const CallbackBase &cb)
1178 Ptr<const TraceSourceAccessor> accessor = m_tid.LookupTraceSourceByName (name);
1183 bool ok = accessor->ConnectWithContext (this, context, cb);
1187 Object::TraceSourceDisconnect (std::string name, const CallbackBase &cb)
1189 Ptr<const TraceSourceAccessor> accessor = m_tid.LookupTraceSourceByName (name);
1194 bool ok = accessor->Disconnect (this, cb);
1199 Object::GetRealTypeId (void) const
1206 Object::DoGetObject (TypeId tid) const
1208 NS_ASSERT (CheckLoose ());
1209 const Object *currentObject = this;
1211 NS_ASSERT (currentObject != 0);
1212 TypeId cur = currentObject->m_tid;
1213 while (cur != tid && cur != Object::GetTypeId ())
1215 cur = cur.GetParent ();
1219 return const_cast<Object *> (currentObject);
1221 currentObject = currentObject->m_next;
1222 } while (currentObject != this);
1226 Object::Dispose (void)
1228 Object *current = this;
1230 NS_ASSERT (current != 0);
1231 NS_ASSERT (!current->m_disposed);
1232 current->DoDispose ();
1233 current->m_disposed = true;
1234 current = current->m_next;
1235 } while (current != this);
1238 Object::NotifyConstructionCompleted (void)
1241 Object::AggregateObject (Ptr<Object> o)
1243 NS_ASSERT (!m_disposed);
1244 NS_ASSERT (!o->m_disposed);
1245 NS_ASSERT (CheckLoose ());
1246 NS_ASSERT (o->CheckLoose ());
1247 Object *other = PeekPointer (o);
1248 Object *next = m_next;
1249 m_next = other->m_next;
1250 other->m_next = next;
1251 NS_ASSERT (CheckLoose ());
1252 NS_ASSERT (o->CheckLoose ());
1256 Object::TraceConnect (std::string path, const CallbackBase &cb) const
1258 NS_ASSERT (CheckLoose ());
1259 GetTraceResolver ()->Connect (path, cb, TraceContext ());
1262 Object::TraceDisconnect (std::string path, const CallbackBase &cb) const
1264 NS_ASSERT (CheckLoose ());
1265 GetTraceResolver ()->Disconnect (path, cb);
1269 Object::SetTypeId (TypeId tid)
1271 NS_ASSERT (Check ());
1276 Object::DoDispose (void)
1278 NS_ASSERT (!m_disposed);
1282 Object::GetTraceResolver (void) const
1284 NS_ASSERT (CheckLoose ());
1285 Ptr<TypeIdTraceResolver> resolver =
1286 Create<TypeIdTraceResolver> (this);
1291 Object::Check (void) const
1293 return (m_count > 0);
1296 /* In some cases, when an event is scheduled against a subclass of
1297 * Object, and if no one owns a reference directly to this object, the
1298 * object is alive, has a refcount of zero and the method ran when the
1299 * event expires runs against the raw pointer which means that we are
1300 * manipulating an object with a refcount of zero. So, instead we
1301 * check the aggregate reference count.
1304 Object::CheckLoose (void) const
1306 uint32_t refcount = 0;
1307 const Object *current = this;
1310 refcount += current->m_count;
1311 current = current->m_next;
1313 while (current != this);
1315 return (refcount > 0);
1319 Object::MaybeDelete (void) const
1321 // First, check if any of the attached
1322 // Object has a non-zero count.
1323 const Object *current = this;
1325 NS_ASSERT (current != 0);
1326 if (current->m_count != 0)
1330 current = current->m_next;
1331 } while (current != this);
1333 // Ensure we are disposed.
1334 Object *tmp = const_cast<Object *> (this);
1335 const Object *end = this;
1337 NS_ASSERT (current != 0);
1338 Object *next = tmp->m_next;
1339 if (!tmp->m_disposed)
1344 } while (tmp != end);
1346 // all attached objects have a zero count so,
1347 // we can delete all attached objects.
1350 NS_ASSERT (current != 0);
1351 Object *next = current->m_next;
1354 } while (current != end);
1358 Object::DoCollectSources (std::string path, const TraceContext &context,
1359 TraceResolver::SourceCollection *collection) const
1361 const Object *current;
1364 if (current->m_collecting)
1368 current = current->m_next;
1369 } while (current != this);
1371 m_collecting = true;
1373 current = this->m_next;
1374 while (current != this)
1376 NS_ASSERT (current != 0);
1377 NS_LOG_LOGIC ("collect current=" << current);
1378 TypeId cur = current->m_tid;
1379 while (cur != Object::GetTypeId ())
1381 std::string name = cur.GetName ();
1382 std::string fullpath = path;
1383 fullpath.append ("/$");
1384 fullpath.append (name);
1385 NS_LOG_LOGIC("collect: " << fullpath);
1386 current->GetTraceResolver ()->CollectSources (fullpath, context, collection);
1387 cur = cur.GetParent ();
1389 current = current->m_next;
1392 m_collecting = false;
1395 Object::DoTraceAll (std::ostream &os, const TraceContext &context) const
1397 const Object *current;
1400 if (current->m_collecting)
1404 current = current->m_next;
1405 } while (current != this);
1407 m_collecting = true;
1409 current = this->m_next;
1410 while (current != this)
1412 NS_ASSERT (current != 0);
1413 current->GetTraceResolver ()->TraceAll (os, context);
1414 current = current->m_next;
1417 m_collecting = false;
1423 #ifdef RUN_SELF_TESTS
1426 #include "sv-trace-source.h"
1427 #include "composite-trace-resolver.h"
1431 class BaseA : public ns3::Object
1434 static ns3::TypeId GetTypeId (void) {
1435 static ns3::TypeId tid = ns3::TypeId ("BaseA")
1436 .SetParent (Object::GetTypeId ())
1437 .AddConstructor<BaseA> ();
1442 void BaseGenerateTrace (int16_t v)
1444 virtual void Dispose (void) {}
1445 virtual ns3::Ptr<ns3::TraceResolver> GetTraceResolver (void) const
1447 ns3::Ptr<ns3::CompositeTraceResolver> resolver =
1448 ns3::Create<ns3::CompositeTraceResolver> ();
1449 resolver->AddSource ("basea-x", ns3::TraceDoc ("test source"), m_source);
1450 resolver->SetParentResolver (Object::GetTraceResolver ());
1453 ns3::SVTraceSource<int16_t> m_source;
1456 class DerivedA : public BaseA
1459 static ns3::TypeId GetTypeId (void) {
1460 static ns3::TypeId tid = ns3::TypeId ("DerivedA")
1461 .SetParent (BaseA::GetTypeId ())
1462 .AddConstructor<DerivedA> ();
1467 void DerivedGenerateTrace (int16_t v)
1468 { m_sourceDerived = v; }
1469 virtual void Dispose (void) {
1472 virtual ns3::Ptr<ns3::TraceResolver> GetTraceResolver (void) const
1474 ns3::Ptr<ns3::CompositeTraceResolver> resolver =
1475 ns3::Create<ns3::CompositeTraceResolver> ();
1476 resolver->AddSource ("deriveda-x", ns3::TraceDoc ("test source"), m_sourceDerived);
1477 resolver->SetParentResolver (BaseA::GetTraceResolver ());
1480 ns3::SVTraceSource<int16_t> m_sourceDerived;
1483 class BaseB : public ns3::Object
1486 static ns3::TypeId GetTypeId (void) {
1487 static ns3::TypeId tid = ns3::TypeId ("BaseB")
1488 .SetParent (Object::GetTypeId ())
1489 .AddConstructor<BaseB> ();
1494 void BaseGenerateTrace (int16_t v)
1496 virtual void Dispose (void) {}
1497 virtual ns3::Ptr<ns3::TraceResolver> GetTraceResolver (void) const
1499 ns3::Ptr<ns3::CompositeTraceResolver> resolver =
1500 ns3::Create<ns3::CompositeTraceResolver> ();
1501 resolver->AddSource ("baseb-x", ns3::TraceDoc ("test source"), m_source);
1502 resolver->SetParentResolver (Object::GetTraceResolver ());
1505 ns3::SVTraceSource<int16_t> m_source;
1508 class DerivedB : public BaseB
1511 static ns3::TypeId GetTypeId (void) {
1512 static ns3::TypeId tid = ns3::TypeId ("DerivedB")
1513 .SetParent (BaseB::GetTypeId ())
1514 .AddConstructor<DerivedB> ();
1519 void DerivedGenerateTrace (int16_t v)
1520 { m_sourceDerived = v; }
1521 virtual void Dispose (void) {
1524 virtual ns3::Ptr<ns3::TraceResolver> GetTraceResolver (void) const
1526 ns3::Ptr<ns3::CompositeTraceResolver> resolver =
1527 ns3::Create<ns3::CompositeTraceResolver> ();
1528 resolver->AddSource ("derivedb-x", ns3::TraceDoc ("test source"), m_sourceDerived);
1529 resolver->SetParentResolver (BaseB::GetTraceResolver ());
1532 ns3::SVTraceSource<int16_t> m_sourceDerived;
1535 NS_OBJECT_ENSURE_REGISTERED (BaseA);
1536 NS_OBJECT_ENSURE_REGISTERED (DerivedA);
1537 NS_OBJECT_ENSURE_REGISTERED (BaseB);
1538 NS_OBJECT_ENSURE_REGISTERED (DerivedB);
1540 } // namespace anonymous
1544 class ObjectTest : public Test
1548 virtual bool RunTests (void);
1550 void BaseATrace (const TraceContext &context, int64_t oldValue, int64_t newValue);
1551 void DerivedATrace (const TraceContext &context, int64_t oldValue, int64_t newValue);
1552 void BaseBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue);
1553 void DerivedBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue);
1556 bool m_derivedATrace;
1558 bool m_derivedBTrace;
1561 ObjectTest::ObjectTest ()
1565 ObjectTest::BaseATrace (const TraceContext &context, int64_t oldValue, int64_t newValue)
1567 m_baseATrace = true;
1570 ObjectTest::DerivedATrace (const TraceContext &context, int64_t oldValue, int64_t newValue)
1572 m_derivedATrace = true;
1575 ObjectTest::BaseBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue)
1577 m_baseBTrace = true;
1580 ObjectTest::DerivedBTrace (const TraceContext &context, int64_t oldValue, int64_t newValue)
1582 m_derivedBTrace = true;
1586 ObjectTest::RunTests (void)
1590 Ptr<BaseA> baseA = CreateObject<BaseA> ();
1591 NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (), baseA);
1592 NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), 0);
1593 NS_TEST_ASSERT_EQUAL (baseA->GetObject<DerivedA> (), 0);
1594 baseA = CreateObject<DerivedA> ();
1595 NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (), baseA);
1596 NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), baseA);
1597 NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<DerivedA> (), 0);
1599 baseA = CreateObject<BaseA> ();
1600 Ptr<BaseB> baseB = CreateObject<BaseB> ();
1601 Ptr<BaseB> baseBCopy = baseB;
1602 baseA->AggregateObject (baseB);
1603 NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<BaseA> (), 0);
1604 NS_TEST_ASSERT_EQUAL (baseA->GetObject<DerivedA> (), 0);
1605 NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<BaseB> (), 0);
1606 NS_TEST_ASSERT_EQUAL (baseA->GetObject<DerivedB> (), 0);
1607 NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseB> (), 0);
1608 NS_TEST_ASSERT_EQUAL (baseB->GetObject<DerivedB> (), 0);
1609 NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseA> (), 0);
1610 NS_TEST_ASSERT_EQUAL (baseB->GetObject<DerivedA> (), 0);
1611 NS_TEST_ASSERT_UNEQUAL (baseBCopy->GetObject<BaseA> (), 0);
1613 baseA = CreateObject<DerivedA> ();
1614 baseB = CreateObject<DerivedB> ();
1616 baseA->AggregateObject (baseB);
1617 NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<DerivedB> (), 0);
1618 NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<BaseB> (), 0);
1619 NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<DerivedA> (), 0);
1620 NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseA> (), 0);
1621 NS_TEST_ASSERT_UNEQUAL (baseBCopy->GetObject<DerivedA> (), 0);
1622 NS_TEST_ASSERT_UNEQUAL (baseBCopy->GetObject<BaseA> (), 0);
1623 NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<DerivedB> (), 0);
1624 NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseB> (), 0)
1626 baseA = CreateObject<BaseA> ();
1627 baseB = CreateObject<BaseB> ();
1628 baseA->AggregateObject (baseB);
1630 baseA = baseB->GetObject<BaseA> ();
1632 baseA = CreateObject<BaseA> ();
1633 baseA->TraceConnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
1634 m_baseATrace = false;
1635 baseA->BaseGenerateTrace (1);
1636 NS_TEST_ASSERT (m_baseATrace);
1637 baseA->TraceDisconnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
1639 baseB = CreateObject<BaseB> ();
1640 baseB->TraceConnect ("/baseb-x", MakeCallback (&ObjectTest::BaseBTrace, this));
1641 m_baseBTrace = false;
1642 baseB->BaseGenerateTrace (2);
1643 NS_TEST_ASSERT (m_baseBTrace);
1644 baseB->TraceDisconnect ("/baseb-x", MakeCallback (&ObjectTest::BaseBTrace, this));
1646 baseA->AggregateObject (baseB);
1648 baseA->TraceConnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
1649 m_baseATrace = false;
1650 baseA->BaseGenerateTrace (3);
1651 NS_TEST_ASSERT (m_baseATrace);
1652 baseA->TraceDisconnect ("/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
1654 baseA->TraceConnect ("/$BaseB/baseb-x", MakeCallback (&ObjectTest::BaseBTrace, this));
1655 m_baseBTrace = false;
1656 baseB->BaseGenerateTrace (4);
1657 NS_TEST_ASSERT (m_baseBTrace);
1658 baseA->TraceDisconnect ("/$BaseB/baseb-x", MakeCallback (&ObjectTest::BaseBTrace, this));
1659 m_baseBTrace = false;
1660 baseB->BaseGenerateTrace (5);
1661 NS_TEST_ASSERT (!m_baseBTrace);
1663 baseB->TraceConnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
1664 m_baseATrace = false;
1665 baseA->BaseGenerateTrace (6);
1666 NS_TEST_ASSERT (m_baseATrace);
1667 baseB->TraceDisconnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
1669 baseA->TraceConnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
1670 m_baseATrace = false;
1671 baseA->BaseGenerateTrace (7);
1672 NS_TEST_ASSERT (m_baseATrace);
1673 baseA->TraceDisconnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
1675 Ptr<DerivedA> derivedA;
1676 derivedA = CreateObject<DerivedA> ();
1677 baseB = CreateObject<BaseB> ();
1678 derivedA->AggregateObject (baseB);
1679 baseB->TraceConnect ("/$DerivedA/deriveda-x", MakeCallback (&ObjectTest::DerivedATrace, this));
1680 baseB->TraceConnect ("/$DerivedA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
1681 m_derivedATrace = false;
1682 m_baseATrace = false;
1683 derivedA->DerivedGenerateTrace (8);
1684 derivedA->BaseGenerateTrace (9);
1685 NS_TEST_ASSERT (m_derivedATrace);
1686 NS_TEST_ASSERT (m_baseATrace);
1687 baseB->TraceDisconnect ("/$DerivedA/deriveda-x", MakeCallback (&ObjectTest::BaseATrace, this));
1688 baseB->TraceDisconnect ("/$DerivedA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
1690 baseB->TraceConnect ("/$DerivedA/*", MakeCallback (&ObjectTest::DerivedATrace, this));
1691 m_derivedATrace = false;
1692 derivedA->DerivedGenerateTrace (10);
1693 NS_TEST_ASSERT (m_derivedATrace);
1694 // here, we have connected the derived trace sink to all
1695 // trace sources, including the base trace source.
1696 m_derivedATrace = false;
1697 derivedA->BaseGenerateTrace (11);
1698 NS_TEST_ASSERT (m_derivedATrace);
1699 baseB->TraceDisconnect ("/$DerivedA/*", MakeCallback (&ObjectTest::BaseATrace, this));
1701 // Test the object creation code of TypeId
1702 Ptr<Object> a = BaseA::GetTypeId ().CreateObject ();
1703 NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (), a);
1704 NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (DerivedA::GetTypeId ()), 0);
1705 NS_TEST_ASSERT_EQUAL (a->GetObject<DerivedA> (), 0);
1706 a = DerivedA::GetTypeId ().CreateObject ();
1707 NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (), a);
1708 NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (DerivedA::GetTypeId ()), a);
1709 NS_TEST_ASSERT_UNEQUAL (a->GetObject<DerivedA> (), 0);
1715 static ObjectTest g_interfaceObjectTests;
1720 #endif /* RUN_SELF_TESTS */