Listing 1: Definition of Slot<> and Index<> classes
// Listing 1: Definition of Slot<> and Index<> classes template <typename C, size_t CCH> struct Slot { Slot(Slot *next) : next(next) {} ~Slot() { delete next; } // Use the process heap because: // // 1. Don't want to worry about thread-specificity, since // deallocation will occur in a different thread to allocation // 2. Don't want to worry about linkage to any specific CRT or // other library // 3. Doesn't matter how fast it is // 4. Want it to be *highly* unlikely that allocation will fail, // which is indeed pretty unheard of when using the Win32 // process heap. // 5. Want a C++-exception free solution, so use the Win32-system // out-of-memory exception, and not have to worry about any // linkage pains. void *operator new(size_t cb) { return ::HeapAlloc(::GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, cb); } void operator delete(void *pv) { ::HeapFree(::GetProcessHeap(), 0, pv); } C buff[CCH]; Slot *next; }; template <typename C, size_t CCH> struct Index { typedef Slot<C, CCH> Slot; Index() : m_index(::TlsAlloc()) { // Use Win32 exception because: // // 1. Process cannot recover from this error in any // meaningful way // 2. Do not want to couple to C++ exception-handling // and there is no graceful way to allow this to be // parameterisable. (May allow a pp-discriminated // mechanism in next version.) if(TLS_OUT_OF_INDEXES == m_index) { ::RaiseException(STATUS_NO_MEMORY, EXCEPTION_NONCONTINUABLE, 0, 0); } } ~Index() { // Walk the slot list and free. This can be as slow as // you like, since performance is not important here delete m_top; // Now release the index ::TlsFree(m_index); } Slot *GetSlot() { // NOTE: This does not need to be thread-safe return reinterpret_cast<Slot*>(::TlsGetValue(m_index)); } Slot *AllocSlot() { Slot *next; { // Protect linked-list manipulation lock_scope<thread_mutex> lock(m_mx); m_top = next = new Slot(m_top); } ::TlsSetValue(m_index, next); return next; } private: ws_dword_t const m_index; Slot *m_top; thread_mutex m_mx; };