Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

ItemAllocator.h

Go to the documentation of this file.
00001 // -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; indent-tabs-mode: nil; -*-
00002 ////////////////////////////////////////////////////////////////////
00003 //
00004 // Filename : ItemAllocator.h (base)
00005 //
00006 // This file is a part of the UPPAAL toolkit.
00007 // Copyright (c) 1995 - 2003, Uppsala University and Aalborg University.
00008 // All right reserved.
00009 //
00010 // $Id: ItemAllocator.h,v 1.8 2005/01/25 18:30:22 adavid Exp $
00011 //
00012 ///////////////////////////////////////////////////////////////////
00013 
00014 #ifndef INCLUDE_BASE_ITEMALLOCATOR_H
00015 #define INCLUDE_BASE_ITEMALLOCATOR_H
00016 
00017 #include <assert.h>
00018 #include <stdlib.h>
00019 #include <cstddef>
00020 
00021 namespace base
00022 {
00023     /** Simple (and fast) item allocator.
00024      * The interest of it, compared
00025      * to DataAllocator is to have a different memory area (and thus
00026      * avoid messing up with the pages) for another kind of data. This
00027      * is particularly fitted to the waiting queue vs explored states
00028      * stored.
00029      *
00030      * Working of ItemAllocator: it allocates a
00031      * continuous chunk of numberOfItems items (=pool) and 
00032      * initializes the list of free items. Allocation
00033      * and deallocation just pop and push items on
00034      * this list. When the list is empty, a new pool
00035      * of items is allocated.
00036      * Template arguments:
00037      * @param ITEM: type of object to allocate
00038      * Default = 128k items
00039      * @pre ITEM size is at least 1 int.
00040      */
00041     template<class ITEM>
00042     class ItemAllocator
00043     {
00044     public:
00045 
00046         /** Default number of items.
00047          */
00048         enum { NB_ITEMS = (1 << 17) };
00049 
00050         /** Constructor: check precondition & init to NULL
00051          * @param nbItems: number of items per pool.
00052          * @pre nbItems > 1
00053          */
00054         ItemAllocator(size_t nbItems = NB_ITEMS)
00055             : numberOfItems(nbItems),
00056               pool(NULL),
00057               freeItem(NULL)
00058         {
00059             assert(sizeof(ITEM) >= sizeof(void*));
00060             assert(nbItems > 1);
00061         }
00062 
00063         /** Destructor = reset
00064          */
00065         ~ItemAllocator()
00066         {
00067             reset();
00068         }
00069 
00070         /** Allocate a new item.
00071          * @return new allocated item.
00072          * @post result != NULL
00073          */
00074         ITEM* allocate()
00075         {
00076             if (!freeItem) addPool();
00077             AllocCell_t *cell = freeItem;
00078             freeItem = cell->next;
00079             return &cell->item;
00080         }
00081 
00082         /** Deallocate an item.
00083          * @param item: item to deallocate.
00084          * @pre
00085          * - item allocated with this allocator
00086          * - item != NULL
00087          */
00088         void deallocate(ITEM *item)
00089         {
00090             assert(item);
00091             AllocCell_t *cell = (AllocCell_t*) item;
00092             cell->next = freeItem;
00093             freeItem = cell;
00094         }
00095 
00096         /** Reset the allocator: free all pools
00097          * and reset the list of free items.
00098          */
00099         void reset()
00100         {
00101             AllocPool_t *p = pool;
00102             pool = NULL;
00103             freeItem = NULL;
00104             while(p)
00105             {
00106                 AllocPool_t *next = p->next;
00107                 delete [] (char*) p;
00108                 p = next;
00109             }
00110         }
00111 
00112     private:
00113         
00114         /** Add a new pool of items.
00115          */
00116         void addPool()
00117         {
00118             // Add new pool to list of pools
00119             AllocPool_t *newPool = (AllocPool_t*)
00120                 new char[sizeof(AllocPool_t)+
00121                          sizeof(AllocCell_t[numberOfItems])];
00122             newPool->next = pool;
00123             pool = newPool;
00124 
00125             // Init beginning of the list of free items
00126             AllocCell_t *item = &newPool->items[0];
00127             assert(!freeItem);
00128             freeItem = item;
00129 
00130             // Init list of free items
00131             size_t n = numberOfItems - 1;
00132             assert(numberOfItems > 1);
00133             do {
00134                 item[0].next = &item[1];
00135                 item++;
00136             } while(--n);
00137             item[0].next = NULL; // last item: no next
00138         }
00139 
00140         /** UNION to manage list of
00141          * free items (next) and allocation
00142          * of items (item).
00143          * Guarantee at compile time that
00144          * ITEM does not have a constructor.
00145          */
00146         union AllocCell_t
00147         {
00148             AllocCell_t *next;
00149             ITEM item;
00150         };
00151 
00152         /** Pool of items.
00153          */
00154         struct AllocPool_t
00155         {
00156             AllocPool_t *next;
00157             AllocCell_t items[];
00158         };
00159 
00160         size_t numberOfItems; /**< number of items per pool */
00161         AllocPool_t *pool;         /**< allocated pools          */
00162         AllocCell_t *freeItem;     /**< list of free items       */
00163     };
00164 
00165 } // namespace base
00166 
00167 #endif // INCLUDE_BASE_ITEMALLOCATOR_H

Generated on Fri Jun 30 00:02:30 2006 for Module base by  doxygen 1.4.2