implement constructor/destructor handling for tags

Mathieu Lacage 2007-04-19 10:28:51 +02:00
parent 363c64c04f
commit c0f7585f95
2 changed files with 89 additions and 16 deletions

View File

@ -28,24 +28,33 @@ TagRegistry::TagsData TagRegistry::m_registry;
void
TagRegistry::Record (std::string uuid, PrettyPrinter prettyPrinter)
TagRegistry::Record (std::string uuid, PrettyPrinter prettyPrinter, Destructor destructor)
{
NS_ASSERT (!m_sorted);
m_registry.push_back (make_pair (uuid, prettyPrinter));
struct TagInfoItem item;
item.uuid = uuid;
item.printer = prettyPrinter;
item.destructor = destructor;
m_registry.push_back (item);
}
bool
TagRegistry::CompareItem (const struct TagInfoItem &a, const struct TagInfoItem &b)
{
return a.uuid < b.uuid;
}
uint32_t
TagRegistry::LookupUid (std::string uuid)
{
if (!m_sorted)
{
std::sort (m_registry.begin (), m_registry.end ());
std::sort (m_registry.begin (), m_registry.end (), &TagRegistry::CompareItem);
m_sorted = true;
}
NS_ASSERT (m_sorted);
uint32_t uid = 1;
for (TagsDataCI i = m_registry.begin (); i != m_registry.end (); i++)
{
if (i->first == uuid)
if (i->uuid == uuid)
{
return uid;
}
@ -62,12 +71,23 @@ TagRegistry::PrettyPrint (uint32_t uid, uint8_t buf[Tags::SIZE], std::ostream &o
NS_ASSERT (uid > 0);
uint32_t index = uid - 1;
NS_ASSERT (m_registry.size () > index);
PrettyPrinter prettyPrinter = m_registry[index].second;
PrettyPrinter prettyPrinter = m_registry[index].printer;
if (prettyPrinter != 0)
{
prettyPrinter (buf, os);
}
}
void
TagRegistry::Destruct (uint32_t uid, uint8_t buf[Tags::SIZE])
{
NS_ASSERT (uid > 0);
uint32_t index = uid - 1;
NS_ASSERT (m_registry.size () > index);
Destructor destructor = m_registry[index].destructor;
NS_ASSERT (destructor != 0);
destructor (buf);
}
#ifdef USE_FREE_LIST
@ -212,6 +232,30 @@ struct myTagZ {
uint8_t z;
};
class MySmartTag
{
public:
MySmartTag ()
{
std::cout << "construct" << std::endl;
}
MySmartTag (const MySmartTag &o)
{
std::cout << "copy" << std::endl;
}
~MySmartTag ()
{
std::cout << "destruct" << std::endl;
}
MySmartTag &operator = (const MySmartTag &o)
{
std::cout << "assign" << std::endl;
return *this;
}
static void PrettyPrinterCb (const MySmartTag *a, std::ostream &os)
{}
};
static void
myTagAPrettyPrinterCb (struct myTagA const*a, std::ostream &os)
{
@ -243,6 +287,7 @@ static TagRegistration<struct myTagB> gMyTagBRegistration ("B", &myTagBPrettyPri
static TagRegistration<struct myTagC> gMyTagCRegistration ("C", &myTagCPrettyPrinterCb);
static TagRegistration<struct myTagZ> g_myTagZRegistration ("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ",
&myTagZPrettyPrinterCb);
static TagRegistration<MySmartTag> g_myTagSmartRegistration ("SmartTag", &MySmartTag::PrettyPrinterCb);
TagsTest::TagsTest ()
@ -313,6 +358,7 @@ TagsTest::RunTests (void)
ok = false;
}
struct myTagB oB;
oB.b = 1;
other.Peek (oB);
if (oB.b != 0xff)
{
@ -348,7 +394,7 @@ TagsTest::RunTests (void)
other = tags;
Tags another = other;
struct myTagC c;
c.c[0] = 0x66;
memset (c.c, 0x66, 16);
another.Add (c);
c.c[0] = 0;
another.Peek (c);
@ -369,6 +415,7 @@ TagsTest::RunTests (void)
struct myTagZ tagZ;
Tags testLastTag;
tagZ.z = 0;
testLastTag.Add (tagZ);
g_z = false;
testLastTag.PrettyPrint (std::cout);
@ -377,6 +424,14 @@ TagsTest::RunTests (void)
ok = false;
}
MySmartTag smartTag;
{
Tags tmp;
tmp.Add (smartTag);
tmp.Peek (smartTag);
tmp.Remove (smartTag);
}
return ok;
}

View File

@ -63,10 +63,10 @@ public:
};
private:
struct TagData {
uint8_t m_data[Tags::SIZE];
struct TagData *m_next;
uint32_t m_id;
uint32_t m_count;
uint8_t m_data[Tags::SIZE];
};
bool Remove (uint32_t id);
@ -99,6 +99,7 @@ public:
TagRegistration<T> (std::string uuid, void(*fn) (T const*, std::ostream &));
private:
static void PrettyPrinterCb (uint8_t *buf, std::ostream &os);
static void DestructorCb (uint8_t *buf);
static void(*m_prettyPrinter) (T const*, std::ostream &);
};
@ -117,16 +118,25 @@ namespace ns3 {
class TagRegistry {
public:
typedef void (*PrettyPrinter) (uint8_t [Tags::SIZE], std::ostream &);
static void Record (std::string uuid, PrettyPrinter prettyPrinter);
typedef void (*Destructor) (uint8_t [Tags::SIZE]);
static void Record (std::string uuid, PrettyPrinter prettyPrinter, Destructor destructor);
/**
* returns a numeric integer which uniquely identifies the input string.
* that integer cannot be zero which is a reserved value.
*/
static uint32_t LookupUid (std::string uuid);
static void PrettyPrint (uint32_t uid, uint8_t buf[Tags::SIZE], std::ostream &os);
static void Destruct (uint32_t uid, uint8_t buf[Tags::SIZE]);
private:
typedef std::vector<std::pair<std::string,PrettyPrinter> > TagsData;
typedef std::vector<std::pair<std::string,PrettyPrinter> >::const_iterator TagsDataCI;
struct TagInfoItem
{
std::string uuid;
PrettyPrinter printer;
Destructor destructor;
};
typedef std::vector<struct TagInfoItem> TagsData;
typedef std::vector<struct TagInfoItem>::const_iterator TagsDataCI;
static bool CompareItem (const struct TagInfoItem &a, const struct TagInfoItem &b);
static bool m_sorted;
static TagsData m_registry;
};
@ -181,7 +191,7 @@ TagRegistration<T>::TagRegistration (std::string uuid, void (*prettyPrinter) (T
{
NS_ASSERT (sizeof (T) <= Tags::SIZE);
m_prettyPrinter = prettyPrinter;
TagRegistry::Record (uuid, &TagRegistration<T>::PrettyPrinterCb);
TagRegistry::Record (uuid, &TagRegistration<T>::PrettyPrinterCb, &TagRegistration<T>::DestructorCb);
TypeUid<T>::Record (uuid);
}
template <typename T>
@ -192,7 +202,13 @@ TagRegistration<T>::PrettyPrinterCb (uint8_t *buf, std::ostream &os)
T *tag = reinterpret_cast<T *> (buf);
(*m_prettyPrinter) (tag, os);
}
template <typename T>
void
TagRegistration<T>::DestructorCb (uint8_t *buf)
{
T *tag = reinterpret_cast<T *> (buf);
tag->~T ();
}
template <typename T>
void (*TagRegistration<T>::m_prettyPrinter) (T const*, std::ostream &) = 0;
@ -204,7 +220,6 @@ void
Tags::Add (T const&tag)
{
NS_ASSERT (sizeof (T) <= Tags::SIZE);
uint8_t const*buf = reinterpret_cast<uint8_t const*> (&tag);
// ensure this id was not yet added
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
{
@ -214,7 +229,8 @@ Tags::Add (T const&tag)
newStart->m_count = 1;
newStart->m_next = 0;
newStart->m_id = TypeUid<T>::GetUid ();
memcpy (newStart->m_data, buf, sizeof (T));
void *buf = &newStart->m_data;
new (buf) T (tag);
newStart->m_next = m_next;
m_next = newStart;
}
@ -232,13 +248,13 @@ bool
Tags::Peek (T &tag) const
{
NS_ASSERT (sizeof (T) <= Tags::SIZE);
uint8_t *buf = reinterpret_cast<uint8_t *> (&tag);
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
{
if (cur->m_id == TypeUid<T>::GetUid ())
{
/* found tag */
memcpy (buf, cur->m_data, sizeof (T));
T *data = reinterpret_cast<T *> (&cur->m_data);
tag = T (*data);
return true;
}
}
@ -294,12 +310,14 @@ Tags::RemoveAll (void)
}
if (prev != 0)
{
TagRegistry::Destruct (prev->m_id, prev->m_data);
FreeData (prev);
}
prev = cur;
}
if (prev != 0)
{
TagRegistry::Destruct (prev->m_id, prev->m_data);
FreeData (prev);
}
m_next = 0;