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