00001 /*00002 * The Software License00003 * =================================================================================00004 * Copyright (c) 2003-.The Terimber Corporation. All rights reserved.00005 * =================================================================================00006 * Redistributions of source code must retain the above copyright notice, 00007 * this list of conditions and the following disclaimer.00008 * Redistributions in binary form must reproduce the above copyright notice, 00009 * this list of conditions and the following disclaimer in the documentation 00010 * and/or other materials provided with the distribution.00011 * The end-user documentation included with the redistribution, if any, 00012 * must include the following acknowledgment:00013 * "This product includes software developed by the Terimber Corporation."00014 * =================================================================================00015 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, 00016 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 00017 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00018 * IN NO EVENT SHALL THE TERIMBER CORPORATION OR ITS CONTRIBUTORS BE LIABLE FOR 00019 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00020 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00021 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 00022 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT00023 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE00024 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.00025 * ================================================================================00026 */00027
00028 #ifndef _terimber_memory_hpp_00029 #define _terimber_memory_hpp_00030
00031 #include "base/memory.h"00032
00033 BEGIN_TERIMBER_NAMESPACE00034 #pragma pack(4)00035
00036 // class to keep free chunks of memory for reusing00037 // clears stack00038 inline00039chunk_stack::chunk_stack() :
00040 _head(0)
00041 {
00042 }
00043
00044 inline00045 void00046chunk_stack::clear()
00047 {
00048 _head = 0;
00049 }
00050
00051 // pushes new chunk00052 inline00053 void00054chunk_stack::push(size_t* chunk)
00055 {
00056 if (!chunk)
00057 return;
00058 *chunk = reinterpret_cast<size_t>(_head);
00059 _head = chunk;
00060 }
00061
00062 // removes the head chunk00063 inline00064 size_t*
00065chunk_stack::pop()
00066 {
00067 size_t* chunk = _head;
00068 if (chunk)
00069 _head = reinterpret_cast<size_t* >(*chunk);
00070 return chunk;
00071 }
00072
00073 // return the head chunk00074 inline00075 size_t*
00076chunk_stack::top()
00077 {
00078 return_head;
00079 }
00080
00081 // returns the head chunk00082 inline00083 bool00084chunk_stack::empty()
00085 {
00086 return_head == 0;
00087 }
00088
00089 inline00090 void00091byte_allocator::reset(bool secure)
00092 {
00093 if (secure && _start_chunk)
00094 {
00095 _using_chunk = _start_chunk;
00096 while (_using_chunk) // while memory is there00097 {
00098 memset(_using_chunk->_mem, 0, _using_chunk->_chunk_size);
00099 _using_chunk = _using_chunk->_next_chunk; // move to next chunk00100 }
00101 }
00102
00103 _using_chunk = _start_chunk;
00104 _free_pos = _start_chunk ? _start_chunk->_mem : 0;
00105 }
00106
00107 inline00108 void*
00109byte_allocator::allocate(size_t size)
00110 {
00111 if (!size) return 0;
00112 //corect size00113 size_t correct_size = ALIGNED_SIZEOF(size);
00114 // try do it easy00115 if (_using_chunk && _using_chunk->_chunk_size - (_free_pos - _using_chunk->_mem) >= correct_size)
00116 {
00117 unsignedchar* pos = _free_pos;
00118 _free_pos += correct_size;
00119 return pos;
00120 }
00121 else// you can get nothing easy in the current life00122 returnnext_chunk(correct_size);
00123 }
00124
00125 // deallocates00126 // we don't support deallocation by pointer00127 // everything or nothing00128 inline00129 void00130byte_allocator::deallocate(void*)
00131 {
00132 }
00133
00134 // returns the capacity of chunk00135 inline00136 size_t00137byte_allocator::capacity() const 00138 {
00139 return_capacity;
00140 }
00141
00142 // returns the count of chunks00143 inline00144 size_t00145byte_allocator::count() const 00146 {
00147 return_count;
00148 }
00149
00151 inline00152 void00153rep_allocator::clear_extra(bool secure)
00154 {
00155 _rep.clear();
00156 byte_allocator::clear_extra(secure);
00157 }
00158
00159 inline00160 void00161rep_allocator::clear_all(bool secure)
00162 {
00163 _rep.clear();
00164 byte_allocator::clear_all(secure);
00165 }
00166
00167 inline00168 void00169rep_allocator::reset(bool secure)
00170 {
00171 _rep.clear();
00172 byte_allocator::reset(secure);
00173 }
00174
00175 // push pointer to object back to repository stack00176 inline00177 void00178rep_allocator::deallocate(void* p)
00179 {
00180 _rep.push((size_t*)p);
00181 }
00182
00184 // high performance template class for allocation00185 // one object at a time00186 // constructor00187 template < class T >
00188node_allocator< T >::node_allocator(size_tcapacity) :
00189 rep_allocator((capacity ? capacity : os_def_size) * ALIGNED_SIZEOF(sizeof(T)))
00190 {
00191 }
00192
00193 template < class T >
00194 inline00195 T*
00196node_allocator< T >::allocate()
00197 {
00198 return_rep.empty() ? (T*)byte_allocator::allocate(ALIGNED_SIZEOF(sizeof(T))) : (T*)_rep.pop();
00199 }
00200
00202 // template class for allocation of the array of objects00203 // it seems like this class covers the functionality of previous one00204 // but the previous class (node_allocator) has better performance00205 // constructor00206 template < class T >
00207array_allocator< T >::array_allocator(size_tcapacity) :
00208 rep_allocator((capacity ? capacity : os_def_size) * ALIGNED_SIZEOF(sizeof(T)))
00209 {
00210 }
00211
00212 // destructor00213 template < class T >
00214array_allocator< T >::~array_allocator()
00215 {
00216 }
00217
00218 template < class T >
00219 inline00220 T*
00221array_allocator< T >::allocate(size_t n)
00222 {
00223 if (!n)
00224 return 0; // nothing to do00225 // loans from stack00226 T* p = pop(n);
00227 if (!p)
00228 {
00229 size_t* ob = (size_t*)byte_allocator::allocate(n * ALIGNED_SIZEOF(sizeof(T)) + sizeof(size_t));
00230 if (!ob) return 0;
00231 *ob = n;
00232 p = (T*)(ob + 1);
00233 }
00234
00235 return p;
00236 }
00237
00238 template < class T >
00239 inline00240 T*
00241array_allocator< T >::pop(size_t n)
00242 {
00243 // looks for right size00244 size_t* cur = _rep.top();
00245 size_t* prev = 0;
00246 while (cur && *(cur - 1) < n) // sets the next chunk in stack00247 {
00248 prev = cur;
00249 cur = (size_t*)*cur;
00250 }
00251
00252 if (!cur)
00253 return 0; // nothing available in stack00254 if (prev == 0)
00255 return (T*)_rep.pop();// head is a right item00256 // removes item from stak manually00257 *prev = *cur;
00258 // returns result00259 return (T*)cur;
00260 }
00261
00263 template < class T >
00264 // static 00265 inline00266 node_allocator< T >*
00267node_allocator_creator< T >::create(size_t size)
00268 {
00269 returnnewnode_allocator< T >(size);
00270 }
00271
00272 template < class T >
00273 // static 00274 inline00275 bool00276node_allocator_creator< T >::find(node_allocator< T >* obj, size_t size)
00277 {
00278 return obj->capacity() >= size;
00279 }
00280
00281 template < class T >
00282 // static 00283 inline00284 void00285node_allocator_creator< T >::back(node_allocator< T >* obj, size_t)
00286 {
00287 obj->count() > 1 ? obj->clear() : obj->reset();
00288 }
00289
00290 template < class T >
00291 // static 00292 inline00293 void00294node_allocator_creator< T >::deactivate(node_allocator< T >* obj, size_t)
00295 {
00296 obj->clear();
00297 }
00298
00300 template < class T >
00301 // static00302 inline00303 array_allocator< T >*
00304array_allocator_creator< T >::create(size_t size)
00305 {
00306 returnnewarray_allocator< T >(size);
00307 }
00308
00309 template < class T >
00310 // static00311 inline00312 bool00313array_allocator_creator< T >::find(array_allocator< T >* obj, size_t size)
00314 {
00315 return obj->capacity() >= size;
00316 }
00317
00318 template < class T >
00319 // static00320 inline00321 void00322array_allocator_creator< T >::back(array_allocator< T >* obj, size_t)
00323 {
00324 obj->count() > 1 ? obj->clear() : obj->reset();
00325 }
00326
00327 template < class T >
00328 // static00329 inline00330 void00331array_allocator_creator< T >::deactivate(array_allocator< T >* obj, size_t)
00332 {
00333 obj->clear();
00334 }
00335
00336 #pragma pack()00337 END_TERIMBER_NAMESPACE00338
00339 #endif // _terimber_memory_hpp_00340
00341
00342