1 //
2 // pool.h
3 //
4 // Copyright (C) 1996 Limit Point Systems, Inc.
5 //
6 // Author: Curtis Janssen <cljanss@limitpt.com>
7 // Maintainer: LPS
8 //
9 // This file is part of the SC Toolkit.
10 //
11 // The SC Toolkit is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU Library General Public License as published by
13 // the Free Software Foundation; either version 2, or (at your option)
14 // any later version.
15 //
16 // The SC Toolkit 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 Library General Public License for more details.
20 //
21 // You should have received a copy of the GNU Library General Public License
22 // along with the SC Toolkit; see the file COPYING.LIB.  If not, write to
23 // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 //
25 // The U.S. Government is granted a limited license as per AL 91-7.
26 //
27 
28 #ifdef __GNUC__
29 #pragma interface
30 #endif
31 
32 #ifndef _util_group_pool_h
33 #define _util_group_pool_h
34 
35 #include <stdlib.h>
36 #include <new>
37 #include <iostream>
38 
39 #include <util/misc/exenv.h>
40 
41 #undef DEBUG_POOL
42 
43 namespace sc {
44 
45 const int pool_data_alignment_bit = 3;
46 //const int pool_data_alignment_bit = 14;
47 const size_t pool_data_alignment = 1<<pool_data_alignment_bit;
48 inline size_t
align_pool_data(size_t size)49 align_pool_data(size_t size)
50 {
51   return (size + pool_data_alignment - 1)
52       & (~ (pool_data_alignment - 1));
53 }
54 inline void*
align_pool_data(void * ptr)55 align_pool_data(void* ptr)
56 {
57   return (void*)( (unsigned long) ((char*)ptr + pool_data_alignment - 1)
58                  & (~ (pool_data_alignment - 1)));
59 }
60 inline size_t
align_pool_data_downward(size_t size)61 align_pool_data_downward(size_t size)
62 {
63   return size & (~ (pool_data_alignment - 1));
64 }
65 inline void*
align_pool_data_downward(void * ptr)66 align_pool_data_downward(void* ptr)
67 {
68   return (void*) ( (unsigned long) ptr & (~ (pool_data_alignment - 1)));
69 }
70 
71 // ////////////////////////////////////////////////////////////////////////////
72 
73 class PoolData;
74 struct FreeData {
75     PoolData* next_free_;
76     PoolData* prev_free_;
77 };
78 
79 // ////////////////////////////////////////////////////////////////////////////
80 
81 struct UsedData {
82     unsigned int flags;
83     unsigned int held_:16;
84     int priority_:15;
85     unsigned int fixed_:1;
86 };
87 
88 // ////////////////////////////////////////////////////////////////////////////
89 
90 class PoolData {
91   public:
92     enum {magic = 0x1f1d1e1c};
93     int magic_;
94     size_t size_;
95     unsigned int free_:1;
96     unsigned int flags_:15;
97   private:
98     PoolData* next_;
99     PoolData* prev_;
100   public:
101     union {
102         FreeData f;
103         UsedData u;
104     };
105 
106     // Allocates a chunk of free memory, only initializing the size.
107     PoolData(size_t size);
108 
109     PoolData* next();
110     PoolData* prev();
111 
112     void next(PoolData*);
113     void prev(PoolData*);
114     void prev_next(PoolData*,PoolData*);
115 
116     PoolData* next_free();
117     PoolData* prev_free();
118 
119     void next_free(PoolData*);
120     void prev_free(PoolData*);
121     void prev_next_free(PoolData*,PoolData*);
122 
123     void set_magic(int = magic);
124 
125     // This new can only be called with aligned memory.
126     //void* operator new(size_t size, void* placement);
127     void* data();
128 
129     void check(void*lower=(void*)0x0,void*upper=(void*)0x7fffffffL);
130 };
131 
132 const int PoolData_aligned_size = (sizeof(PoolData) + pool_data_alignment - 1)
133     & (~ (pool_data_alignment - 1));
data()134 inline void* PoolData::data()
135 {
136   return (void*)(((char*)this) + PoolData_aligned_size);
137 }
138 
139 inline PoolData*
next()140 PoolData::next()
141 {
142   return next_;
143 }
144 
145 inline PoolData*
prev()146 PoolData::prev()
147 {
148   return prev_;
149 }
150 
151 inline void
next(PoolData * p)152 PoolData::next(PoolData*p)
153 {
154   next_ = p;
155 #ifdef DEBUG_POOL
156   if (next_ && prev_ && (next_ < prev_)) {
157       ExEnv::errn() << "PoolData::next(PoolData*): next < prev" << endl;
158       abort();
159     }
160 #endif
161 }
162 
163 inline void
prev(PoolData * p)164 PoolData::prev(PoolData*p)
165 {
166   prev_ = p;
167 #ifdef DEBUG_POOL
168   if (next_ && prev_ && (next_ < prev_)) {
169       ExEnv::errn() << "PoolData::prev(PoolData*): next < prev" << endl;
170       abort();
171     }
172 #endif
173 }
174 
175 inline void
prev_next(PoolData * p,PoolData * n)176 PoolData::prev_next(PoolData*p,PoolData*n)
177 {
178   prev_ = p;
179   next_ = n;
180 #ifdef DEBUG_POOL
181   if (next_ && prev_ && (next_ < prev_)) {
182       ExEnv::errn() << "PoolData::prev_next: next < prev" << endl;
183       abort();
184     }
185 #endif
186 }
187 
188 // ////
189 
190 inline PoolData*
next_free()191 PoolData::next_free()
192 {
193 #ifdef DEBUG_POOL
194   if (!free_) {
195       ExEnv::errn() << "PoolData::next_free(): datum is not free" << endl;
196       abort();
197     }
198 #endif
199   return f.next_free_;
200 }
201 
202 inline PoolData*
prev_free()203 PoolData::prev_free()
204 {
205 #ifdef DEBUG_POOL
206   if (!free_) {
207       ExEnv::errn() << "PoolData::prev_free(): datum is not free" << endl;
208       abort();
209     }
210 #endif
211   return f.prev_free_;
212 }
213 
214 inline void
next_free(PoolData * p)215 PoolData::next_free(PoolData*p)
216 {
217 #ifdef DEBUG_POOL
218   if (!free_) {
219       ExEnv::errn() << "PoolData::next_free(PoolData*): datum is not free" << endl;
220       abort();
221     }
222 #endif
223   f.next_free_ = p;
224 }
225 
226 inline void
prev_free(PoolData * p)227 PoolData::prev_free(PoolData*p)
228 {
229 #ifdef DEBUG_POOL
230   if (!free_) {
231       ExEnv::errn() << "PoolData::prev_free(PoolData*): datum is not free" << endl;
232       abort();
233     }
234 #endif
235   f.prev_free_ = p;
236 }
237 
238 inline void
prev_next_free(PoolData * p,PoolData * n)239 PoolData::prev_next_free(PoolData*p,PoolData*n)
240 {
241 #ifdef DEBUG_POOL
242   if (!free_) {
243       ExEnv::errn() << "PoolData::prev_next_free: datum is not free" << endl;
244       abort();
245     }
246 #endif
247   f.prev_free_ = p;
248   f.next_free_ = n;
249 }
250 
251 inline
PoolData(size_t size)252 PoolData::PoolData(size_t size):
253   magic_(magic),
254   size_(size-PoolData_aligned_size)
255 {
256 }
257 
258 inline void
set_magic(int magic_a)259 PoolData::set_magic(int magic_a)
260 {
261   magic_ = magic_a;
262 }
263 
264 // ////////////////////////////////////////////////////////////////////////////
265 
266 class Pool {
267   protected:
268     enum { freelist_size = sizeof(size_t)*8 };
269     PoolData* freelist_[freelist_size];
270 
271     size_t size_;
272 
273     PoolData* firstdatum_;
274     PoolData* voidptr_to_pd(void*d);
275 
276     int freelist_find_slot(size_t);
277     void freelist_add(PoolData*);
278     void freelist_del(PoolData*);
279   public:
280     Pool(size_t);
281     ~Pool();
282 
283 //     void* operator new(size_t size, void* placement) { return placement; }
284 
285 //     Handle& allocate_handle(size_t size, int priority = 0);
286 //     void release(Handle&);
287 
size()288     size_t size() { return size_; }
289 
290     void* allocate(size_t size);
291     void release(void*d);
292     double* allocate_double(size_t n);
293     void release(double*d);
294     int* allocate_int(size_t n);
295     void release(int*d);
296     void print(std::ostream&o=ExEnv::out0());
297     void check();
298 };
299 
300 inline PoolData*
voidptr_to_pd(void * d)301 Pool::voidptr_to_pd(void*d)
302 {
303   return (PoolData*)((char*)d - PoolData_aligned_size);
304 }
305 
306 inline double*
allocate_double(size_t n)307 Pool::allocate_double(size_t n)
308 {
309   return (double*) allocate(n*sizeof(double));
310 }
311 
312 inline void
release(double * d)313 Pool::release(double*d)
314 {
315   release((void*)d);
316 }
317 inline int*
allocate_int(size_t n)318 Pool::allocate_int(size_t n)
319 {
320   return (int*) allocate(n*sizeof(int));
321 }
322 inline void
release(int * d)323 Pool::release(int*d)
324 {
325   release((void*)d);
326 }
327 
328 }
329 
330 #endif
331 
332 
333 // Local Variables:
334 // mode: c++
335 // c-file-style: "CLJ"
336 // End:
337