source: proiecte/swift/trunk/lib/hoard-371/src/heaplayers/segheap.h @ 176

Last change on this file since 176 was 176, checked in by (none), 14 years ago
  • imported repo from "guagal"
File size: 8.7 KB
Line 
1/* -*- C++ -*- */
2
3/*
4
5Heap Layers: An Extensible Memory Allocation Infrastructure
6 
7Copyright (C) 2000-2005 by Emery Berger
8http://www.cs.umass.edu/~emery
9emery@cs.umass.edu
10 
11This program is free software; you can redistribute it and/or modify
12it under the terms of the GNU General Public License as published by
13the Free Software Foundation; either version 2 of the License, or
14(at your option) any later version.
15 
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19GNU General Public License for more details.
20 
21You should have received a copy of the GNU General Public License
22along with this program; if not, write to the Free Software
23Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24
25*/
26
27  /**
28   * @file segheap.h
29   * @brief Definitions of SegHeap and StrictSegHeap.
30   */
31
32#ifndef _SEGHEAP_H_
33#define _SEGHEAP_H_
34
35  /**
36   * @class SegHeap
37   * @brief A segregated-fits collection of (homogeneous) heaps.
38   * @author Emery Berger
39   *
40   * Note that one extra heap is used for objects that are "too big".
41   *
42   * @param NumBins The number of bins (subheaps).
43   * @param getSizeClass Function to compute size class from size.
44   * @param getClassMaxSize Function to compute the largest size for a given size class.
45   * @param LittleHeap The subheap class.
46   * @param BigHeap The parent class, used for "big" objects.
47   *
48   * Example:<BR>
49   * <TT>
50   *  int myFunc (size_t sz); // The size-to-class function.<BR>
51   *  size_t myFunc2 (int); // The class-to-size function.<P>
52   *  // The heap. Use freelists for these small objects,<BR>
53   *  // but defer to malloc for large objects.<P>
54   *
55   * SegHeap<4, myFunc, myFunc2, freelistHeap<mallocHeap>, mallocHeap> mySegHeap;
56   * </TT>
57   **/
58
59#include <assert.h>
60#include "bitstring.h"
61
62  namespace HL {
63
64    template <int NumBins,
65              int (*getSizeClass) (const size_t),
66              size_t (*getClassMaxSize) (const int),
67              class LittleHeap,
68              class BigHeap>
69    class SegHeap : public LittleHeap {
70    private:
71
72      typedef int (*scFunction) (const size_t);
73      typedef size_t (*csFunction) (const int);
74
75    public:
76
77      inline SegHeap (void)
78        : memoryHeld (0),
79          maxObjectSize (((csFunction) getClassMaxSize) (NumBins - 1))
80      {
81        for (int i = 0; i < NUM_ULONGS; i++) {
82          binmap[i] = 0;
83        }
84      }
85
86      inline ~SegHeap (void) {}
87
88      inline size_t getMemoryHeld (void) const {
89        return memoryHeld;
90      }
91
92      // new...
93      size_t getSize (void * ptr) {
94        return LittleHeap::getSize (ptr);
95      }
96
97      inline void * malloc (const size_t sz) {
98        void * ptr = NULL;
99        if (sz > maxObjectSize) {
100          goto GET_MEMORY;
101        }
102
103        {
104          const int sc = ((scFunction) getSizeClass)(sz);
105          assert (sc >= 0);
106          assert (sc < NumBins);
107          int idx = sc;
108          int block = idx2block (idx);
109          unsigned long map = binmap[block];
110          unsigned long bit = idx2bit (idx);
111   
112          for (;;) {
113            if (bit > map || bit == 0) {
114              do {
115                if (++block >= NUM_ULONGS) {
116                  goto GET_MEMORY;
117                  // return bigheap.malloc (sz);
118                }
119              } while ( (map = binmap[block]) == 0);
120
121              idx = block << SHIFTS_PER_ULONG;
122              bit = 1;
123            }
124       
125            while ((bit & map) == 0) {
126              bit <<= 1;
127              assert(bit != 0);
128              idx++;
129            }
130     
131            assert (idx < NumBins);
132            ptr = myLittleHeap[idx].malloc (sz);
133     
134            if (ptr == NULL) {
135              binmap[block] = map &= ~bit; // Write through
136              idx++;
137              bit <<= 1;
138            } else {
139              return ptr;
140            }
141          }
142        }
143
144      GET_MEMORY:
145        if (ptr == NULL) {
146          // There was no free memory in any of the bins.
147          // Get some memory.
148          ptr = bigheap.malloc (sz);
149        }
150   
151        return ptr;
152      }
153
154
155      inline void free (void * ptr) {
156        // printf ("Free: %x (%d bytes)\n", ptr, getSize(ptr));
157        const size_t objectSize = getSize(ptr); // was bigheap.getSize(ptr)
158        if (objectSize > maxObjectSize) {
159          // printf ("free up! (size class = %d)\n", objectSizeClass);
160          bigheap.free (ptr);
161        } else {
162          int objectSizeClass = ((scFunction) getSizeClass) (objectSize);
163          assert (objectSizeClass >= 0);
164          assert (objectSizeClass < NumBins);
165          // Put the freed object into the right sizeclass heap.
166          assert (getClassMaxSize(objectSizeClass) >= objectSize);
167#if 1
168          while (((csFunction) getClassMaxSize)(objectSizeClass) > objectSize) {
169            objectSizeClass--;
170          }
171#endif
172          assert (((csFunction) getClassMaxSize)(objectSizeClass) <= objectSize);
173          if (objectSizeClass > 0) {
174            assert (objectSize >= ((csFunction) getClassMaxSize)(objectSizeClass - 1));
175          }
176
177
178          myLittleHeap[objectSizeClass].free (ptr);
179          mark_bin (objectSizeClass);
180          memoryHeld += objectSize;
181        }
182      }
183
184
185      void clear (void) {
186        int i;
187        for (i = 0; i < NumBins; i++) {
188          myLittleHeap[i].clear();
189        }
190        for (int j = 0; j < NUM_ULONGS; j++) {
191          binmap[j] = 0;
192        }
193        // bitstring.clear();
194        bigheap.clear();
195        memoryHeld = 0;
196      }
197
198    private:
199
200      enum { BITS_PER_ULONG = 32 };
201      enum { SHIFTS_PER_ULONG = 5 };
202      enum { MAX_BITS = (NumBins + BITS_PER_ULONG - 1) & ~(BITS_PER_ULONG - 1) };
203
204
205    private:
206
207      static inline int idx2block (int i) {
208        int blk = i >> SHIFTS_PER_ULONG;
209        assert (blk < NUM_ULONGS);
210        assert (blk >= 0);
211        return blk;
212      }
213
214      static inline unsigned long idx2bit (int i) {
215        unsigned long bit = ((1U << ((i) & ((1U << SHIFTS_PER_ULONG)-1))));
216        return bit;
217      }
218
219
220    protected:
221
222      BigHeap bigheap;
223
224      enum { NUM_ULONGS = MAX_BITS / BITS_PER_ULONG };
225      unsigned long binmap[NUM_ULONGS];
226
227      inline int get_binmap (int i) const {
228        return binmap[i >> SHIFTS_PER_ULONG] & idx2bit(i);
229      }
230
231      inline void mark_bin (int i) {
232        binmap[i >> SHIFTS_PER_ULONG] |=  idx2bit(i);
233      }
234
235      inline void unmark_bin (int i) {
236        binmap[i >> SHIFTS_PER_ULONG] &= ~(idx2bit(i));
237      }
238
239      size_t memoryHeld;
240
241      const size_t maxObjectSize;
242
243      // The little heaps.
244      LittleHeap myLittleHeap[NumBins];
245
246    };
247
248  };
249
250
251/**
252 * @class StrictSegHeap
253 * @brief A "strict" segregated-fits collection of (homogeneous) heaps.
254 *
255 * One extra heap is used for objects that are "too big".  Unlike
256 * SegHeap, StrictSegHeap does not perform splitting to satisfy memory
257 * requests. If no memory is available from the appropriate bin,
258 * malloc returns NULL.
259 *
260 * @sa SegHeap
261 *
262 * @param NumBins The number of bins (subheaps).
263 * @param getSizeClass Function to compute size class from size.
264 * @param getClassMaxSize Function to compute the largest size for a given size class.
265 * @param LittleHeap The subheap class.
266 * @param BigHeap The parent class, used for "big" objects.
267 */
268
269namespace HL {
270
271  template <int NumBins,
272            int (*getSizeClass) (const size_t),
273            size_t (*getClassMaxSize) (const int),
274            class LittleHeap,
275            class BigHeap>
276  class StrictSegHeap :
277    public SegHeap<NumBins, getSizeClass, getClassMaxSize, LittleHeap, BigHeap>
278  {
279  private:
280
281    typedef SegHeap<NumBins, getSizeClass, getClassMaxSize, LittleHeap, BigHeap> super;
282
283    typedef int (*scFunction) (const size_t);
284    typedef size_t (*csFunction) (const int);
285
286  public:
287
288    void freeAll (void) {
289      int i;
290      for (i = 0; i < NumBins; i++) {
291        const size_t sz = ((csFunction) getClassMaxSize)(i);
292        void * ptr;
293        while ((ptr = super::myLittleHeap[i].malloc (sz)) != NULL) {
294          super::bigheap.free (ptr);
295        }
296      }
297      for (int j = 0; j < super::NUM_ULONGS; j++) {
298        super::binmap[j] = 0;
299      }
300      super::memoryHeld = 0;
301    }
302
303 
304    /**
305     * Malloc from exactly one available size.
306     * (don't look in every small heap, as in SegHeap).
307     */
308
309    inline void * malloc (const size_t sz) {
310      void * ptr = NULL;
311      if (sz <= super::maxObjectSize) {
312        const int sizeClass = ((scFunction) getSizeClass) (sz);
313        assert (sizeClass >= 0);
314        assert (sizeClass < NumBins);
315        ptr = super::myLittleHeap[sizeClass].malloc (sz);
316      }
317      if (!ptr) {
318        ptr = super::bigheap.malloc (sz);
319      }
320      return ptr;
321    }
322
323    inline void free (void * ptr) {
324      const size_t objectSize = super::getSize(ptr);
325      if (objectSize > super::maxObjectSize) {
326        super::bigheap.free (ptr);
327      } else {
328        int objectSizeClass = ((scFunction) getSizeClass) (objectSize);
329        assert (objectSizeClass >= 0);
330        assert (objectSizeClass < NumBins);
331        // Put the freed object into the right sizeclass heap.
332        assert (getClassMaxSize(objectSizeClass) >= objectSize);
333        while (((csFunction) getClassMaxSize)(objectSizeClass) > objectSize) {
334          objectSizeClass--;
335        }
336        assert (((csFunction) getClassMaxSize)(objectSizeClass) <= objectSize);
337        if (objectSizeClass > 0) {
338          assert (objectSize >= ((csFunction) getClassMaxSize)(objectSizeClass - 1));
339        }
340
341        super::myLittleHeap[objectSizeClass].free (ptr);
342        super::memoryHeld += objectSize;
343      }
344    }
345
346  };
347
348};
349
350
351#endif
Note: See TracBrowser for help on using the repository browser.