Back to index

lightning-sunbird  0.9+nobinonly
nsFixedSizeAllocator.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Chris Waterson <waterson@netscape.com
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 /*
00040 
00041   A simple fixed-size allocator that allocates its memory from an
00042   arena.
00043 
00044   Although the allocator can handle blocks of any size, its
00045   preformance will degrade rapidly if used to allocate blocks of
00046   arbitrary size. Ideally, it should be used to allocate and recycle a
00047   large number of fixed-size blocks.
00048 
00049   Here is a typical usage pattern:
00050 
00051     #include NEW_H // You'll need this!
00052     #include "nsFixedSizeAllocator.h"
00053 
00054     // Say this is the object you want to allocate a ton of
00055     class Foo {
00056     public:
00057       // Implement placement new & delete operators that will
00058       // use the fixed size allocator.
00059       static Foo *
00060       Create(nsFixedSizeAllocator &aAllocator)
00061       {
00062         void *place = aAllocator.Alloc(sizeof(Foo));
00063         return place ? ::new (place) Foo() : nsnull;
00064       }
00065 
00066       static void
00067       Destroy(nsFixedSizeAllocator &aAllocator, Foo *aFoo)
00068       {
00069         aFoo->~Foo();
00070         aAllocator.Free(aFoo, sizeof(Foo));
00071       }
00072 
00073       // ctor & dtor
00074       Foo() {}
00075       ~Foo() {}
00076     };
00077 
00078 
00079     int main(int argc, char* argv[])
00080     {
00081       // Somewhere in your code, you'll need to create an
00082       // nsFixedSizeAllocator object and initialize it:
00083       nsFixedSizeAllocator pool;
00084 
00085       // The fixed size allocator will support multiple fixed sizes.
00086       // This array lists an initial set of sizes that the allocator
00087       // should be prepared to support. In our case, there's just one,
00088       // which is Foo.
00089       static const size_t kBucketSizes[]
00090         = { sizeof(Foo) }
00091 
00092       // This is the number of different "buckets" you'll need for
00093       // fixed size objects. In our example, this will be "1".
00094       static const PRInt32 kNumBuckets
00095         = sizeof(kBucketSizes) / sizeof(size_t);
00096 
00097       // This is the intial size of the allocator, in bytes. We'll
00098       // assume that we want to start with space for 1024 Foo objects.
00099       static const PRInt32 kInitialPoolSize =
00100         NS_SIZE_IN_HEAP(sizeof(Foo)) * 1024;
00101 
00102       // Initialize (or re-initialize) the pool
00103       pool.Init("TheFooPool", kBucketSizes, kNumBuckets, kInitialPoolSize);
00104 
00105       // Now we can use the pool.
00106 
00107       // Create a new Foo object using the pool:
00108       Foo* foo = Foo::Create(pool);
00109       if (! foo) {
00110         // uh oh, out of memory!
00111       }
00112 
00113       // Delete the object. The memory used by `foo' is recycled in
00114       // the pool, and placed in a freelist
00115       Foo::Destroy(foo);
00116 
00117       // Create another foo: this one will be allocated from the
00118       // free-list
00119       foo = Foo::Create(pool);
00120 
00121       // When pool is destroyed, all of its memory is automatically
00122       // freed. N.B. it will *not* call your objects' destructors! In
00123       // this case, foo's ~Foo() method would never be called.
00124     }
00125 
00126 */
00127 
00128 #ifndef nsFixedSizeAllocator_h__
00129 #define nsFixedSizeAllocator_h__
00130 
00131 #include "nscore.h"
00132 #include "nsError.h"
00133 #include "plarena.h"
00134 
00135 #define NS_SIZE_IN_HEAP(_size) (_size)
00136 
00137 class NS_COM nsFixedSizeAllocator
00138 {
00139 protected:
00140     PLArenaPool mPool;
00141 
00142     struct Bucket;
00143     struct FreeEntry;
00144   
00145     friend struct Bucket;
00146     friend struct FreeEntry;
00147 
00148     struct FreeEntry {
00149         FreeEntry* mNext;
00150     };
00151 
00152     struct Bucket {
00153         size_t     mSize;
00154         FreeEntry* mFirst;
00155         Bucket*    mNext;
00156     };
00157 
00158     Bucket* mBuckets;
00159 
00160     Bucket *
00161     AddBucket(size_t aSize);
00162 
00163     Bucket *
00164     FindBucket(size_t aSize);
00165 
00166 public:
00167     nsFixedSizeAllocator() : mBuckets(nsnull) {}
00168 
00169     ~nsFixedSizeAllocator() {
00170         if (mBuckets)
00171             PL_FinishArenaPool(&mPool);
00172     }
00173 
00181     nsresult
00182     Init(const char* aName,
00183          const size_t* aBucketSizes,
00184          PRInt32 aNumBuckets,
00185          PRInt32 aInitialSize,
00186          PRInt32 aAlign = 0);
00187 
00191     void* Alloc(size_t aSize);
00192 
00196     void Free(void* aPtr, size_t aSize);
00197 };
00198 
00199 
00200 
00201 #endif // nsFixedSizeAllocator_h__