diff --git a/src/common/buffer.cc b/src/common/buffer.cc index 2f1e61838..adb2804b4 100644 --- a/src/common/buffer.cc +++ b/src/common/buffer.cc @@ -75,11 +75,7 @@ struct BufferData { */ uint8_t m_data[1]; }; -class BufferDataList : public std::vector -{ -public: - ~BufferDataList (); -}; +typedef std::vector BufferDataList; static struct BufferData *BufferAllocate (uint32_t reqSize); @@ -91,39 +87,69 @@ static void BufferDeallocate (struct BufferData *data); namespace ns3 { #ifdef BUFFER_HEURISTICS +/* The following macros are pretty evil but they are needed to allow us to + * keep track of 3 possible states for the g_freeList variable: + * - uninitialized means that no one has created a buffer yet + * so no one has created the associated free list (it is created + * on-demand when the first buffer is created) + * - initialized means that the free list exists and is valid + * - destroyed means that the static destructors of this compilation unit + * have run so, the free list has been cleared from its content + * The key is that in destroyed state, we are careful not re-create it + * which is a typical weakness of lazy evaluation schemes which use + * '0' as a special value to indicate both un-initialized and destroyed. + * Note that it is important to use '0' as the marker for un-initialized state + * because the variable holding this state information is initialized to zero + * which the compiler assigns to zero-memory which is initialized to _zero_ + * before the constructors run so this ensures perfect handling of crazy + * constructor orderings. + */ +#define MAGIC_DESTROYED (~(long) 0) +#define IS_UNINITIALIZED(x) (x == (BufferDataList*)0) +#define IS_DESTROYED(x) (x == (BufferDataList*)MAGIC_DESTROYED) +#define IS_INITIALIZED(x) (!IS_UNINITIALIZED(x) && !IS_DESTROYED(x)) +#define DESTROYED ((BufferDataList*)MAGIC_DESTROYED) +#define UNINITIALIZED ((BufferDataList*)0) static uint32_t g_recommendedStart = 0; static uint64_t g_nAddNoRealloc = 0; static uint64_t g_nAddRealloc = 0; -static BufferDataList g_freeList; +static BufferDataList *g_freeList = 0; static uint32_t g_maxSize = 0; static uint64_t g_nAllocs = 0; static uint64_t g_nCreates = 0; #endif /* BUFFER_HEURISTICS */ -BufferDataList::~BufferDataList () -{ +static struct LocalStaticDestructor { + LocalStaticDestructor(void) + { #ifdef PRINT_STATS #ifdef BUFFER_HEURISTICS - double efficiency; - efficiency = g_nAllocs; - efficiency /= g_nCreates; - std::cout <<"buffer free list efficiency="<