From 8e1489d85b5e31ae45ca8d25df8a105f1fa2e91b Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Sat, 4 Aug 2007 17:14:54 +0200 Subject: [PATCH] update the Tag API to match the Header/Trailer API --- src/common/packet.h | 2 +- src/common/tags.cc | 50 ++++++++++++------------ src/common/tags.h | 92 +++++++++++++++++++++++---------------------- 3 files changed, 74 insertions(+), 70 deletions(-) diff --git a/src/common/packet.h b/src/common/packet.h index ce614d2c6..c9aa0beb2 100644 --- a/src/common/packet.h +++ b/src/common/packet.h @@ -361,7 +361,7 @@ private: * { * // we really want to make sure that this * // string is unique in the universe. - * static uint32_t uid = TagRegistry ("MyTag.unique.prefix"); + * static uint32_t uid = TagRegistry::Register ("MyTag.unique.prefix"); * return uid; * } * \endcode diff --git a/src/common/tags.cc b/src/common/tags.cc index 0d78334f4..795118981 100644 --- a/src/common/tags.cc +++ b/src/common/tags.cc @@ -24,21 +24,21 @@ namespace ns3 { -Tag::TagInfoVector * -Tag::GetInfo (void) +TagRegistry::TagInfoVector * +TagRegistry::GetInfo (void) { - static Tag::TagInfoVector vector; + static TagRegistry::TagInfoVector vector; return &vector; } std::string -Tag::GetUidString (uint32_t uid) +TagRegistry::GetUidString (uint32_t uid) { TagInfo info = (*GetInfo ())[uid - 1]; return info.uidString; } uint32_t -Tag::GetUidFromUidString (std::string uidString) +TagRegistry::GetUidFromUidString (std::string uidString) { TagInfoVector *vec = GetInfo (); uint32_t uid = 1; @@ -55,31 +55,31 @@ Tag::GetUidFromUidString (std::string uidString) } void -Tag::Destruct (uint32_t uid, uint8_t data[Tags::SIZE]) +TagRegistry::Destruct (uint32_t uid, uint8_t data[Tags::SIZE]) { TagInfo info = (*GetInfo ())[uid - 1]; info.destruct (data); } void -Tag::Print (uint32_t uid, uint8_t data[Tags::SIZE], std::ostream &os) +TagRegistry::Print (uint32_t uid, uint8_t data[Tags::SIZE], std::ostream &os) { TagInfo info = (*GetInfo ())[uid - 1]; info.print (data, os); } uint32_t -Tag::GetSerializedSize (uint32_t uid, uint8_t data[Tags::SIZE]) +TagRegistry::GetSerializedSize (uint32_t uid, uint8_t data[Tags::SIZE]) { TagInfo info = (*GetInfo ())[uid - 1]; return info.getSerializedSize (data); } void -Tag::Serialize (uint32_t uid, uint8_t data[Tags::SIZE], Buffer::Iterator start) +TagRegistry::Serialize (uint32_t uid, uint8_t data[Tags::SIZE], Buffer::Iterator start) { TagInfo info = (*GetInfo ())[uid - 1]; info.serialize (data, start); } uint32_t -Tag::Deserialize (uint32_t uid, uint8_t data[Tags::SIZE], Buffer::Iterator start) +TagRegistry::Deserialize (uint32_t uid, uint8_t data[Tags::SIZE], Buffer::Iterator start) { TagInfo info = (*GetInfo ())[uid - 1]; return info.deserialize (data, start); @@ -184,7 +184,7 @@ Tags::Print (std::ostream &os) const { for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) { - Tag::Print (cur->m_id, cur->m_data, os); + TagRegistry::Print (cur->m_id, cur->m_data, os); } } @@ -194,10 +194,10 @@ Tags::GetSerializedSize (void) const uint32_t totalSize = 4; // reserve space for the size of the tag data. for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) { - uint32_t size = Tag::GetSerializedSize (cur->m_id, cur->m_data); + uint32_t size = TagRegistry::GetSerializedSize (cur->m_id, cur->m_data); if (size != 0) { - std::string uidString = Tag::GetUidString (cur->m_id); + std::string uidString = TagRegistry::GetUidString (cur->m_id); totalSize += 4; // for the size of the string itself. totalSize += uidString.size (); totalSize += size; @@ -212,14 +212,14 @@ Tags::Serialize (Buffer::Iterator i, uint32_t totalSize) const i.WriteU32 (totalSize); for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) { - uint32_t size = Tag::GetSerializedSize (cur->m_id, cur->m_data); + uint32_t size = TagRegistry::GetSerializedSize (cur->m_id, cur->m_data); if (size != 0) { - std::string uidString = Tag::GetUidString (cur->m_id); + std::string uidString = TagRegistry::GetUidString (cur->m_id); i.WriteU32 (uidString.size ()); uint8_t *buf = (uint8_t *)uidString.c_str (); i.Write (buf, uidString.size ()); - Tag::Serialize (cur->m_id, cur->m_data, i); + TagRegistry::Serialize (cur->m_id, cur->m_data, i); } } } @@ -240,12 +240,12 @@ Tags::Deserialize (Buffer::Iterator i) uidString.push_back (c); } bytesRead += uidStringSize; - uint32_t uid = Tag::GetUidFromUidString (uidString); + uint32_t uid = TagRegistry::GetUidFromUidString (uidString); struct TagData *newStart = AllocData (); newStart->m_count = 1; newStart->m_next = 0; newStart->m_id = uid; - bytesRead += Tag::Deserialize (uid, newStart->m_data, i); + bytesRead += TagRegistry::Deserialize (uid, newStart->m_data, i); newStart->m_next = m_next; m_next = newStart; } @@ -299,7 +299,7 @@ public: class myTagA { public: - static const char *GetUid (void) {return "myTagA.test.nsnam.org";} + static uint32_t GetUid (void) {static uint32_t uid = TagRegistry::Register ("myTagA.test.nsnam.org"); return uid;} void Print (std::ostream &os) const {g_a = true;} uint32_t GetSerializedSize (void) const {return 1;} void Serialize (Buffer::Iterator i) const {i.WriteU8 (a);} @@ -310,7 +310,7 @@ public: class myTagB { public: - static const char *GetUid (void) {return "myTagB.test.nsnam.org";} + static uint32_t GetUid (void) {static uint32_t uid = TagRegistry::Register ("myTagB.test.nsnam.org"); return uid;} void Print (std::ostream &os) const {g_b = true;} uint32_t GetSerializedSize (void) const {return 4;} void Serialize (Buffer::Iterator i) const {i.WriteU32 (b);} @@ -321,7 +321,7 @@ public: class myTagC { public: - static const char *GetUid (void) {return "myTagC.test.nsnam.org";} + static uint32_t GetUid (void) {static uint32_t uid = TagRegistry::Register ("myTagC.test.nsnam.org"); return uid;} void Print (std::ostream &os) const {g_c = true;} uint32_t GetSerializedSize (void) const {return Tags::SIZE;} void Serialize (Buffer::Iterator i) const {i.Write (c, Tags::SIZE);} @@ -331,7 +331,8 @@ public: class myInvalidTag { public: - static const char *GetUid (void) {return "myInvalidTag.test.nsnam.org";} + static uint32_t GetUid (void) + {static uint32_t uid = TagRegistry::Register ("myinvalidTag.test.nsnam.org"); return uid;} void Print (std::ostream &os) const {} uint32_t GetSerializedSize (void) const {return 0;} void Serialize (Buffer::Iterator i) const {} @@ -342,7 +343,7 @@ public: class myTagZ { public: - static const char *GetUid (void) {return "myTagZ.test.nsnam.org";} + static uint32_t GetUid (void) {static uint32_t uid = TagRegistry::Register ("myTagZ.test.nsnam.org"); return uid;} void Print (std::ostream &os) const {g_z = true;} uint32_t GetSerializedSize (void) const {return 0;} void Serialize (Buffer::Iterator i) const {} @@ -354,7 +355,8 @@ public: class MySmartTag { public: - static const char *GetUid (void) {return "mySmartTag.test.nsnam.org";} + static uint32_t GetUid (void) + {static uint32_t uid = TagRegistry::Register ("MySmartTag.test.nsnam.org"); return uid;} MySmartTag () { //std::cout << "construct" << std::endl; diff --git a/src/common/tags.h b/src/common/tags.h index 7442b6439..db89f0694 100644 --- a/src/common/tags.h +++ b/src/common/tags.h @@ -26,6 +26,30 @@ #include #include "buffer.h" +/** + * \ingroup tag + * \brief this macro should be instantiated exactly once for each + * new type of Tag + * + * This macro will ensure that your new Tag type is registered + * within the tag registry. In most cases, this macro + * is not really needed but, for safety, please, use it all the + * time. + * + * Note: This macro is _absolutely_ needed if you try to run a + * distributed simulation. + */ +#define NS_TAG_ENSURE_REGISTERED(x) \ +namespace { \ +static class thisisaveryverylongclassname \ +{ \ +public: \ + thisisaveryverylongclassname () \ + { uint32_t uid; uid = x::GetUid ();} \ +} g_thisisanotherveryveryverylongname; \ +} + + namespace ns3 { template @@ -96,30 +120,18 @@ private: namespace ns3 { /** - * \brief represent a single tag + * \brief a registry of all existing tag types. * \internal * * This class is used to give polymorphic access to the methods * exported by a tag. It also is used to associate a single - * reliable uid to each unique type. The tricky part here is - * that we have to deal correctly with a single type - * being registered multiple times in AllocateUid so, - * AllocateUid must first check in the list of existing - * types if there is already a type registered with the - * same string returned by T::GetUid. - * - * It is important to note that, for example, this code - * will never be triggered on ELF systems (linux, and - * a lot of unixes) because the ELF runtime ensures that - * there exist a single instance of a template instanciation - * even if multiple instanciations of that template are - * present in memory at runtime. + * reliable uid to each unique type. */ -class Tag +class TagRegistry { public: template - static uint32_t GetUid (void); + static uint32_t Register (std::string uidString); static std::string GetUidString (uint32_t uid); static uint32_t GetUidFromUidString (std::string uidString); static void Destruct (uint32_t uid, uint8_t data[Tags::SIZE]); @@ -154,43 +166,41 @@ private: static void DoSerialize (uint8_t data[Tags::SIZE], Buffer::Iterator start); template static uint32_t DoDeserialize (uint8_t data[Tags::SIZE], Buffer::Iterator start); - template - static uint32_t AllocateUid (void); static TagInfoVector *GetInfo (void); }; template void -Tag::DoDestruct (uint8_t data[Tags::SIZE]) +TagRegistry::DoDestruct (uint8_t data[Tags::SIZE]) { T *tag = reinterpret_cast (data); tag->~T (); } template void -Tag::DoPrint (uint8_t data[Tags::SIZE], std::ostream &os) +TagRegistry::DoPrint (uint8_t data[Tags::SIZE], std::ostream &os) { T *tag = reinterpret_cast (data); tag->Print (os); } template uint32_t -Tag::DoGetSerializedSize (uint8_t data[Tags::SIZE]) +TagRegistry::DoGetSerializedSize (uint8_t data[Tags::SIZE]) { T *tag = reinterpret_cast (data); return tag->GetSerializedSize (); } template void -Tag::DoSerialize (uint8_t data[Tags::SIZE], Buffer::Iterator start) +TagRegistry::DoSerialize (uint8_t data[Tags::SIZE], Buffer::Iterator start) { T *tag = reinterpret_cast (data); tag->Serialize (start); } template uint32_t -Tag::DoDeserialize (uint8_t data[Tags::SIZE], Buffer::Iterator start) +TagRegistry::DoDeserialize (uint8_t data[Tags::SIZE], Buffer::Iterator start) { T *tag = reinterpret_cast (data); return tag->Deserialize (start); @@ -198,33 +208,25 @@ Tag::DoDeserialize (uint8_t data[Tags::SIZE], Buffer::Iterator start) template uint32_t -Tag::GetUid (void) -{ - static uint32_t uid = AllocateUid (); - return uid; -} - -template -uint32_t -Tag::AllocateUid (void) +TagRegistry::Register (std::string uidString) { TagInfoVector *vec = GetInfo (); uint32_t j = 0; for (TagInfoVector::iterator i = vec->begin (); i != vec->end (); i++) { - if (i->uidString == T::GetUid ()) + if (i->uidString == uidString) { return j; } j++; } TagInfo info; - info.uidString = T::GetUid (); - info.destruct = &Tag::DoDestruct; - info.print = &Tag::DoPrint; - info.getSerializedSize = &Tag::DoGetSerializedSize; - info.serialize = &Tag::DoSerialize; - info.deserialize = &Tag::DoDeserialize; + info.uidString = uidString; + info.destruct = &TagRegistry::DoDestruct; + info.print = &TagRegistry::DoPrint; + info.getSerializedSize = &TagRegistry::DoGetSerializedSize; + info.serialize = &TagRegistry::DoSerialize; + info.deserialize = &TagRegistry::DoDeserialize; vec->push_back (info); uint32_t uid = vec->size (); return uid; @@ -238,12 +240,12 @@ Tags::Add (T const&tag) // ensure this id was not yet added for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) { - NS_ASSERT (cur->m_id != Tag::GetUid ()); + NS_ASSERT (cur->m_id != T::GetUid ()); } struct TagData *newStart = AllocData (); newStart->m_count = 1; newStart->m_next = 0; - newStart->m_id = Tag::GetUid (); + newStart->m_id = T::GetUid (); void *buf = &newStart->m_data; new (buf) T (tag); newStart->m_next = m_next; @@ -255,7 +257,7 @@ bool Tags::Remove (T &tag) { NS_ASSERT (sizeof (T) <= Tags::SIZE); - return Remove (Tag::GetUid ()); + return Remove (T::GetUid ()); } template @@ -265,7 +267,7 @@ Tags::Peek (T &tag) const NS_ASSERT (sizeof (T) <= Tags::SIZE); for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) { - if (cur->m_id == Tag::GetUid ()) + if (cur->m_id == T::GetUid ()) { /* found tag */ T *data = reinterpret_cast (&cur->m_data); @@ -325,14 +327,14 @@ Tags::RemoveAll (void) } if (prev != 0) { - Tag::Destruct (prev->m_id, prev->m_data); + TagRegistry::Destruct (prev->m_id, prev->m_data); FreeData (prev); } prev = cur; } if (prev != 0) { - Tag::Destruct (prev->m_id, prev->m_data); + TagRegistry::Destruct (prev->m_id, prev->m_data); FreeData (prev); } m_next = 0;