From c0f7585f957b7367676c87945d4da9dfbf725e10 Mon Sep 17 00:00:00 2001 From: Mathieu Lacage Date: Thu, 19 Apr 2007 10:28:51 +0200 Subject: [PATCH] implement constructor/destructor handling for tags --- src/common/tags.cc | 67 +++++++++++++++++++++++++++++++++++++++++----- src/common/tags.h | 38 +++++++++++++++++++------- 2 files changed, 89 insertions(+), 16 deletions(-) diff --git a/src/common/tags.cc b/src/common/tags.cc index 044d96e65..b508ad074 100644 --- a/src/common/tags.cc +++ b/src/common/tags.cc @@ -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 gMyTagBRegistration ("B", &myTagBPrettyPri static TagRegistration gMyTagCRegistration ("C", &myTagCPrettyPrinterCb); static TagRegistration g_myTagZRegistration ("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ", &myTagZPrettyPrinterCb); +static TagRegistration 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; } diff --git a/src/common/tags.h b/src/common/tags.h index fd0bfacbf..fadbe1c1f 100644 --- a/src/common/tags.h +++ b/src/common/tags.h @@ -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 (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 > TagsData; - typedef std::vector >::const_iterator TagsDataCI; + struct TagInfoItem + { + std::string uuid; + PrettyPrinter printer; + Destructor destructor; + }; + typedef std::vector TagsData; + typedef std::vector::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::TagRegistration (std::string uuid, void (*prettyPrinter) (T { NS_ASSERT (sizeof (T) <= Tags::SIZE); m_prettyPrinter = prettyPrinter; - TagRegistry::Record (uuid, &TagRegistration::PrettyPrinterCb); + TagRegistry::Record (uuid, &TagRegistration::PrettyPrinterCb, &TagRegistration::DestructorCb); TypeUid::Record (uuid); } template @@ -192,7 +202,13 @@ TagRegistration::PrettyPrinterCb (uint8_t *buf, std::ostream &os) T *tag = reinterpret_cast (buf); (*m_prettyPrinter) (tag, os); } - +template +void +TagRegistration::DestructorCb (uint8_t *buf) +{ + T *tag = reinterpret_cast (buf); + tag->~T (); +} template void (*TagRegistration::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 (&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::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 (&tag); for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) { if (cur->m_id == TypeUid::GetUid ()) { /* found tag */ - memcpy (buf, cur->m_data, sizeof (T)); + T *data = reinterpret_cast (&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;