update the Tag API to match the Header/Trailer API
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sat, 04 Aug 2007 17:14:54 +0200
changeset 1155 1269189b9f41
parent 1154 3434ebc3c553
child 1156 48595ba90908
update the Tag API to match the Header/Trailer API
src/common/packet.h
src/common/tags.cc
src/common/tags.h
--- a/src/common/packet.h	Sat Aug 04 16:58:16 2007 +0200
+++ b/src/common/packet.h	Sat Aug 04 17:14:54 2007 +0200
@@ -361,7 +361,7 @@
  * {
  *   // we really want to make sure that this
  *   // string is unique in the universe.
- *   static uint32_t uid = TagRegistry<MyTag> ("MyTag.unique.prefix");
+ *   static uint32_t uid = TagRegistry::Register<MyTag> ("MyTag.unique.prefix");
  *   return uid;
  * }
  * \endcode
--- a/src/common/tags.cc	Sat Aug 04 16:58:16 2007 +0200
+++ b/src/common/tags.cc	Sat Aug 04 17:14:54 2007 +0200
@@ -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 @@
 }
 
 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 @@
 {
   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 @@
   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 @@
   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 @@
           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 @@
 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> ("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 @@
 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> ("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 @@
 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> ("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 @@
 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> ("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 @@
 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> ("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 @@
 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> ("MySmartTag.test.nsnam.org"); return uid;}
   MySmartTag ()
   {
     //std::cout << "construct" << std::endl;
--- a/src/common/tags.h	Sat Aug 04 16:58:16 2007 +0200
+++ b/src/common/tags.h	Sat Aug 04 17:14:54 2007 +0200
@@ -26,6 +26,30 @@
 #include <vector>
 #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 <typename T>
@@ -96,30 +120,18 @@
 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 <typename T>
-  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 @@
   static void DoSerialize (uint8_t data[Tags::SIZE], Buffer::Iterator start);
   template <typename T>
   static uint32_t DoDeserialize (uint8_t data[Tags::SIZE], Buffer::Iterator start);
-  template <typename T>
-  static uint32_t AllocateUid (void);
 
   static TagInfoVector *GetInfo (void);
 };
 
 template <typename T>
 void 
-Tag::DoDestruct (uint8_t data[Tags::SIZE])
+TagRegistry::DoDestruct (uint8_t data[Tags::SIZE])
 {
   T *tag = reinterpret_cast<T *> (data);
   tag->~T ();  
 }
 template <typename T>
 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<T *> (data);
   tag->Print (os);
 }
 template <typename T>
 uint32_t 
-Tag::DoGetSerializedSize (uint8_t data[Tags::SIZE])
+TagRegistry::DoGetSerializedSize (uint8_t data[Tags::SIZE])
 {
   T *tag = reinterpret_cast<T *> (data);
   return tag->GetSerializedSize ();
 }
 template <typename T>
 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<T *> (data);
   tag->Serialize (start);
 }
 template <typename T>
 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<T *> (data);
   return tag->Deserialize (start);
@@ -198,33 +208,25 @@
 
 template <typename T>
 uint32_t 
-Tag::GetUid (void)
-{
-  static uint32_t uid = AllocateUid<T> ();
-  return uid;
-}
-
-template <typename T>
-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<T>;
-  info.print = &Tag::DoPrint<T>;
-  info.getSerializedSize = &Tag::DoGetSerializedSize<T>;
-  info.serialize = &Tag::DoSerialize<T>;
-  info.deserialize = &Tag::DoDeserialize<T>;
+  info.uidString = uidString;
+  info.destruct = &TagRegistry::DoDestruct<T>;
+  info.print = &TagRegistry::DoPrint<T>;
+  info.getSerializedSize = &TagRegistry::DoGetSerializedSize<T>;
+  info.serialize = &TagRegistry::DoSerialize<T>;
+  info.deserialize = &TagRegistry::DoDeserialize<T>;
   vec->push_back (info);
   uint32_t uid = vec->size ();
   return uid;
@@ -238,12 +240,12 @@
   // 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<T> ());
+      NS_ASSERT (cur->m_id != T::GetUid ());
     }
   struct TagData *newStart = AllocData ();
   newStart->m_count = 1;
   newStart->m_next = 0;
-  newStart->m_id = Tag::GetUid<T> ();
+  newStart->m_id = T::GetUid ();
   void *buf = &newStart->m_data;
   new (buf) T (tag);
   newStart->m_next = m_next;
@@ -255,7 +257,7 @@
 Tags::Remove (T &tag)
 {
   NS_ASSERT (sizeof (T) <= Tags::SIZE);
-  return Remove (Tag::GetUid<T> ());
+  return Remove (T::GetUid ());
 }
 
 template <typename T>
@@ -265,7 +267,7 @@
   NS_ASSERT (sizeof (T) <= Tags::SIZE);
   for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) 
     {
-      if (cur->m_id == Tag::GetUid<T> ()) 
+      if (cur->m_id == T::GetUid ()) 
         {
           /* found tag */
           T *data = reinterpret_cast<T *> (&cur->m_data);
@@ -325,14 +327,14 @@
         }
       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;