/sparrowhawk/foundation/ESFFixedAllocator.h
C Header | 188 lines | 43 code | 23 blank | 122 comment | 0 complexity | df66579033d216ab254421f2e59dbf06 MD5 | raw file
1/** @file ESFFixedAllocator.h 2 * @brief A ESFAllocator implementation good for fixed-length allocations. 3 * 4 * Copyright (c) 2009 Yahoo! Inc. 5 * The copyrights embodied in the content of this file are licensed by Yahoo! Inc. 6 * under the BSD (revised) open source license. 7 * 8 * Derived from code that is Copyright (c) 2009 Joshua Blatt and offered under both 9 * BSD and Apache 2.0 licenses (http://sourceforge.net/projects/sparrowhawk/). 10 * 11 * $Author: blattj $ 12 * $Date: 2009/05/25 21:51:08 $ 13 * $Name: $ 14 * $Revision: 1.3 $ 15 */ 16 17#ifndef ESF_FIXED_ALLOCATOR_H 18#define ESF_FIXED_ALLOCATOR_H 19 20#ifndef ESF_CONFIG_H 21#include <ESFConfig.h> 22#endif 23 24#ifndef ESF_ALLOCATOR_H 25#include <ESFAllocator.h> 26#endif 27 28#ifndef ESF_TYPES_H 29#include <ESFTypes.h> 30#endif 31 32/** ESFFixedAllocator realizes the ESFAllocator interface with a simple fixed 33 * length allocator. The ESFFixedAllocator handles memory reservation and 34 * compaction very efficiently with the low overhead of 1 word per 35 * allocation because of its limitation that all allocations are always the 36 * same, fixed size. 37 * 38 * @ingroup allocator 39 */ 40class ESFFixedAllocator: public ESFAllocator { 41public: 42 43 /** Constructor. Creates the ESFFixedAllocator given the number of blocks 44 * and size of each block for its memory pool and also a source allocator 45 * from which it will request its memory pool. The amount of memory it 46 * will actually request from the source allocator is blocks * blockSize 47 * plus one word per block. 48 * 49 * @param blocks The number of blocks this allocator can allocate before 50 * exhausting its memory pool. 51 * @param blockSize The size in bytes of each block. 52 * @param source The allocator to use to allocate the memory pool. 53 */ 54 ESFFixedAllocator(int blocks, int blockSize, ESFAllocator *source); 55 56 /** Destructor. If initialized, the allocator will call the its destroy 57 * method. The destroy method may or may not return the allocator's 58 * managed memory to its source allocator. 59 */ 60 virtual ~ESFFixedAllocator(); 61 62 /** Allocate a word-aligned memory block of at least size bytes. 63 * 64 * @param size The minimum number of bytes to allocate. 65 * @return a word-aligned memory block of at least size bytes if 66 * successful, NULL otherwise. 67 */ 68 virtual void *allocate(ESFUWord size); 69 70 /** Deallocate a memory block allocated by this allocator or by its 71 * failover allocators. 72 * 73 * @param block The block to deallocate 74 * @return ESF_SUCCESS if the block was successfully deallocated, another 75 * error code otherwise. ESF_NOT_OWNER will be returned if the 76 * block was not allocated by this allocator. 77 */ 78 virtual ESFError deallocate(void *block); 79 80 /** Get the overhead in bytes of any additional control structures 81 * attached to an allocated block. This can be used to optimize 82 * allocation requests for some allocators. Power of two allocators, 83 * for example, will always round the size requested + the overhead up 84 * to the next power of two. If the caller always requests powers of 85 * two, then the allocator can waste a lot of memory. If, however, the 86 * caller requests a power of two minus the allocator overhead, then 87 * the allocator will return the optimal amount of memory. 88 * 89 * @return the allocator's overhead in bytes for each allocation. 90 */ 91 virtual ESFUWord getOverhead(); 92 93 /** Initialize this memory pool. 94 * 95 * @return ESF_SUCCESS if successful, another error code otherwise. 96 */ 97 virtual ESFError initialize(); 98 99 /** Destroy this allocator. The allocator will return all of the memory 100 * it manages to its source allocator and return itself to a state where 101 * initialize could be called again. All memory should be returned to 102 * the allocator before calling its destroy method. Some implementations 103 * may refuse to shutdown if they have outstanding allocations. 104 * 105 * @return ESF_SUCCESS if the allocator could destroy itself, another 106 * error code otherwise. ESF_IN_USE will be returned if the 107 * allocator has handed out memory that has not been returned. 108 * @see initialize. 109 */ 110 virtual ESFError destroy(); 111 112 /** Get the allocator's current initialization state. 113 * 114 * @return ESF_SUCCESS if the allocator is initialized, 115 * ESF_NOT_INITIALIZED if the allocator has not been initialized, 116 * another error code if an error occurred determining the 117 * allocator's current state. 118 * @see initialize. 119 */ 120 virtual ESFError isInitialized(); 121 122 /** Set another allocator to be used if this allocator cannot fulfill a 123 * allocate request. This failover allocator will be initialized lazily. 124 * If a failover allocator is not set, an allocator will simply return 125 * NULL if it cannot fulfill an allocation request. Destroying an 126 * allocator with registered failover allocators must also destroy those 127 * failover allocators if they have been initialized. Failover allocators 128 * may be chained. An allocator is responsible for determining whether 129 * a block of memory to be deallocated came from itself or from its 130 * failover allocator and take the appropriate action. Allocators should 131 * never be used as failover allocators for themselves to avoid 132 * infinite recursion. 133 * 134 * @param allocator The failover allocator. Set to NULL to clear an 135 * already registered failover allocator. 136 * @return ESF_SUCCESS if successful, another error code otherwise. 137 */ 138 virtual ESFError setFailoverAllocator(ESFAllocator *allocator); 139 140 /** Get the failover allocator used by this allocator. 141 * 142 * @param allocator The failover allocator to get (pointer to a pointer). 143 * This pointer will be set to NULL if no failover allocator exists. 144 * @return ESF_SUCCESS if successful, another error code otherwise. Note 145 * that if no failover allocator exists, ESF_SUCCESS will be returned 146 * and the allocator argument will be set to NULL. 147 * @see setFailoverAllocator 148 */ 149 virtual ESFError getFailoverAllocator(ESFAllocator **allocator); 150 151 /** Get the size of the blocks allocated by this allocator. 152 * 153 * @return The block size of this allocator. 154 */ 155 int getBlockSize(); 156 157 /** Placement new. 158 * 159 * @param size The size of the object. 160 * @param allocator The source of the object's memory. 161 * @return The new object or NULL of the memory allocation failed. 162 */ 163 inline void *operator new(size_t size, ESFAllocator *allocator) { 164 return allocator->allocate(size); 165 } 166 167private: 168 169 // Disabled 170 ESFFixedAllocator(const ESFFixedAllocator &); 171 ESFFixedAllocator &operator=(const ESFFixedAllocator &); 172 173 typedef struct AvailListElem { 174 AvailListElem *_next; 175 } AvailListElem; 176 177 AvailListElem *popAvailList(); 178 void pushAvailList(AvailListElem *elem); 179 180 AvailListElem *_availList; 181 void *_pool; 182 ESFAllocator *_sourceAllocator; 183 ESFAllocator *_failoverAllocator; 184 ESFUWord _blockSize; 185 int _blocks; 186}; 187 188#endif /* ! ESF_FIXED_ALLOCATOR_H */