/// /// Copyright © 2003-2008 JetBrains s.r.o. /// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder). /// #pragma unmanaged //#define CRT_ALLOCATIONS #include #include "DBIndexHeapObject.h" namespace DBIndex { HANDLE DBIndexHeapObject::_heap = NULL; int DBIndexHeapObject::_heapSize = 0; int DBIndexHeapObject::_objectsCount = 0; #ifndef CRT_ALLOCATIONS static __forceinline __int8 InterlockedExchange(volatile __int8* pTarget, __int8 c) { __asm { mov ebx, pTarget mov al, c lock xchg byte ptr [ebx], al } } #define STATIC_HEAP_SIZE 16384 #define STATIC_HEAP_LONG_MULTIPLIER 4 // each heap entry consists of 4 longs (32 bytes) static __int64 _staticHeap[STATIC_HEAP_SIZE * STATIC_HEAP_LONG_MULTIPLIER]; static __int8 _staticHeapStates[STATIC_HEAP_SIZE]; static int _staticHeapObjects; #endif void DBIndexHeapObject::CreateHeap() { #ifndef CRT_ALLOCATIONS if( _heap == NULL ) { _heap = ::HeapCreate( HEAP_GENERATE_EXCEPTIONS, 0, 0 ); ::ZeroMemory( _staticHeapStates, sizeof( _staticHeapStates ) ); _staticHeapObjects = 0; } #endif } void* DBIndexHeapObject::operator new( size_t size ) { #ifdef CRT_ALLOCATIONS return malloc( size ); #else CreateHeap(); int* result = 0; if( size <= sizeof( __int64 ) * STATIC_HEAP_LONG_MULTIPLIER && _staticHeapObjects < STATIC_HEAP_SIZE * 15 / 16 ) { int index = ( _objectsCount + _heapSize + _staticHeapObjects ) % STATIC_HEAP_SIZE; for( int i = 0; i < 16; ++i ) { if( DBIndex::InterlockedExchange( &_staticHeapStates[ index ], 1 ) == 0 ) { result = (int*) &_staticHeap[ index * STATIC_HEAP_LONG_MULTIPLIER ]; size = sizeof( __int64 ) * STATIC_HEAP_LONG_MULTIPLIER; ::InterlockedIncrement( (LPLONG)&_staticHeapObjects ); break; } index = ( 2717 * index + 3141 ) % STATIC_HEAP_SIZE; } } if( !result ) { size += 4; result = (int*)::HeapAlloc( _heap, 0, size ); *result = size; ++result; } ::InterlockedExchangeAdd( (LPLONG)&_heapSize, size ); ::InterlockedIncrement( (LPLONG)&_objectsCount ); return result; #endif } void DBIndexHeapObject::operator delete( void* object ) { #ifdef CRT_ALLOCATIONS free( object ); #else CreateHeap(); int* ptr = (int*)object; int size = -((int)sizeof( __int64 ) * STATIC_HEAP_LONG_MULTIPLIER); if( ptr >= (int*)_staticHeap && ptr <= (int*)&_staticHeap[ (STATIC_HEAP_SIZE - 1) * STATIC_HEAP_LONG_MULTIPLIER ] ) { int index = (((__int64*)ptr ) - (__int64*)_staticHeap ) / STATIC_HEAP_LONG_MULTIPLIER; DBIndex::InterlockedExchange( &_staticHeapStates[ index ], 0 ); ::InterlockedDecrement( (LPLONG)&_staticHeapObjects ); } else { --ptr; size = -*ptr; ::HeapFree( _heap, 0, ptr ); } ::InterlockedExchangeAdd( (LPLONG)&_heapSize, size ); ::InterlockedDecrement( (LPLONG)&_objectsCount ); #endif } }