// // ******************************************************************** // * DISCLAIMER * // * * // * The following disclaimer summarizes all the specific disclaimers * // * of contributors to this software. The specific disclaimers,which * // * govern, are listed with their locations in: * // * http://cern.ch/geant4/license * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. * // * * // * This code implementation is the intellectual property of the * // * GEANT4 collaboration. * // * By copying, distributing or modifying the Program (or any work * // * based on the Program) you indicate your acceptance of this * // * statement, and all its terms. * // ******************************************************************** // // // $Id: G4Allocator.hh,v 1.11 2002/06/21 16:59:56 gcosmo Exp $ // GEANT4 tag $Name: geant4-05-00 $ // // // ------------------------------------------------------------ // GEANT 4 class header file // // Class Description: // // A class for fast allocation of objects to the heap through paging // mechanism. It's meant to be used by associating it to the object to // be allocated and defining for it new and delete operators via // MallocSingle() and FreeSingle() methods. // ---------------- G4Allocator ---------------- // by Tim Bell, September 1995 // ------------------------------------------------------------ #ifndef G4Allocator_h #define G4Allocator_h 1 #include #include #include "G4AllocatorPage.hh" template class G4Allocator { public: // with description G4Allocator(); ~G4Allocator(); // Constructor & destructor inline Type* MallocSingle(); inline void FreeSingle(Type* anElement); // Malloc and Free methods to be used when overloading // new and delete operators in the client object private: void AddNewPage(); Type* AddNewElement(); private: enum { Allocated = 0x47416C, Deleted = 0xB8BE93 }; G4AllocatorPage * fPages; G4AllocatorUnit * fFreeList; size_t fUnitSize, fPageSize; }; // ------------------------------------------------------------ // Inline implementation // ------------------------------------------------------------ // ************************************************************ // G4Allocator constructor // ************************************************************ // template G4Allocator::G4Allocator() { fPages = 0; fFreeList = 0; fUnitSize = sizeof(G4AllocatorUnit); fPageSize = ( (fUnitSize < 512) ? 1024 : (fUnitSize*10) ); AddNewPage(); return; } // ************************************************************ // G4Allocator destructor // ************************************************************ // template G4Allocator::~G4Allocator() { G4AllocatorPage * aPage; G4AllocatorPage * aNextPage; aPage = fPages; while (aPage != 0) { aNextPage = aPage->fNext; free(aPage->fUnits); delete aPage; aPage = aNextPage; } fPages = 0; fFreeList = 0; return; } // ************************************************************ // MallocSingle // ************************************************************ // template Type* G4Allocator::MallocSingle() { Type * anElement; if (fFreeList != 0) { fFreeList->deleted = Allocated; anElement = &fFreeList->fElement; fFreeList = fFreeList->fNext; } else anElement = AddNewElement(); return anElement; } // ************************************************************ // FreeSingle // ************************************************************ // template void G4Allocator::FreeSingle(Type* anElement) { G4AllocatorUnit * fUnit; // The gcc-3.1 compiler will complain and not correctly handle offsets // computed from non-POD types. Pointers to member data should be used // instead. This advanced C++ feature seems not to work on earlier // versions of the same compiler. // #if (GNU_GCC==1) && (__GNUC__==3) && (__GNUC_MINOR__>0) Type G4AllocatorUnit::*pOffset = &G4AllocatorUnit::fElement; fUnit = (G4AllocatorUnit *) ((char *)anElement - size_t(pOffset)); #else fUnit = (G4AllocatorUnit *) ((char *) anElement - offsetof(G4AllocatorUnit, fElement)); #endif if (fUnit->deleted == Allocated) { fUnit->deleted = Deleted; fUnit->fNext = fFreeList; fFreeList = fUnit; } } // ************************************************************ // AddNewPage // ************************************************************ // template void G4Allocator::AddNewPage() { G4AllocatorPage * aPage; register G4int unit_no; aPage = new G4AllocatorPage; aPage->fNext = fPages; aPage->fUnits = (G4AllocatorUnit *) malloc(fPageSize); fPages = aPage; for (unit_no = 0; unit_no < G4int(fPageSize/fUnitSize - 1); ++unit_no) { aPage->fUnits[unit_no].fNext = &aPage->fUnits[unit_no + 1]; } aPage->fUnits[unit_no].fNext = fFreeList; fFreeList = &aPage->fUnits[0]; } // ************************************************************ // AddNewElement // ************************************************************ // template Type* G4Allocator::AddNewElement() { Type* anElement; AddNewPage(); fFreeList->deleted = Allocated; anElement = &fFreeList->fElement; fFreeList=fFreeList->fNext; return anElement; } #endif