/*- * Copyright 2007 Guram Dukashvili * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ //--------------------------------------------------------------------------- #ifndef _memmgr_H_ #define _memmgr_H_ //--------------------------------------------------------------------------- namespace ksys { //--------------------------------------------------------------------------- void initialize(int,char **); void cleanup(); //--------------------------------------------------------------------------- ///////////////////////////////////////////////////////////////////////////// // Memory manager ///////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //--------------------------------------------------------------------------- class MemoryManager { friend void initialize(int,char **); friend void cleanup(); public: ~MemoryManager(); MemoryManager(); static MemoryManager & globalMemoryManager(); MemoryManager & clear(); void * sysalloc(uintptr_t size,bool lock,bool & locked,bool noThrow); MemoryManager & sysfree(void * memory,uintptr_t size,bool locked,bool noThrow); void * malloc(uintptr_t size,bool lock,bool & locked); void * realloc(void * ptr,uintptr_t size,bool lock,bool & locked); void * malloc(uintptr_t size){ bool locked; return malloc(size,lock_,locked); } void * realloc(void * ptr,uintptr_t size){ bool locked; return realloc(ptr,size,lock_,locked); } void free(void * ptr); const uintptr_t & clusterSize() const { return clusterSize_; } const uintptr_t & allocatedSystemMemory() const { return allocatedSystemMemory_; } const uintptr_t & allocatedMemory() const { return allocatedMemory_; } const bool & lock() const { return lock_; } MemoryManager & lock(bool a){ lock_ = a; return *this; } protected: class Clusters; class Cluster { public: Cluster(Clusters * cs = NULL,void * memory = NULL) : cs_(cs), memory_((uint8_t *) memory), size_(0), fsize_(0), bsize_(0), index_(~uintptr_t(0)), count_(0), head_(NULL), next_(NULL), locked_(false) {} static RBTreeNode & treeO2N(const Cluster & object,uintptr_t *){ return object.treeNode_; } static Cluster & treeN2O(const RBTreeNode & node,uintptr_t *){ Cluster * p = NULL; return node.object(p->treeNode_); } static intptr_t treeCO(const Cluster & a0,const Cluster & a1,uintptr_t *){ return a0.memory_ < a1.memory_ ? -1 : a0.memory_ + a0.fsize_ >= a1.memory_ + a1.fsize_ ? 1 : 0; } mutable RBTreeNode treeNode_; static EmbeddedListNode & listNode(const Cluster & object){ return object.listNode_; } static Cluster & listObject(const EmbeddedListNode & node,Cluster * p = NULL){ return node.object(p->listNode_); } mutable EmbeddedListNode listNode_; Cluster & initialize(){ index_ = 0; uintptr_t i, j = size_ / bsize_; if( bsize_ == 1 ){ if( j > 256 ) j = 256; for( i = 0; i < j; i++ ) *(uint8_t *) (memory_ + i) = uint8_t(i + 1); } else if( bsize_ == 2 ){ if( j > 65536 ) j = 65536; for( i = 0; i < j; i++ ) *(uint16_t *) (memory_ + i * 2) = uint16_t(i + 1); } else if( bsize_ == 3 ){ if( j > 16777216 ) j = 16777216; for( i = 0; i < j; i++ ) *(uint32_t *) (memory_ + i * 3) = uint32_t(i + 1); } else if( bsize_ > ~uint32_t(0) - 1 ){ for( i = 0; i < j; i++ ) *(uintptr_t *) (memory_ + bsize_ * i) = i + 1; } else { for( i = 0; i < j; i++ ) *(uint32_t *) (memory_ + bsize_ * i) = uint32_t(i + 1); } count_ = j; return *this; } Clusters * cs_; uint8_t * memory_; uintptr_t size_; // size of allocated memory uintptr_t fsize_; // size of searching memory block uintptr_t bsize_; // size of allocating memory block uintptr_t index_; // first in free list block index uintptr_t count_; // count of allocated blocks Cluster * head_; // head of allocated memory for small blocks (with size < 4) Cluster * next_; // next memory for small blocks (with size < 4) bool locked_; }; class SizeDescriptor; class Clusters { public: Clusters(SizeDescriptor * sd = NULL,uintptr_t size = 0) : sd_(sd), size_(size) {} static EmbeddedListNode & listNode(const Clusters & object){ return object.listNode_; } static Clusters & listObject(const EmbeddedListNode & node,Clusters * p = NULL){ return node.object(p->listNode_); } mutable EmbeddedListNode listNode_; EmbeddedList free_; // free slots EmbeddedList lru_; // for fast allocating uintptr_t count() const { return (size_ - sizeof(Clusters) + sizeof(Cluster)) / sizeof(Cluster); } SizeDescriptor * sd_; uintptr_t size_; // size of allocated memory bool locked_; Cluster clusters_[1]; }; class SizeDescriptors; class SizeDescriptor { public: SizeDescriptor(SizeDescriptors * sds = NULL,uintptr_t size = 0) : sds_(sds), size_(size) {} SizeDescriptors * sds_; uintptr_t size_; // size of allocating memory block EmbeddedList clusters_; }; class SizeDescriptors { public: SizeDescriptors() {} static EmbeddedListNode & listNode(const SizeDescriptors & object){ return object.listNode_; } static SizeDescriptors & listObject(const EmbeddedListNode & node,SizeDescriptors * p = NULL){ return node.object(p->listNode_); } mutable EmbeddedListNode listNode_; uintptr_t count() const { return (size_ - sizeof(SizeDescriptors) + sizeof(SizeDescriptor)) / sizeof(SizeDescriptor); } uintptr_t size_; // size of allocated memory uintptr_t count_; bool locked_; SizeDescriptor sizes_[1]; }; EmbeddedList sizes_; typedef RBTree< Cluster, uintptr_t, Cluster::treeO2N, Cluster::treeN2O, Cluster::treeCO > ClustersTree; ClustersTree clustersTree_; uintptr_t clusterSize_; uintptr_t align_; uintptr_t allocatedSystemMemory_; uintptr_t allocatedMemory_; #if defined(__WIN32__) || defined(__WIN64__) DWORD flags_; #endif FiberInterlockedMutex mutex_; bool lock_; bool interlocked_; volatile ilock_t initMutex_; // used only in global volatile ilock_t initCount_; // used only in global EmbeddedListNode * findSDSNode(uintptr_t size,uintptr_t & fsize,uintptr_t & lsize); EmbeddedListNode * findCSNode(SizeDescriptor * sd,uintptr_t size,bool & ffc); private: MemoryManager(const MemoryManager &); void operator = (const MemoryManager &); static uint8_t globalMemoryManagerHolder_[]; static void initialize(); static void cleanup(); }; //--------------------------------------------------------------------------- inline MemoryManager & MemoryManager::globalMemoryManager() { return *reinterpret_cast(globalMemoryManagerHolder_); } //--------------------------------------------------------------------------- void heapBenchmark(); //--------------------------------------------------------------------------- } // namespace ksys //--------------------------------------------------------------------------- #endif /* _memmgr_H_ */ //---------------------------------------------------------------------------