diff options
Diffstat (limited to '')
-rw-r--r-- | src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.h | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.h b/src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.h new file mode 100644 index 00000000..16708cdc --- /dev/null +++ b/src/libs/xpcom18a4/xpcom/ds/nsFixedSizeAllocator.h @@ -0,0 +1,201 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Chris Waterson <waterson@netscape.com + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + + A simple fixed-size allocator that allocates its memory from an + arena. + + Although the allocator can handle blocks of any size, its + preformance will degrade rapidly if used to allocate blocks of + arbitrary size. Ideally, it should be used to allocate and recycle a + large number of fixed-size blocks. + + Here is a typical usage pattern: + + #include NEW_H // You'll need this! + #include "nsFixedSizeAllocator.h" + + // Say this is the object you want to allocate a ton of + class Foo { + public: + // Implement placement new & delete operators that will + // use the fixed size allocator. + static Foo * + Create(nsFixedSizeAllocator &aAllocator) + { + void *place = aAllocator.Alloc(sizeof(Foo)); + return place ? ::new (place) Foo() : nsnull; + } + + static void + Destroy(nsFixedSizeAllocator &aAllocator, Foo *aFoo) + { + aFoo->~Foo(); + aAllocator.Free(aFoo, sizeof(Foo)); + } + + // ctor & dtor + Foo() {} + ~Foo() {} + }; + + + int main(int argc, char* argv[]) + { + // Somewhere in your code, you'll need to create an + // nsFixedSizeAllocator object and initialize it: + nsFixedSizeAllocator pool; + + // The fixed size allocator will support multiple fixed sizes. + // This array lists an initial set of sizes that the allocator + // should be prepared to support. In our case, there's just one, + // which is Foo. + static const size_t kBucketSizes[] + = { sizeof(Foo) } + + // This is the number of different "buckets" you'll need for + // fixed size objects. In our example, this will be "1". + static const PRInt32 kNumBuckets + = sizeof(kBucketSizes) / sizeof(size_t); + + // This is the intial size of the allocator, in bytes. We'll + // assume that we want to start with space for 1024 Foo objects. + static const PRInt32 kInitialPoolSize = + NS_SIZE_IN_HEAP(sizeof(Foo)) * 1024; + + // Initialize (or re-initialize) the pool + pool.Init("TheFooPool", kBucketSizes, kNumBuckets, kInitialPoolSize); + + // Now we can use the pool. + + // Create a new Foo object using the pool: + Foo* foo = Foo::Create(pool); + if (! foo) { + // uh oh, out of memory! + } + + // Delete the object. The memory used by `foo' is recycled in + // the pool, and placed in a freelist + Foo::Destroy(foo); + + // Create another foo: this one will be allocated from the + // free-list + foo = Foo::Create(pool); + + // When pool is destroyed, all of its memory is automatically + // freed. N.B. it will *not* call your objects' destructors! In + // this case, foo's ~Foo() method would never be called. + } + +*/ + +#ifndef nsFixedSizeAllocator_h__ +#define nsFixedSizeAllocator_h__ + +#include "nscore.h" +#include "nsError.h" +#include "plarena.h" + +#define NS_SIZE_IN_HEAP(_size) (_size) + +class NS_COM nsFixedSizeAllocator +{ +protected: + PLArenaPool mPool; + + struct Bucket; + struct FreeEntry; + + friend struct Bucket; + friend struct FreeEntry; + + struct FreeEntry { + FreeEntry* mNext; + }; + + struct Bucket { + size_t mSize; + FreeEntry* mFirst; + Bucket* mNext; + }; + + Bucket* mBuckets; + + Bucket * + AddBucket(size_t aSize); + + Bucket * + FindBucket(size_t aSize); + +public: + nsFixedSizeAllocator() : mBuckets(nsnull) {} + + ~nsFixedSizeAllocator() { + if (mBuckets) + PL_FinishArenaPool(&mPool); + } + + /** + * Initialize the fixed size allocator. 'aName' is used to tag + * the underlying PLArena object for debugging and measurement + * purposes. 'aNumBuckets' specifies the number of elements in + * 'aBucketSizes', which is an array of integral block sizes + * that this allocator should be prepared to handle. + */ + nsresult + Init(const char* aName, + const size_t* aBucketSizes, + PRInt32 aNumBuckets, + PRInt32 aInitialSize, + PRInt32 aAlign = 0); + + /** + * Allocate a block of memory 'aSize' bytes big. + */ + void* Alloc(size_t aSize); + + /** + * Free a pointer allocated using a fixed-size allocator + */ + void Free(void* aPtr, size_t aSize); +}; + + + +#endif // nsFixedSizeAllocator_h__ |