source: proiecte/swift/trunk/lib/hoard-371/src/heaplayers/experimental/objectmanager.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.0 KB
Line 
1// -*- C++ -*-
2
3/*
4
5  Heap Layers: An Extensible Memory Allocation Infrastructure
6 
7  Copyright (C) 2000-2003 by Emery Berger
8  http://www.cs.umass.edu/~emery
9  emery@cs.umass.edu
10 
11  This program is free software; you can redistribute it and/or modify
12  it under the terms of the GNU General Public License as published by
13  the Free Software Foundation; either version 2 of the License, or
14  (at your option) any later version.
15 
16  This program is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with this program; if not, write to the Free Software
23  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24
25*/
26
27#ifndef _OBJECTMANAGER_H_
28#define _OBJECTMANAGER_H_
29
30#include <stdlib.h>  // for size_t
31
32namespace HL {
33
34class EmptyHeap {};
35
36// The default object manager class.
37
38
39template <class SuperHeap>
40class ObjectManagerBase : public SuperHeap {
41public:
42
43  // Return the object's size.
44  inline static size_t getSize (void * const ptr) {
45    return getObject(ptr)->getSize();
46  }
47
48protected:
49
50  //// accessors ////
51
52  // Return the object's overhead (i.e., in the header).
53  inline static size_t getOverhead (void * const) {
54    return sizeof(AllocatedObject);
55  }
56
57  // Is this object free?
58  inline static bool isFree (void * const ptr) {
59    return getObject(ptr)->isFree();
60  }
61
62
63  // Is the previous object free?
64  inline static bool isPrevFree (void * const ptr) {
65    return getObject(ptr)->isPrevFree();
66  }
67
68  // Previous object
69  inline static void * getPrev (void * const ptr) {
70    return getObject(ptr)->getPrev();
71  }
72
73
74  // Next object
75  inline static void * getNext (void * const ptr) {
76    return getObject(ptr)->getNext();
77  }
78
79
80  //// mutators ////
81       
82  // Instantiate an object in a given space.
83  inline static void * makeObject (void * buf, size_t prevSize, size_t sz) {
84    AllocatedObject * p = new (buf) AllocatedObject (prevSize, sz);
85    return (void *) (p + 1);
86  }
87
88  inline static size_t getPrevSize (void * const ptr) {
89    return getObject(ptr)->getPrevSize();
90  }
91       
92  // Mark this item as free.
93  inline static void markFree (void * ptr) {
94    getObject(ptr)->markFree();
95    getObject(getNext(ptr))->markPrevFree();
96  }
97
98  // Mark this item as in use.
99  inline static void markInUse (void * ptr) {
100    getObject(ptr)->markInUse();
101    getObject(getNext(ptr))->markPrevInUse();
102  }
103
104
105private:
106
107
108  // Change the object's size.
109  inline static void setSize (void * ptr, size_t sz) {
110    getObject(ptr)->setSize (sz);
111  }
112
113  // Change the object's size.
114  inline static void setPrevSize (void * ptr, size_t sz) {
115    getObject(ptr)->setPrevSize (sz);
116  }
117
118
119  // All objects managed by this object manager
120  // are prefaced by a header of type AllocatedObject,
121  // which manages the size of the current & previous allocated objects.
122
123  class AllocatedObject {
124    friend class ObjectManagerBase<SuperHeap>;
125  private:
126    inline AllocatedObject (size_t prevSize, size_t sz)
127      : _sz (sz)
128      , _prevSize (prevSize)
129#if 0 //ndef NDEBUG
130      , _magic ((double) MAGIC_NUMBER)
131#endif
132      {
133        // Set the prev size of the next object.
134        ((AllocatedObject *) ((char *) (this + 1) + _sz))->setPrevSize (sz);
135        assert (!isFree());
136        assert (!isPrevFree());
137      }
138
139    inline size_t getSize (void) const {
140      assert (isValid());
141      return _sz & ~FREE_BIT;
142    }
143    inline void setSize (size_t sz) {
144      assert (sz > 0);
145      assert (isValid());
146      _sz = sz;
147    }
148    inline bool isFree (void) const {
149      assert (isValid());
150      return _sz & FREE_BIT;
151    }
152    inline bool isPrevFree (void) const {
153      assert (isValid());
154      return _prevSize & FREE_BIT;
155    }
156    // Return the previous object (in address order).
157    inline void * getPrev (void) const {
158      assert (isValid());
159      return (void *) ((char *) this - getPrevSize());
160    }
161    // Return the next object (in address order).
162    inline void * getNext (void) const {
163      assert (isValid());
164      return (void *) ((char *) (this+2) + getSize());
165    }
166    inline size_t getPrevSize (void) const {
167      assert (isValid());
168      return _prevSize & ~FREE_BIT;
169    }
170    inline void markFree (void) {
171      assert (isValid());
172      markFree(_sz);
173    }
174    inline void markInUse (void) {
175      assert (isValid());
176      markInUse(_sz);
177    }
178    inline void markPrevFree (void) {
179      assert (isValid());
180      markFree(_prevSize);
181    }
182    inline void markPrevInUse (void) {
183      assert (isValid());
184      markInUse(_prevSize);
185    }
186    inline void setPrevSize (size_t sz) {
187      assert (sz > 0);
188      assert (isValid());
189      _prevSize = sz;
190    }
191  private:
192    enum { FREE_BIT = 1 };
193    enum { MAGIC_NUMBER = 0 };
194
195    int isValid (void) const {
196#if 0 // ndef NDEBUG
197      return (_magic == (double) MAGIC_NUMBER);
198#else
199      return 1; //((_sz & 6) == 0);
200#endif
201    }
202
203    inline static void markInUse (size_t& sz) {
204      sz &= ~FREE_BIT;
205    }
206
207    inline static void markFree (size_t& sz) {
208      sz |= FREE_BIT;
209    }
210
211
212    // The size of the previous object (that is, right behind this one).
213    size_t _prevSize;
214
215    // We steal the last bit of the size field
216    // for free/in use.
217    // If the last bit is 1, the object is free.
218    // Otherwise, it's in use.
219    size_t _sz;
220
221#if 0 //ndef NDEBUG
222    double _magic;
223#endif
224  };
225
226protected:
227  inline static AllocatedObject * getObject (void * const ptr) {
228    return (AllocatedObject *) ptr - 1;
229  }
230};
231
232
233
234template <class SuperHeap>
235class ProvideObjectManager : public ObjectManagerBase<SuperHeap> {
236public:
237  inline void * malloc (size_t sz) {
238    assert (sz > 0);
239    void * ptr = SuperHeap::malloc (sz + getOverhead(NULL));
240    if (ptr == NULL)
241      return NULL;
242    void * p = makeObject (ptr, getPrevSize((char *) ptr + getOverhead(NULL)), sz);
243    markInUse (p);
244    assert (getSize(p) >= sz);
245    assert (getPrevSize(getNext(p)) == getSize(p));
246    return p;
247  }
248
249  inline void free (void * ptr) {
250    int ps = getPrevSize(getNext(ptr));
251    int sz = getSize(ptr);
252    assert (getPrevSize(getNext(ptr)) == getSize(ptr));
253    markFree (ptr);
254    SuperHeap::free ((void *) getObject(ptr));
255  }
256};
257
258
259template <class SuperHeap>
260class ObjectManager : public ObjectManagerBase<SuperHeap> {
261public:
262#if 1
263  inline void * malloc (size_t sz) {
264    void * p = SuperHeap::malloc (sz);
265    if (p != NULL) {
266      assert (getSize(p) >= sz);
267      //setPrevSize(getNext(p), getSize(p));
268      markInUse (p);
269    }
270    return p;
271  }
272
273  inline void free (void * ptr) {
274    markFree (ptr);
275    SuperHeap::free (ptr);
276  }
277#endif
278};
279
280
281
282class ObjectManagerWrapper {
283public:
284  template <class S>
285  class Manager : public ObjectManager<S> {};
286};
287
288
289class ProvideObjectManagerWrapper {
290public:
291  template <class S>
292  class Manager : public ProvideObjectManager<S> {};
293};
294
295template <class S>
296class NOP : public S {};
297
298class NullObjectManagerWrapper {
299public:
300  template <class S>
301  class Manager : public NOP<S> {};
302};
303
304
305/*
306
307  This ObjectManagerHeap is a tortuous work-around
308  for a bug in Visual C++ 6.0 that finally allows us
309  to pass ObjectManager wrappers as template arguments.
310
311  This can go away once support is added for nested templates.
312
313  Wrappers look like this:
314
315  class Wrap1 {
316  public:
317        template <class S>
318                class Manager : public ObjectManager<S> {};
319  };
320
321  */
322
323
324#if __SVR4
325template <class SuperHeap, class OMWrapper>
326class SelectObjectManagerHeap {
327public:
328  class TheHeap : public OMWrapper::Manager<SuperHeap> {};
329};
330
331#else
332template <class SuperHeap, class OMWrapper>
333class SelectObjectManagerHeap  {
334public:
335  class ObjectManagerHeapProxy1 : public OMWrapper {
336  public:
337    template <class A> class Manager {};
338  };
339
340  class ObjectManagerHeapProxy2 : public ObjectManagerHeapProxy1 {
341  private:
342    typedef typename OMWrapper::Manager<SuperHeap> ManageFoo;
343  public:
344    class ManageMe : public ManageFoo {};
345  };
346
347  class TheHeap : public ObjectManagerHeapProxy2::ManageMe {};
348};
349#endif
350
351};
352
353#endif
354
Note: See TracBrowser for help on using the repository browser.