// CObject local new operator to mark allocation in heap void* CObject::operator new(size_t size) { _ASSERT(size >= sizeof(CObject)); size = max(size, sizeof(CObject) + sizeof(TCounter)); #ifdef USE_SINGLE_ALLOC void* ptr = single_alloc(size); sx_FillNewMemory(ptr, size); //static_cast<CObject*>(ptr)->m_Counter.Set(0); return ptr; #else void* ptr = ::operator new(size); #if USE_TLS_PTR // just remember pointer in TLS sx_PushLastNewPtr(ptr, eMagicCounterNew); #else// !USE_TLS_PTR #if USE_HEAPOBJ_LIST {{ CFastMutexGuard LOCK(sm_ObjectMutex); s_heap_obj->push_front(ptr); }} #else// !USE_HEAPOBJ_LIST sx_FillNewMemory(ptr, size); # if USE_COMPLEX_MASK GetSecondCounter(static_cast<CObject*>(ptr))->Set(eMagicCounterNew); # endif// USE_COMPLEX_MASK #endif// USE_HEAPOBJ_LIST static_cast<CObject*>(ptr)->m_Counter.Set(eMagicCounterNew); #endif// USE_TLS_PTR return ptr; #endif }
// CObject new operator from memory pool void* CObject::operator new(size_t size, CObjectMemoryPool* memory_pool) { _ASSERT(size >= sizeof(CObject)); if ( !memory_pool ) { return operator new(size); } void* ptr = memory_pool->Allocate(size); if ( !ptr ) { return operator new(size); } #if USE_TLS_PTR // just remember pointer in TLS sx_PushLastNewPtr(ptr, eMagicCounterPoolNew); #else// !USE_TLS_PTR # if USE_COMPLEX_MASK GetSecondCounter(static_cast<CObject*>(ptr))->Set(eMagicCounterPoolNew); # endif// USE_COMPLEX_MASK static_cast<CObject*>(ptr)->m_Counter.Set(eMagicCounterPoolNew); #endif// USE_TLS_PTR return ptr; }
void CTestTlsObjectApp::RunTest(void) { const size_t OBJECT_SIZE = sizeof(CObjectWithNew); for ( int t = 0; t < 1; ++t ) { // prealloc { size_t size = (OBJECT_SIZE+16)*COUNT; void* p = ::operator new(size); memset(p, 1, size); ::operator delete(p); } { const size_t COUNT2 = COUNT*2; void** p = new void*[COUNT2]; for ( size_t i = 0; i < COUNT2; ++i ) { add_alloc(1); add_step(); p[i] = ::operator new(OBJECT_SIZE); } for ( size_t i = 0; i < COUNT2; ++i ) { add_alloc(-1); add_step(); ::operator delete(p[i]); } delete[] p; } { const size_t COUNT2 = COUNT*2; int** p = new int*[COUNT2]; for ( size_t i = 0; i < COUNT2; ++i ) { add_alloc(1); add_step(); p[i] = new int(int(i)); } for ( size_t i = 0; i < COUNT2; ++i ) { add_alloc(-1); add_step(); delete p[i]; } delete[] p; } } //return; CStopWatch sw; check_cnts(); for ( int t = 0; t < 1; ++t ) { void** ptr = new void*[COUNT]; sw.Start(); for ( size_t i = 0; i < COUNT; ++i ) { add_alloc(1); add_step(); ptr[i] = ::operator new(OBJECT_SIZE); } double t1 = sw.Elapsed(); sw.Start(); for ( size_t i = 0; i < COUNT; ++i ) { add_alloc(-1); add_step(); ::operator delete(ptr[i]); } double t2 = sw.Elapsed(); message("plain malloc", "create", t1, "delete", t2, COUNT); delete[] ptr; } check_cnts(); { sw.Start(); int* ptr = new int; sx_PushLastNewPtr(ptr, 2); double t1 = sw.Elapsed(); sw.Start(); _VERIFY(sx_PopLastNewPtr(ptr)); delete ptr; double t2 = sw.Elapsed(); message("tls", "set", t1, "get", t2, COUNT); } check_cnts(); { CObjectWithNew** ptr = new CObjectWithNew*[COUNT]; for ( size_t i = 0; i < COUNT; ++i ) { ptr[i] = 0; } sw.Start(); s_CurrentStep = "new CObjectWithNew"; s_CurrentInHeap = true; for ( size_t i = 0; i < COUNT; ++i ) { add_step(); ptr[i] = new CObjectWithNew; } s_CurrentInHeap = false; double t1 = sw.Elapsed(); check_cnts(COUNT); for ( size_t i = 0; i < COUNT; ++i ) { _ASSERT(ptr[i]->IsInHeap()); } sw.Start(); for ( size_t i = 0; i < COUNT; ++i ) { add_step(); CObjectWithNew::Delete(ptr[i]); } double t2 = sw.Elapsed(); message("new CObjectWithNew", "create", t1, "delete", t2, COUNT); delete[] ptr; } check_cnts(); { CObjectWithTLS** ptr = new CObjectWithTLS*[COUNT]; sw.Start(); s_CurrentStep = "new CObjectWithTLS"; s_CurrentInHeap = true; for ( size_t i = 0; i < COUNT; ++i ) { add_step(); try { switch ( rand()%3 ) { case 0: ptr[i] = new CObjectWithTLS; break; case 1: ptr[i] = new CObjectWithTLS2; break; case 2: ptr[i] = new CObjectWithTLS3; break; } } catch ( exception& ) { ptr[i] = 0; } _ASSERT(!sx_HaveLastNewPtr()); _ASSERT(!ptr[i] || ptr[i]->IsInHeap()); } s_CurrentInHeap = false; double t1 = sw.Elapsed(); check_cnts(COUNT); sw.Start(); for ( size_t i = 0; i < COUNT; ++i ) { add_step(); CObjectWithTLS::Delete(ptr[i]); } double t2 = sw.Elapsed(); message("new CObjectWithTLS", "create", t1, "delete", t2, COUNT); delete[] ptr; } check_cnts(); { CRef<CObjectWithRef>* ptr = new CRef<CObjectWithRef>[COUNT]; sw.Start(); s_CurrentStep = "new CObjectWithRef"; for ( size_t i = 0; i < COUNT; ++i ) { add_step(); try { switch ( rand()%2 ) { case 0: ptr[i] = new CObjectWithRef; break; case 1: ptr[i] = new CObjectWithRef2; break; } } catch ( exception& ) { ptr[i] = 0; } _ASSERT(!sx_HaveLastNewPtr()); _ASSERT(!ptr[i] || ptr[i]->CanBeDeleted()); } double t1 = sw.Elapsed(); check_cnts(COUNT); sw.Start(); for ( size_t i = 0; i < COUNT; ++i ) { add_step(); ptr[i].Reset(); } double t2 = sw.Elapsed(); message("new CObjectWithRef", "create", t1, "delete", t2, COUNT); delete[] ptr; } check_cnts(); { CObjectWithNew** ptr = new CObjectWithNew*[COUNT]; for ( size_t i = 0; i < COUNT; ++i ) { ptr[i] = 0; } sw.Start(); s_CurrentStep = "new CObjectWithNew()"; s_CurrentInHeap = true; for ( size_t i = 0; i < COUNT; ++i ) { add_step(); ptr[i] = new CObjectWithNew(); } s_CurrentInHeap = false; double t1 = sw.Elapsed(); check_cnts(COUNT); for ( size_t i = 0; i < COUNT; ++i ) { _ASSERT(ptr[i]->IsInHeap()); } sw.Start(); for ( size_t i = 0; i < COUNT; ++i ) { add_step(); CObjectWithNew::Delete(ptr[i]); } double t2 = sw.Elapsed(); message("new CObjectWithNew()", "create", t1, "delete", t2, COUNT); delete[] ptr; } check_cnts(); { CObjectWithTLS** ptr = new CObjectWithTLS*[COUNT]; sw.Start(); s_CurrentStep = "new CObjectWithTLS()"; s_CurrentInHeap = true; for ( size_t i = 0; i < COUNT; ++i ) { add_step(); try { switch ( rand()%4 ) { case 0: ptr[i] = new CObjectWithTLS(); break; case 1: ptr[i] = new CObjectWithTLS2(); break; case 2: ptr[i] = new CObjectWithTLS3(); break; case 3: ptr[i] = new CObjectWithTLS3(RecursiveNewTLS(rand()%4)); break; } } catch ( exception& ) { ptr[i] = 0; } _ASSERT(!sx_HaveLastNewPtr()); _ASSERT(!ptr[i] || ptr[i]->IsInHeap()); } s_CurrentInHeap = false; double t1 = sw.Elapsed(); check_cnts(COUNT); sw.Start(); for ( size_t i = 0; i < COUNT; ++i ) { add_step(); CObjectWithTLS::Delete(ptr[i]); } double t2 = sw.Elapsed(); message("new CObjectWithTLS()", "create", t1, "delete", t2, COUNT); delete[] ptr; } check_cnts(); { CRef<CObjectWithRef>* ptr = new CRef<CObjectWithRef>[COUNT]; sw.Start(); s_CurrentStep = "new CObjectWithRef()"; for ( size_t i = 0; i < COUNT; ++i ) { add_step(); try { size_t j = rand()%COUNT; switch ( rand()%4 ) { case 0: ptr[j] = new CObjectWithRef(); break; case 1: ptr[j] = new CObjectWithRef(RecursiveNewRef(rand()%4)); break; case 2: ptr[j] = new CObjectWithRef2(); break; case 3: ptr[j] = new CObjectWithRef2(RecursiveNewRef(rand()%4)); break; } } catch ( exception& ) { ptr[i] = 0; } _ASSERT(!sx_HaveLastNewPtr()); _ASSERT(!ptr[i] || ptr[i]->CanBeDeleted()); } double t1 = sw.Elapsed(); check_cnts(COUNT); sw.Start(); for ( size_t i = 0; i < COUNT; ++i ) { add_step(); ptr[i] = 0; } double t2 = sw.Elapsed(); message("new CObjectWithRef()", "create", t1, "delete", t2, COUNT); delete[] ptr; } check_cnts(); { sw.Start(); s_CurrentStep = "CObjectWithNew[]"; CArray<CObjectWithNew, COUNT>* arr = new CArray<CObjectWithNew, COUNT>; double t1 = sw.Elapsed(); check_cnts(COUNT, COUNT); for ( size_t i = 0; i < COUNT; ++i ) { _ASSERT(!arr->m_Array[i].IsInHeap()); } sw.Start(); delete arr; double t2 = sw.Elapsed(); message("static CObjectWithNew", "create", t1, "delete", t2, COUNT); } check_cnts(); { sw.Start(); s_CurrentStep = "CObjectWithTLS[]"; CArray<CObjectWithTLS, COUNT, false>* arr = new CArray<CObjectWithTLS, COUNT, false>; double t1 = sw.Elapsed(); check_cnts(COUNT, COUNT); for ( size_t i = 0; i < COUNT; ++i ) { _ASSERT(!arr->m_Array[i].IsInHeap()); } sw.Start(); delete arr; double t2 = sw.Elapsed(); message("static CObjectWithTLS", "create", t1, "delete", t2, COUNT); } check_cnts(); { sw.Start(); s_CurrentStep = "CObjectWithRef[]"; CArray<CObjectWithRef, COUNT, false>* arr = new CArray<CObjectWithRef, COUNT, false>; double t1 = sw.Elapsed(); check_cnts(COUNT, COUNT); for ( size_t i = 0; i < COUNT; ++i ) { _ASSERT(!arr->m_Array[i].CanBeDeleted()); } sw.Start(); delete arr; double t2 = sw.Elapsed(); message("static CObjectWithRef", "create", t1, "delete", t2, COUNT); } check_cnts(); }
static void RegisterNew(CObjectWithTLS* ptr) { sx_PushLastNewPtr(ptr, 2); }