diff --git a/src/common/tag-list.cc b/src/common/tag-list.cc index 430058741..df136c622 100644 --- a/src/common/tag-list.cc +++ b/src/common/tag-list.cc @@ -64,45 +64,68 @@ TagList::Iterator::GetOffsetStart (void) const TagList::TagList () - : m_buffer (0), - m_size (0) + : m_used (0), + m_data (0) {} TagList::TagList (const TagList &o) - : m_size (o.m_size) + : m_used (o.m_used), + m_data (o.m_data) { - m_buffer = new uint8_t [o.m_size] (); - memcpy (m_buffer, o.m_buffer, o.m_size); + if (m_data != 0) + { + m_data->count++; + } } TagList & TagList::operator = (const TagList &o) { - delete [] m_buffer; - m_buffer = new uint8_t [o.m_size] (); - memcpy (m_buffer, o.m_buffer, m_size); - m_size = o.m_size; + if (this == &o) + { + return *this; + } + + Deallocate (m_data); + m_data = o.m_data; + m_used = o.m_used; + if (m_data != 0) + { + m_data->count++; + } return *this; } TagList::~TagList () { - delete [] m_buffer; - m_buffer = 0; - m_size = 0; + Deallocate (m_data); + m_data = 0; + m_used = 0; } TagBuffer TagList::Add (TypeId tid, uint32_t bufferSize, uint32_t start, uint32_t end) { - uint32_t newSize = m_size + bufferSize + 4 + 4 + 4 + 4; - uint8_t *newBuffer = new uint8_t [newSize] (); - memcpy (newBuffer, m_buffer, m_size); - TagBuffer tag = TagBuffer (newBuffer + m_size, newBuffer + newSize); + uint32_t spaceNeeded = m_used + bufferSize + 4 + 4 + 4 + 4; + NS_ASSERT (m_used <= spaceNeeded); + if (m_data == 0) + { + m_data = Allocate (spaceNeeded); + m_used = 0; + } + else if (m_data->size < spaceNeeded || + (m_data->count != 1 && m_data->dirty != m_used)) + { + struct TagList::Data *newData = Allocate (spaceNeeded); + memcpy (&newData->data, &m_data->data, m_used); + Deallocate (m_data); + m_data = newData; + } + TagBuffer tag = TagBuffer (&m_data->data[m_used], + &m_data->data[spaceNeeded]); tag.WriteU32 (tid.GetUid ()); tag.WriteU32 (bufferSize); tag.WriteU32 (start); tag.WriteU32 (end); - delete [] m_buffer; - m_buffer = newBuffer; - m_size = newSize; + m_used = spaceNeeded; + m_data->dirty = m_used; return tag; } @@ -127,15 +150,22 @@ TagList::Remove (const Iterator &i) void TagList::RemoveAll (void) { - delete [] m_buffer; - m_buffer = 0; - m_size = 0; + Deallocate (m_data); + m_data = 0; + m_used = 0; } TagList::Iterator TagList::Begin (uint32_t offsetStart, uint32_t offsetEnd) const { - return Iterator (m_buffer, m_buffer + m_size, offsetStart, offsetEnd); + if (m_data == 0) + { + return Iterator (0, 0, offsetStart, offsetEnd); + } + else + { + return Iterator (m_data->data, &m_data->data[m_used], offsetStart, offsetEnd); + } } bool @@ -234,4 +264,32 @@ TagList::AddAtStart (int32_t adjustment, uint32_t prependOffset) *this = list; } + +struct TagList::Data * +TagList::Allocate (uint32_t size) +{ + uint8_t *buffer = new uint8_t [size + sizeof (struct TagList::Data) - 4]; + struct Data *data = (struct Data *)buffer; + data->count = 1; + data->size = size; + data->dirty = 0; + return data; +} + +void +TagList::Deallocate (struct Data *data) +{ + if (data == 0) + { + return; + } + data->count--; + if (data->count == 0) + { + uint8_t *buffer = (uint8_t *)data; + delete [] buffer; + } +} + + } // namespace ns3 diff --git a/src/common/tag-list.h b/src/common/tag-list.h index 31ffcddc0..6e6dc14af 100644 --- a/src/common/tag-list.h +++ b/src/common/tag-list.h @@ -58,8 +58,18 @@ public: private: bool IsDirtyAtEnd (uint32_t appendOffset); bool IsDirtyAtStart (uint32_t prependOffset); - uint8_t *m_buffer; - uint32_t m_size; + + struct Data { + uint32_t size; + uint32_t count; + uint32_t dirty; + uint8_t data[4]; + }; + struct TagList::Data *Allocate (uint32_t size); + void Deallocate (struct Data *data); + + uint16_t m_used; + struct Data *m_data; }; } // namespace ns3