Sierra Toolkit Version of the Day
fixed_allocator_eastl.h
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends