update the Tag API to match the Header/Trailer API

This commit is contained in:
Mathieu Lacage
2007-08-04 17:14:54 +02:00
parent 797d537cb8
commit 8e1489d85b
3 changed files with 74 additions and 70 deletions

View File

@@ -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> ("MyTag.unique.prefix");
* static uint32_t uid = TagRegistry::Register<MyTag> ("MyTag.unique.prefix");
* return uid;
* }
* \endcode

View File

@@ -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> ("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> ("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> ("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> ("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> ("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> ("MySmartTag.test.nsnam.org"); return uid;}
MySmartTag ()
{
//std::cout << "construct" << std::endl;

View File

@@ -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 @@ 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 <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 @@ private:
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 @@ Tag::DoDeserialize (uint8_t data[Tags::SIZE], Buffer::Iterator start)
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 @@ 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<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 @@ bool
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 @@ 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<T> ())
if (cur->m_id == T::GetUid ())
{
/* found tag */
T *data = reinterpret_cast<T *> (&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;