|
Sierra Toolkit
Version of the Day
|
00001 /* 00002 Copyright (C) 2009-2010 Electronic Arts, Inc. All rights reserved. 00003 00004 Redistribution and use in source and binary forms, with or without 00005 modification, are permitted provided that the following conditions 00006 are met: 00007 00008 1. Redistributions of source code must retain the above copyright 00009 notice, this list of conditions and the following disclaimer. 00010 2. Redistributions in binary form must reproduce the above copyright 00011 notice, this list of conditions and the following disclaimer in the 00012 documentation and/or other materials provided with the distribution. 00013 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of 00014 its contributors may be used to endorse or promote products derived 00015 from this software without specific prior written permission. 00016 00017 THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY 00018 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00019 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00020 DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY 00021 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00022 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00023 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00024 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00025 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00026 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00027 */ 00028 00030 // EASTL/fixed_allocator.h 00031 // 00032 // Copyright (c) 2005, Electronic Arts. All rights reserved. 00033 // Written and maintained by Paul Pedriana. 00035 00037 // This file implements the following 00038 // fixed_allocator 00039 // fixed_allocator_with_overflow 00041 00042 00043 #ifndef EASTL_FIXED_ALLOCATOR_H 00044 #define EASTL_FIXED_ALLOCATOR_H 00045 00046 00047 #include <stk_util/util/config_eastl.h> 00048 #include <stk_util/util/fixed_pool_eastl.h> 00049 #include <stk_util/util/functional_eastl.h> 00050 #include <stk_util/util/memory_eastl.h> 00051 #include <stk_util/util/allocator_eastl.h> 00052 #include <stk_util/util/type_traits_eastl.h> 00053 00054 #ifdef _MSC_VER 00055 #pragma warning(push, 0) 00056 #include <new> 00057 #pragma warning(pop) 00058 #else 00059 #include <new> 00060 #endif 00061 00062 00063 namespace eastl 00064 { 00065 00067 // fixed_allocator 00069 00109 class EASTL_API fixed_allocator : public fixed_pool_base 00110 { 00111 public: 00117 fixed_allocator(const char* /*pName*/ = EASTL_FIXED_POOL_DEFAULT_NAME) 00118 : fixed_pool_base(NULL) 00119 { 00120 } 00121 00122 00130 fixed_allocator(const fixed_allocator&) 00131 : fixed_pool_base(NULL) 00132 { 00133 } 00134 00135 00142 fixed_allocator& operator=(const fixed_allocator&) 00143 { 00144 return *this; 00145 } 00146 00147 00148 // init 00149 // 00150 // No init here, as the base class version is sufficient. 00151 // 00152 //void init(void* pMemory, size_t memorySize, size_t nodeSize, 00153 // size_t alignment, size_t alignmentOffset = 0); 00154 00155 00161 void* allocate(size_t /*n*/, int /*flags*/ = 0) 00162 { 00163 // To consider: Verify that 'n' is what the user initialized us with. 00164 00165 Link* pLink = mpHead; 00166 00167 if(pLink) // If we have space... 00168 { 00169 #if EASTL_FIXED_SIZE_TRACKING_ENABLED 00170 if(++mnCurrentSize > mnPeakSize) 00171 mnPeakSize = mnCurrentSize; 00172 #endif 00173 00174 mpHead = pLink->mpNext; 00175 return pLink; 00176 } 00177 else 00178 { 00179 // If there's no free node in the free list, just 00180 // allocate another from the reserved memory area 00181 00182 if(mpNext != mpCapacity) 00183 { 00184 pLink = mpNext; 00185 00186 mpNext = reinterpret_cast<Link*>(reinterpret_cast<char8_t*>(mpNext) + mnNodeSize); 00187 00188 #if EASTL_FIXED_SIZE_TRACKING_ENABLED 00189 if(++mnCurrentSize > mnPeakSize) 00190 mnPeakSize = mnCurrentSize; 00191 #endif 00192 00193 return pLink; 00194 } 00195 00196 // EASTL_ASSERT(false); To consider: enable this assert. However, we intentionally disable it because this isn't necessarily an assertable error. 00197 return NULL; 00198 } 00199 } 00200 00201 00204 void* allocate(size_t n, size_t /*alignment*/, size_t /*offset*/, int flags = 0) 00205 { 00206 return allocate(n, flags); 00207 } 00208 00209 00216 void deallocate(void* p, size_t) 00217 { 00218 #if EASTL_FIXED_SIZE_TRACKING_ENABLED 00219 --mnCurrentSize; 00220 #endif 00221 00222 ((Link*)p)->mpNext = mpHead; 00223 mpHead = ((Link*)p); 00224 } 00225 00226 00227 using fixed_pool_base::can_allocate; 00228 00229 00230 const char* get_name() const 00231 { 00232 return EASTL_FIXED_POOL_DEFAULT_NAME; 00233 } 00234 00235 00236 void set_name(const char*) 00237 { 00238 // Nothing to do. We don't allocate memory. 00239 } 00240 00241 }; // fixed_allocator 00242 00243 bool operator==(const fixed_allocator& a, const fixed_allocator& b); 00244 bool operator!=(const fixed_allocator& a, const fixed_allocator& b); 00245 00246 00247 00249 // fixed_allocator_with_overflow 00251 00287 class EASTL_API fixed_allocator_with_overflow : public fixed_pool_base 00288 { 00289 public: 00295 fixed_allocator_with_overflow(const char* pName = EASTL_FIXED_POOL_DEFAULT_NAME) 00296 : fixed_pool_base(NULL), 00297 mOverflowAllocator(pName) 00298 { 00299 } 00300 00301 00309 fixed_allocator_with_overflow(const fixed_allocator_with_overflow&) 00310 : fixed_pool_base(NULL) 00311 { 00312 } 00313 00314 00321 fixed_allocator_with_overflow& operator=(const fixed_allocator_with_overflow& x) 00322 { 00323 #if EASTL_ALLOCATOR_COPY_ENABLED 00324 mOverflowAllocator = x.mOverflowAllocator; 00325 #else 00326 (void)x; 00327 #endif 00328 00329 return *this; 00330 } 00331 00332 00335 void init(void* pMemory, size_t memorySize, size_t nodeSize, 00336 size_t alignment, size_t alignmentOffset = 0) 00337 { 00338 fixed_pool_base::init(pMemory, memorySize, nodeSize, alignment, alignmentOffset); 00339 00340 mpPoolBegin = pMemory; 00341 mpPoolEnd = (void*)((uintptr_t)pMemory + memorySize); 00342 mnNodeSize = (eastl_size_t)nodeSize; 00343 } 00344 00345 00351 void* allocate(size_t /*n*/, int /*flags*/ = 0) 00352 { 00353 // To consider: Verify that 'n' is what the user initialized us with. 00354 00355 void* p; 00356 00357 if(mpHead) // If we have space... 00358 { 00359 p = mpHead; 00360 mpHead = mpHead->mpNext; 00361 } 00362 else 00363 p = mOverflowAllocator.allocate(mnNodeSize); 00364 00365 #if EASTL_FIXED_SIZE_TRACKING_ENABLED 00366 if(p && (++mnCurrentSize > mnPeakSize)) 00367 mnPeakSize = mnCurrentSize; 00368 #endif 00369 00370 return p; 00371 } 00372 00373 00376 void* allocate(size_t n, size_t /*alignment*/, size_t /*offset*/, int flags = 0) 00377 { 00378 return allocate(n, flags); 00379 } 00380 00381 00388 void deallocate(void* p, size_t) 00389 { 00390 #if EASTL_FIXED_SIZE_TRACKING_ENABLED 00391 --mnCurrentSize; 00392 #endif 00393 00394 if((p >= mpPoolBegin) && (p < mpPoolEnd)) 00395 { 00396 ((Link*)p)->mpNext = mpHead; 00397 mpHead = ((Link*)p); 00398 } 00399 else 00400 mOverflowAllocator.deallocate(p, (size_t)mnNodeSize); 00401 } 00402 00403 00404 using fixed_pool_base::can_allocate; 00405 00406 00407 const char* get_name() const 00408 { 00409 return mOverflowAllocator.get_name(); 00410 } 00411 00412 00413 void set_name(const char* pName) 00414 { 00415 mOverflowAllocator.set_name(pName); 00416 } 00417 00418 protected: 00419 EASTLAllocatorType mOverflowAllocator; // To consider: Allow the user to define the type of this, presumably via a template parameter. 00420 void* mpPoolBegin; // To consider: We have these member variables and ideally we shouldn't need them. The problem is that 00421 void* mpPoolEnd; // the information about the pool buffer and object size is stored in the owning container 00422 eastl_size_t mnNodeSize; // and we can't have access to it without increasing the amount of code we need and by templating 00423 // more code. It may turn out that simply storing data here is smaller in the end. 00424 }; // fixed_allocator_with_overflow // Granted, this class is usually used for debugging purposes, but perhaps there is an elegant solution. 00425 00426 bool operator==(const fixed_allocator_with_overflow& a, const fixed_allocator_with_overflow& b); 00427 bool operator!=(const fixed_allocator_with_overflow& a, const fixed_allocator_with_overflow& b); 00428 00429 00430 00431 00432 00433 00435 // global operators 00437 00438 inline bool operator==(const fixed_allocator&, const fixed_allocator&) 00439 { 00440 return false; 00441 } 00442 00443 inline bool operator!=(const fixed_allocator&, const fixed_allocator&) 00444 { 00445 return false; 00446 } 00447 00448 inline bool operator==(const fixed_allocator_with_overflow&, const fixed_allocator_with_overflow&) 00449 { 00450 return false; 00451 } 00452 00453 inline bool operator!=(const fixed_allocator_with_overflow&, const fixed_allocator_with_overflow&) 00454 { 00455 return false; 00456 } 00457 00458 00459 } // namespace eastl 00460 00461 00462 00463 00464 #endif // Header include guard