00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "base/memory.hpp"
00029
00030 BEGIN_TERIMBER_NAMESPACE
00031 #pragma pack(4)
00032
00034 byte_allocator::byte_allocator(size_t capacity) :
00035 _capacity(capacity > os_def_size ? capacity : os_def_size), _count(0), _free_pos(0), _start_chunk(0), _using_chunk(0)
00036 {
00037 }
00038
00039 byte_allocator::~byte_allocator()
00040 {
00041 clear_all();
00042 }
00043
00044 void*
00045 byte_allocator::new_chunk(size_t size)
00046 {
00047 size_t new_size = size > _capacity ? size : _capacity;
00048
00049
00050
00051 mem_chunk* chunk = (mem_chunk*)::malloc(sizeof(mem_chunk) - sizeof(void*) + new_size);
00052
00053 if (!chunk)
00054 return 0;
00055
00056
00057 chunk->_chunk_size = new_size;
00058 chunk->_next_chunk = 0;
00059
00060 if (_start_chunk)
00061 {
00062 _using_chunk->_next_chunk = chunk;
00063 _using_chunk = chunk;
00064 }
00065 else
00066 _start_chunk = _using_chunk = chunk;
00067
00068
00069 ++_count;
00070
00071
00072 _free_pos = chunk->_mem + size;
00073
00074 return chunk->_mem;
00075 }
00076
00077 void*
00078 byte_allocator::next_chunk(size_t size)
00079 {
00080 mem_chunk* chunk = _using_chunk ? _using_chunk->_next_chunk : 0;
00081 unsigned char* pos = chunk ? chunk->_mem : 0;
00082 while (chunk)
00083 {
00084
00085 _using_chunk = chunk;
00086
00087 if (chunk->_chunk_size - (pos - chunk->_mem) >= size)
00088 { _free_pos = pos + size; return pos; }
00089
00090 chunk = chunk->_next_chunk;
00091
00092 pos = chunk ? chunk->_mem : 0;
00093 }
00094
00095 return new_chunk(size);
00096 }
00097
00098 void
00099 byte_allocator::clear_extra(bool secure)
00100 {
00101
00102 mem_chunk* remove_chunk = _start_chunk ? _start_chunk->_next_chunk : 0;
00103
00104 if (_start_chunk)
00105 _start_chunk->_next_chunk = 0;
00106
00107 while (remove_chunk)
00108 {
00109 _using_chunk = remove_chunk;
00110 remove_chunk = remove_chunk->_next_chunk;
00111
00112 if (secure)
00113 memset(_using_chunk->_mem, 0, _using_chunk->_chunk_size);
00114
00115 ::free(_using_chunk);
00116 --_count;
00117 }
00118
00119 reset();
00120 }
00121
00122 void
00123 byte_allocator::clear_all(bool secure)
00124 {
00125 while (_start_chunk)
00126 {
00127 _using_chunk = _start_chunk;
00128 _start_chunk = _start_chunk->_next_chunk;
00129
00130 if (secure)
00131 memset(_using_chunk->_mem, 0, _using_chunk->_chunk_size);
00132
00133 ::free(_using_chunk);
00134 }
00135
00136 _count = 0;
00137 reset();
00138 }
00139
00141 rep_allocator::rep_allocator(size_t capacity) :
00142 byte_allocator(capacity)
00143 {
00144 }
00145
00146 rep_allocator::~rep_allocator()
00147 {
00148 _rep.clear();
00149 }
00150
00152
00153 byte_allocator*
00154 byte_allocator_creator::create(size_t size)
00155 {
00156
00157 return new byte_allocator(size);
00158 }
00159
00160
00161 bool
00162 byte_allocator_creator::find(byte_allocator* obj, size_t size)
00163 {
00164
00165 return obj->capacity() >= size;
00166 }
00167
00168
00169 void
00170 byte_allocator_creator::back(byte_allocator* obj, size_t)
00171 {
00172
00173 obj->count() > 1 ? obj->clear_extra() : obj->reset();
00174 }
00175
00176
00177 void
00178 byte_allocator_creator::deactivate(byte_allocator* obj, size_t)
00179 {
00180
00181 obj->clear_all();
00182 }
00183
00184
00185
00186 #pragma pack()
00187 END_TERIMBER_NAMESPACE
00188