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

Last change on this file since 176 was 176, checked in by (none), 14 years ago
  • imported repo from "guagal"
File size: 5.4 KB
Line 
1// -*- C++ -*-
2
3#ifndef _EMPTYCLASS_H_
4#define _EMPTYCLASS_H_
5
6#include <stdio.h> // for stderr
7#include "check.h"
8#include "array.h"
9#include "hldefines.h"
10
11/**
12 * @class EmptyClass
13 * @brief Maintains superblocks organized by emptiness.
14 */
15
16namespace Hoard {
17
18template <class SuperblockType_,
19          int EmptinessClasses>
20class EmptyClass {
21
22  enum { SuperblockSize = sizeof(SuperblockType_) };
23
24public:
25
26  typedef SuperblockType_ SuperblockType;
27
28  EmptyClass (void)
29  {
30    for (int i = 0; i <= EmptinessClasses + 1; i++) {
31      _available(i) = 0;
32    }
33  }
34
35  void dumpStats (void) {
36    for (int i = 0; i <= EmptinessClasses + 1; i++) {
37      SuperblockType * s = _available(i);
38      if (s) {
39        fprintf (stderr, "EmptyClass: emptiness class = %d\n", i);
40        while (s) {
41          s->dumpStats();
42          s = s->getNext();
43        }
44      }
45    }
46  }
47
48
49  SuperblockType * getEmpty (void) {
50    Check<EmptyClass, MyChecker> check (this);
51    SuperblockType * s = _available(0);
52    if (s && 
53        (s->getObjectsFree() == s->getTotalObjects())) {
54      // Got an empty one. Remove it.
55      _available(0) = s->getNext();
56      if (_available(0)) {
57        _available(0)->setPrev (0);
58      }
59      s->setPrev (0);
60      s->setNext (0);
61      return s;
62    }
63    return 0;
64  }
65
66  SuperblockType * get (void) {
67    Check<EmptyClass, MyChecker> check (this);
68    // Return as empty a superblock as possible
69    // by iterating from the emptiest to the fullest available class.
70    for (int n = 0; n < EmptinessClasses + 1; n++) {
71      SuperblockType * s = _available(n);
72      while (s) {
73        assert (s->isValidSuperblock());
74        // Got one. Remove it.
75        _available(n) = s->getNext();
76        if (_available(n)) {
77          _available(n)->setPrev (0);
78        }
79        s->setPrev (0);
80        s->setNext (0);
81
82#ifndef NDEBUG
83        // Verify that this superblock is *gone* from the lists.
84        for (int z = 0; z < EmptinessClasses + 1; z++) {
85          SuperblockType * p = _available(z);
86          while (p) {
87            assert (p != s);
88            p = p->getNext();
89          }
90        }
91#endif
92
93        // Ensure that we return a superblock that is as free as
94        // possible.
95        int cl = getFullness (s);
96        if (cl > n) {
97          put (s);
98          SuperblockType * sNew = _available(n);
99          assert (s != sNew);
100          s = sNew;
101        } else {
102          return s;
103        }
104      }
105    }
106    return 0;
107  }
108
109  void put (SuperblockType * s) {
110    Check<EmptyClass, MyChecker> check (this);
111
112#ifndef NDEBUG
113    // Check to verify that this superblock is not already on one of the lists.
114    for (int n = 0; n <= EmptinessClasses + 1; n++) {
115      SuperblockType * p = _available(n);
116      while (p) {
117        assert (p != s);
118        p = p->getNext();
119      }
120    }
121#endif
122
123    // Put on the appropriate available list.
124    int cl = getFullness (s);
125
126    //    printf ("put %x, cl = %d\n", s, cl);
127    s->setPrev (0);
128    s->setNext (_available(cl));
129    if (_available(cl)) {
130      _available(cl)->setPrev (s);
131    }
132    _available(cl) = s;
133  }
134
135  INLINE MALLOC_FUNCTION void * malloc (size_t sz) {
136    // Malloc from the fullest superblock first.
137    for (int i = EmptinessClasses; i >= 0; i--) {
138      SuperblockType * s = _available(i);
139      // printf ("i\n");
140      if (s) {
141        int oldCl = getFullness (s);
142        void * ptr = s->malloc (sz);
143        int newCl = getFullness (s);
144        if (ptr) {
145          if (oldCl != newCl) {
146            transfer (s, oldCl, newCl);
147          }
148          return ptr;
149        }
150      }
151    }
152    return NULL;
153  }
154
155  INLINE void free (void * ptr) {
156    Check<EmptyClass, MyChecker> check (this);
157    SuperblockType * s = getSuperblock (ptr);
158    int oldCl = getFullness (s);
159    s->free (ptr);
160    int newCl = getFullness (s);
161
162    if (oldCl != newCl) {
163      // Transfer.
164      transfer (s, oldCl, newCl);
165    }
166  }
167
168  /// Find the superblock (by bit-masking) that holds a given pointer.
169  static INLINE SuperblockType * getSuperblock (void * ptr) {
170    return SuperblockType::getSuperblock (ptr);
171  }
172
173private:
174
175  void transfer (SuperblockType * s, int oldCl, int newCl)
176  {
177    SuperblockType * prev = s->getPrev();
178    SuperblockType * next = s->getNext();
179    if (prev) { prev->setNext (next); }
180    if (next) { next->setPrev (prev); }
181    if (s == _available(oldCl)) {
182      assert (prev == 0);
183      _available(oldCl) = next;
184    }
185    s->setNext (_available(newCl));
186    s->setPrev (0);
187    if (_available(newCl)) { _available(newCl)->setPrev (s); }
188    _available(newCl) = s;
189  }
190
191  static INLINE int getFullness (SuperblockType * s) {
192    // Completely full = EmptinessClasses + 1
193    // Completely empty (all available) = 0
194    int total = s->getTotalObjects();
195    int free = s->getObjectsFree();
196    if (total == free) {
197      return 0;
198    } else {
199      return 1 + (EmptinessClasses * (total - free)) / total;
200    }
201  }
202
203  /// Forward declarations for the sanity checker.
204  /// @sa Check
205  class MyChecker;
206  friend class MyChecker;
207
208  /// Precondition and postcondition checking.
209  class MyChecker {
210  public:
211#ifndef NDEBUG
212    static void precondition (EmptyClass * e) {
213      e->sanityCheckPre();
214    }
215    static void postcondition (EmptyClass * e) {
216      e->sanityCheck();
217    }
218#else
219    static void precondition (EmptyClass *) {}
220    static void postcondition (EmptyClass *) {}
221#endif
222  };
223
224  void sanityCheckPre (void) { sanityCheck(); }
225
226  void sanityCheck (void) {
227    for (int i = 0; i <= EmptinessClasses + 1; i++) {
228      SuperblockType * s = _available(i);
229      while (s) {
230        assert (getFullness(s) == i);
231        s = s->getNext();
232      }
233    }
234  }
235
236  /// The bins of superblocks, by emptiness class.
237  /// @note index 0 = completely empty, EmptinessClasses + 1 = full
238  Array<EmptinessClasses + 2, SuperblockType *> _available;
239
240};
241
242}
243
244
245#endif
Note: See TracBrowser for help on using the repository browser.