aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/bfc/freelist.h
blob: dba7e46e24ba5f1f5339370b92389a39b8d0545a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#ifndef _FREELIST_H
#define _FREELIST_H

#include <bfc/wasabi_std.h>
#include <bfc/memblock.h>
#include <bfc/ptrlist.h>

// actual implementation
class FreelistPriv {
protected:
  FreelistPriv();
  ~FreelistPriv();

  void *getRecord(int typesize, int blocksize, int initialblocksize);
  void freeRecord(void *rec);

private:
  int total_allocated;
  typedef uint8_t MBT;
  class FLMemBlock : public MemBlock<MBT> {
  public:
    FLMemBlock(int siz) : MemBlock<MBT>(siz) {
      freelist = getMemory();
      nallocated = 0;
    }
    void *freelist;
    int nallocated;	// # of records assigned from block
  };
  PtrList< FLMemBlock > blocks; // the blocks of mem we alloc from
};

// type-safe template
static const int DEF_BLOCKSIZE=250;
template
<class T, int BLOCKSIZE=DEF_BLOCKSIZE, int INITIALBLOCKSIZE=DEF_BLOCKSIZE, int ALIGNMENT=4>
class Freelist : private FreelistPriv {
public:
  // just returns the memory, you have to call constructor manually
  T *getRecord() {
    return static_cast<T *>(FreelistPriv::getRecord(itemsize(), BLOCKSIZE, INITIALBLOCKSIZE));
  }

  // creates object via default constructor
  T *newRecord() {
    T *ret = getRecord();
#ifdef FORTIFY
#undef new
#endif
    new(ret) T;
#ifdef FORTIFY
#define new ZFortify_New
#endif
    return ret;
  }

  // creates object via 1-parameter constructor
  template<class P1>
  T *newRecord(P1 p1) {
    T *ret = getRecord();
#ifdef FORTIFY
#undef new
#endif
    new(ret) T(p1);
#ifdef FORTIFY
#define new ZFortify_New
#endif
    return ret;
  }

  // just frees it, you have to call destructor manually
  void freeRecord(T *record) { FreelistPriv::freeRecord(record); }

  // calls delete for you, and frees it
  void deleteRecord(T *record) {
    if (record != NULL) {
      record->~T();
      freeRecord(record);
    }
  }

  void deletePtrList(PtrList<T> *list) {
    ASSERT(list != NULL);
    for (int i = 0; i < list->getNumItems(); i++) {
      deleteRecord(list->enumItem(i));
    }
    list->removeAll();
  }

protected:
  int itemsize() { return (sizeof(T) + (ALIGNMENT-1)) - (sizeof(T) % ALIGNMENT); }
};

#endif