source: proiecte/swift/trunk/lib/hoard-371/src/heaplayers/experimental/looseslotheap.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.9 KB
Line 
1/* -*- C++ -*- */
2
3#ifndef _LOOSESLOTHEAP_H_
4#define _LOOSESLOTHEAP_H_
5
6#include <assert.h>
7
8#include "bigchunk.h"
9
10/*
11  LooseSlotHeap: A "Loose" slot heap.
12
13  malloc returns objects of size slotSize, allocated from the super heap
14  in chunkSize units.
15
16  free returns objects of size slotSize.
17
18  When the slot heap is at least 1/emptyFraction empty, a
19  chunk that is at least that empty is freed to the super heap.
20  Note that the chunk's memory MAY NOT SAFELY be recycled in toto --
21  it must be parceled out using the chunk interface.
22
23  The intent of this heap is to allow mostly-empty chunks to move up
24  to a staging area (the super heap) where they may be reused by other
25  "loose" slot heaps.
26
27*/
28
29template <int chunkSize, int slotSize, int emptyFraction, class Super>
30class LooseSlotHeap {
31public:
32
33        inline LooseSlotHeap (void);
34        inline ~LooseSlotHeap (void);
35
36  // Get a slotSize object.
37  inline void * malloc (size_t sz);
38
39  // Free a slotSize object.
40  static inline void free (void * ptr);
41
42private:
43
44        Super theHeap;
45
46        typedef BigChunk<chunkSize, slotSize, LooseSlotHeap> chunkType;
47
48        inline void localFree (void * ptr);
49
50        void checkClassInvariant (void) {
51#ifndef NDEBUG
52                assert (inUse >= 0);
53                assert (inUse <= space);
54                assert (lastIndex >= 0);
55                assert (lastIndex <= emptyFraction);
56                // Now check to make sure that inUse & space are correct.
57                int localInUse = 0;
58                int localSpace = 0;
59                for (int i = 0; i < emptyFraction + 1; i++) {
60                        chunkType * ch = myChunks[i];
61                        while (ch != NULL) {
62                                assert (ch->getHeap() == this);
63                                localInUse += ch->getNumSlotsInUse();
64                                localSpace += ch->getNumSlots();
65                                ch = ch->getNext();
66                        }
67                }
68                assert (localSpace == space);
69                assert (localInUse == inUse);
70#endif
71        }
72
73  // How full is this block?
74        //   0 == empty to no more than 1/emptyFraction full.
75        //   emptyFraction == completely full.
76  static inline int getFullness (chunkType * ch);
77   
78        // Move a chunk, if necessary, into the right list
79  // based on its emptiness.
80        // Returns the index of which list it is put or left in.
81        inline int update (chunkType * ch, int prevIndex);
82
83  // The array of chunks, "radix sorted" by emptiness.
84  // completely empty chunks are in index 0.
85  // completely full chunks are in index emptyFraction.
86  chunkType * myChunks[emptyFraction + 1];
87
88  // The last index (from 0) in the above array that has a chunk.
89  int lastIndex;
90
91  // How much space is in use in all of the chunks.
92  int inUse;
93
94  // How much space there is (free or not) in all of the chunks.
95  int space;
96};
97
98
99template <int chunkSize, int slotSize, int emptyFraction, class Super>
100LooseSlotHeap<chunkSize, slotSize, emptyFraction, Super>::LooseSlotHeap (void)
101  : space (0),
102    inUse (0),
103    lastIndex (emptyFraction - 1)
104{
105        // Initialize the chunk pointers (all initially empty).
106        for (int i = 0; i < emptyFraction + 1; i++) {
107                myChunks[i] = NULL;
108        }
109}
110
111
112template <int chunkSize, int slotSize, int emptyFraction, class Super>
113LooseSlotHeap<chunkSize, slotSize, emptyFraction, Super>::~LooseSlotHeap (void)
114{
115        // Free every chunk.
116        chunkType * ch, * tmp;
117        for (int i = 0; i < emptyFraction + 1; i++) {
118                ch = myChunks[i];
119                while (ch != NULL) {
120                        tmp = ch;
121                        ch = ch->getNext();
122                        theHeap.free (tmp);
123                }
124        }
125}
126
127
128template <int chunkSize, int slotSize, int emptyFraction, class Super>
129int LooseSlotHeap<chunkSize, slotSize, emptyFraction, Super>::getFullness (chunkType * ch)
130{
131  int fullness = (emptyFraction * ch->getNumSlotsInUse())/ch->getNumSlots();
132        //printf ("numslots avail = %d, num slots total = %d, fullness = %d\n", ch->getNumSlotsFree(), ch->getNumSlots(), fullness);
133        return fullness;
134}
135
136       
137template <int chunkSize, int slotSize, int emptyFraction, class Super>
138void * LooseSlotHeap<chunkSize, slotSize, emptyFraction, Super>::malloc (size_t sz)
139{
140        checkClassInvariant();
141        //printf ("Loose malloc %d (slot size = %d)\n", sz, slotSize);
142  assert (sz <= slotSize);
143  void * ptr = NULL;
144        chunkType * ch = NULL;
145  // Always try to allocate from the most-full chunk (resetting
146  // lastIndex as we go).
147        lastIndex = emptyFraction - 1; // FIX ME!
148  while (lastIndex >= 0) {
149                ch = myChunks[lastIndex];
150    if (ch == NULL) {
151      lastIndex--;
152    } else {
153      // Got one.
154      break;
155    }
156  }
157  if (lastIndex < 0) {
158                assert (ch == NULL);
159    // There were no chunks available.
160    assert ((space - inUse) == 0);
161    // Make one with memory from the "super" heap.
162                printf ("!!!\n");
163                ch = (chunkType*) theHeap.malloc (chunkSize);
164                ch->setHeap (this);
165                assert (ch->getNumSlotsFree() > 0);
166                printf ("Super malloc %d\n", chunkSize);
167                lastIndex = getFullness(ch);
168                register chunkType*& head = myChunks[lastIndex];
169                assert (head == NULL);
170                ch->setPrev (NULL);
171                ch->setNext (NULL);
172    head = ch;
173    inUse += ch->getNumSlotsInUse();
174    space += ch->getNumSlots();
175                assert (ch->getNumSlotsFree() <= ch->getNumSlots());
176                // FOR NOW!! FIX ME!!!
177                assert (ch->getNumSlotsFree() == ch->getNumSlots());
178                printf ("Space, in use was %d, %d\n", space, inUse);
179                printf ("Space, in use NOW %d, %d\n", space, inUse);
180  }
181        assert (ch != NULL);
182        assert (ch->getNumSlotsFree() > 0);
183        int prevFullness = getFullness (ch);
184        int prevInUse = ch->getNumSlotsInUse();
185        assert (ch->getHeap() == this);
186  ptr = ch->getSlot();
187  inUse++;
188        assert (prevInUse + 1 == ch->getNumSlotsInUse());
189        int newFullness = getFullness (ch);
190        if (prevFullness != newFullness) {
191                int n = update (ch, prevFullness);
192                assert (n == newFullness);
193        }
194  chunkType * bch = (chunkType *) chunkType::getChunk(ptr);
195  assert (bch == ch);
196  assert (ptr != NULL);
197        checkClassInvariant();
198  return ptr;
199}
200
201
202template <int chunkSize, int slotSize, int emptyFraction, class Super>
203void LooseSlotHeap<chunkSize, slotSize, emptyFraction, Super>::free (void * ptr) {
204  chunkType * ch
205    = (chunkType *) chunkType::getChunk (ptr);
206        assert (ch != NULL);
207        (ch->getHeap())->localFree (ptr);
208}
209
210
211template <int chunkSize, int slotSize, int emptyFraction, class Super>
212void LooseSlotHeap<chunkSize, slotSize, emptyFraction, Super>::localFree (void * ptr) {
213        checkClassInvariant();
214        printf ("free! (in use = %d, space = %d)\n", inUse, space);
215  // Mark the slot in the chunk as free.
216  chunkType * ch
217    = (chunkType *) chunkType::getChunk (ptr);
218        assert (ch != NULL);
219        assert (ch->getHeap() == this);
220        int prevFullness = getFullness (ch);
221        int prevInUse = ch->getNumSlotsInUse();
222  ch->putSlot (ptr);
223        inUse--;
224        assert (prevInUse - 1 == ch->getNumSlotsInUse());
225        checkClassInvariant();
226        int newIndex = getFullness (ch);
227        if (prevFullness != newIndex) {
228                int n = update (ch, prevFullness);
229                assert (n == newIndex);
230        }
231  // If we are more than 1/emptyFraction empty,
232  // return a mostly-empty chunk to the super heap.
233  if ((space - inUse > 2 * chunkSize/slotSize)
234                && (emptyFraction * (space - inUse) > space)) {
235                printf ("RETURNING A CHUNK!\n");
236                // Find an empty chunk.
237                int emptyIndex = 0;
238                ch = NULL;
239                while (emptyIndex < emptyFraction) {
240                        ch = myChunks[emptyIndex];
241                        if (ch != NULL)
242                                break;
243                        emptyIndex++;
244                }
245                assert (ch != NULL);
246                checkClassInvariant();
247                ch->setHeap (NULL);
248    // Remove a chunk and give it to the super heap.
249                myChunks[emptyIndex] = myChunks[emptyIndex]->getNext();
250                if (myChunks[emptyIndex] != NULL) {
251                        myChunks[emptyIndex]->setPrev (NULL);
252                }
253                ch->setPrev (NULL);
254                ch->setNext (NULL);
255                // A sanity check on the chunk we're about to return.
256                assert (ch->getNumSlotsFree() >= 0);
257                assert (ch->getNumSlots() >= ch->getNumSlotsFree());
258                printf ("Updating space & in use: was %d, %d (slots in use = %d)\n",
259                        space, inUse, ch->getNumSlotsInUse());
260                space -= ch->getNumSlots();
261                inUse -= ch->getNumSlotsInUse();
262                printf ("Updating space & in use: NOW %d, %d\n", space, inUse);
263                theHeap.free (ch);
264                checkClassInvariant();
265  }
266        checkClassInvariant();
267}
268
269
270// Move a chunk, if necessary, into the right list
271// based on its emptiness.
272template <int chunkSize, int slotSize, int emptyFraction, class Super>
273int LooseSlotHeap<chunkSize, slotSize, emptyFraction, Super>::update (chunkType * ch, int prevIndex)
274{
275  // Move this chunk if necessary.
276#ifndef NDEBUG
277        chunkType * bch = myChunks[prevIndex];
278        while (bch != NULL) {
279                if (bch == ch)
280                        break;
281                bch = bch->getNext();
282        }
283        assert (bch == ch);
284#endif
285  int newIndex = getFullness(ch);
286  // printf ("newIndex = %d\n", newIndex);
287        // Reset last index (for simplicity). // FIX ME??
288  // Remove the chunk from its current list.
289        if (ch == myChunks[prevIndex]) {
290                myChunks[prevIndex] = myChunks[prevIndex]->getNext();
291        }
292        /////   lastIndex = emptyFraction - 1;
293  if (ch->getPrev() != NULL) {
294                ch->getPrev()->setNext(ch->getNext());
295  }
296        if (ch->getNext() != NULL) {
297          ch->getNext()->setPrev(ch->getPrev());
298  }
299  // Add it to the newIndex list.
300  chunkType*& head = myChunks[newIndex];
301  ch->setPrev (NULL);
302  ch->setNext (head);
303  if (head != NULL) {
304    head->setPrev(ch);
305  }
306        head = ch;
307        // Verify that the chunk is in the right list.
308#ifndef NDEBUG
309        bch = myChunks[newIndex];
310        while (bch != NULL) {
311                if (bch == ch)
312                        break;
313                bch = bch->getNext();
314        }
315        assert (bch == ch);
316#endif
317        return newIndex;
318}
319
320
321
322#endif
Note: See TracBrowser for help on using the repository browser.