1
#ifndef __FWEELIN_MEM_H
2
#define __FWEELIN_MEM_H
7
class PreallocatedType {
8
friend class MemoryManager;
11
// Default number of instances to keep preallocated
12
const static int PREALLOC_DEFAULT_NUM_INSTANCES = 10;
14
// Tells memory manager to start preallocating blocks of this type
15
// Note for each type of preallocated data we can specify
16
// a different number of instances to keep ready for RT consumption
18
// We must provide one instance of the Preallocated class as a reference
19
// This is prealloc_base
21
// If block_mode is 1, an array of instances is used, and unused instances
22
// are recycled instead of new ones constructed.
23
PreallocatedType(MemoryManager *mmgr, Preallocated *prealloc_base,
25
int prealloc_num_instances =
26
PREALLOC_DEFAULT_NUM_INSTANCES,
28
// Stops preallocating this type
31
// Realtime-safe function to get a new instance of this class
32
Preallocated *RTNew();
33
// Realtime-safe function to delete this instance of this class
34
void RTDelete(Preallocated *inst);
36
// Perform any preallocations and pending deletes that are needed!
37
// Called by memory manager
41
// Cleanup- delete all preallocated instances of this type- called
45
inline int GetBlockSize() { return prealloc_num_instances; };
46
inline char GetBusy() { return busy; };
50
char busy; // Busy flag- if we are playing with data structures
51
// the memory manager thread will wait
53
// Actual size of one instance (we can't get it with RTTI, so you have to
57
// Number of instances to keep preallocated
58
int prealloc_num_instances;
60
// Block mode or single instance mode?
62
// Last block index scanned for free instances
65
// List of free instances
66
Preallocated *prealloc_free;
67
// List of instances in use
68
Preallocated *prealloc_inuse;
71
// MemoryManager maintains 2 lists of PreallocatedTypes
72
PreallocatedType *next,
73
*anext; // Next in active list
76
// This class is a base for classes that want to be preallocated
77
// and postdeleted-- classes in which new instances are needed
78
// in realtime-- the memory allocation is done in a nonrealtime thread
80
// One such allocate&delete thread exists for all preallocated types
81
// MemoryManager handles that thread.
83
// Using this class as a base adds some bytes of size to each instance
84
// which might be a concern if you are allocating many instances!
86
friend class PreallocatedType;
89
// Default constructor calls recycle to init this instance
90
Preallocated() : prealloc_mgr(0) {};
91
virtual ~Preallocated() {};
93
void *operator new(size_t s) {
94
printf("ERROR: Preallocated type can not be allocated directly\n");
97
void operator delete(void *d) {
98
//printf("ERROR: Preallocated type can not be deleted directly\n");
101
// We used to give an error message-
102
// now we pass this delete on to RTDelete
103
((Preallocated *) d)->RTDelete();
106
// Realtime-safe function to get a new instance of this class
107
Preallocated *RTNew() {
108
if (prealloc_mgr == 0) { // No mgr, so allocate nonRT way!
109
//printf("WARNING: nonRT Prealloc in RTNew\n");
110
return NewInstance();
113
return prealloc_mgr->RTNew();
116
// Realtime-safe function to delete this instance of this class
118
if (prealloc_mgr == 0) { // No mgr, nonRT delete!
119
//printf("WARNING: nonRT delete in RTDelete\n");
123
prealloc_mgr->RTDelete(this);
126
// Returns the PreallocatedType manager associated with this type
127
PreallocatedType *GetMgr() { return prealloc_mgr; };
130
const static char PREALLOC_BASE_INSTANCE = 0, // Base instance, never deleted
131
PREALLOC_PENDING_USE = 1,
133
PREALLOC_PENDING_DELETE = 3;
135
// This setup function is called from PreallocatedType
136
// after a new instance of Preallocated is created.
137
// It sets up the internal variables in this instance.
138
void SetupPreallocated(PreallocatedType *mgr,
141
prealloc_status = status;
142
predata.prealloc_next = 0;
147
// Code to destroy a block of instances- only called in block mode
148
// This is a workaround because operator delete[] is not virtual
149
// and can not handle our arrays of derived instances
150
#define FWMEM_DEFINE_DELBLOCK virtual void DelBlock() { ::delete[] this; };
151
FWMEM_DEFINE_DELBLOCK;
153
// Code to call new operator for the derived class (nonRT)
154
// All allocation and lengthy initialization can be done here
155
// If this type is allocated in block mode, NewInstance must allocate
156
// not one instance, but an array of instances with prealloc_num_instances
158
virtual Preallocated *NewInstance() = 0;
160
// Code to recycle an old instance to be used again
161
// This is called *only* in block mode when an instance is RTDeleted.
162
// Instead of deleting and constructing instances, we recycle
163
// instances and pass them as new instances.
165
// So initialization code can go here, but this function
167
virtual void Recycle() {};
169
// Status of this instance
170
char prealloc_status;
172
// PreallocatedType that manages the allocation of new instances
173
// ** With a table, this could be optimized out of each instance **
174
PreallocatedType *prealloc_mgr;
178
// Each instance is part of an array. And each array is part of a linked
179
// list. So we have a list of blocks of instances.
180
// The 1st instance in a block points to the next block.
181
// The 2nd instance in a block holds the # of free instances in that block:
182
int prealloc_num_free;
184
// Next instance- or in block mode, next block of instances
185
Preallocated *prealloc_next;
189
class MemoryManager {
195
// Starts managing the specified type
196
void AddType(PreallocatedType *t);
197
// Stops managing the specified type
198
void DelType(PreallocatedType *t);
200
// Wake up the manager thread- something to be done on the specified type
201
void WakeUp(PreallocatedType *t);
206
static void *run_mgr_thread (void *ptr);
208
// List of all PreallocatedTypes we are managing
209
PreallocatedType *pts;
210
// List of all PreallocatedTypes with activity pending
211
PreallocatedType *apts;
213
// Thread to preallocate and postdelete instances
214
pthread_t mgr_thread;
215
pthread_mutex_t mgr_thread_lock;
216
pthread_cond_t mgr_go;