/[svn]/linuxsampler/trunk/src/common/Pool.h
ViewVC logotype

Contents of /linuxsampler/trunk/src/common/Pool.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 478 - (show annotations) (download) (as text)
Sat Mar 19 09:31:46 2005 UTC (19 years, 1 month ago) by persson
File MIME type: text/x-c++hdr
File size: 16751 byte(s)
* fixed a compilation error in Pool.h (gcc 3.4.3)

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20 * MA 02111-1307 USA *
21 ***************************************************************************/
22
23 #ifndef __LS_POOL_H__
24 #define __LS_POOL_H__
25
26 #ifndef DEVMODE
27 # include "global.h" // just to check if we should compile in 'DEVMODE'
28 #endif
29
30 // we just use exceptions for debugging, better not in the final realtime thread !
31 #ifndef USE_EXCEPTIONS
32 # define USE_EXCEPTIONS 0
33 #endif
34
35 #if USE_EXCEPTIONS
36 # include <stdexcept>
37 # include <string>
38 #endif // USE_EXCEPTIONS
39
40 #if DEVMODE
41 const std::string __err_msg_iterator_invalidated = "Pool/RTList iterator invalidated";
42 # include <iostream>
43 #endif
44
45 // just symbol prototyping
46 template<typename T> class Pool;
47 template<typename T> class RTList;
48
49 template<typename T>
50 class RTListBase {
51 protected:
52 template<typename T1>
53 struct _Node {
54 _Node<T1>* next;
55 _Node<T1>* prev;
56 T1* data;
57 #if DEVMODE
58 RTListBase<T1>* list; // list to which this node currently belongs to
59 #endif // DEVMODE
60
61 _Node() {
62 next = NULL;
63 prev = NULL;
64 data = NULL;
65 #if DEVMODE
66 list = NULL;
67 #endif // DEVMODE
68 }
69 };
70 typedef _Node<T> Node;
71
72 public:
73 template<typename T1>
74 class _Iterator {
75 public:
76 _Iterator() {
77 current = NULL;
78 fallback = NULL;
79 #if DEVMODE
80 list = NULL;
81 #endif // DEVMODE
82 }
83
84 /// prefix increment op.
85 inline _Iterator& operator++() {
86 #if DEVMODE
87 if (!isValid()) {
88 #if USE_EXCEPTIONS
89 throw std::runtime_error(__err_msg_iterator_invalidated);
90 #else
91 std::cerr << __err_msg_iterator_invalidated << std::endl << std::flush;
92 return *(_Iterator*)NULL; // force segfault if iterator became invalidated
93 #endif // USE_EXCEPTIONS
94 }
95 #endif // DEVMODE
96 fallback = current;
97 current = current->next;
98 return *this;
99 }
100
101 /// postfix increment op.
102 inline _Iterator operator++(int) {
103 _Iterator preval = *this;
104 ++*this; // use prefix operator implementation
105 return preval;
106 }
107
108 /// prefix decrement op.
109 inline _Iterator& operator--() {
110 #if DEVMODE
111 if (!isValid()) {
112 #if USE_EXCEPTIONS
113 throw std::runtime_error(__err_msg_iterator_invalidated);
114 #else
115 std::cerr << __err_msg_iterator_invalidated << std::endl << std::flush;
116 return *(_Iterator*)NULL; // force segfault if iterator became invalidated
117 #endif // USE_EXCEPTIONS
118 }
119 #endif // DEVMODE
120 fallback = current;
121 current = current->prev;
122 return *this;
123 }
124
125 /// postfix decrement op.
126 inline _Iterator operator--(int) {
127 _Iterator preval = *this;
128 --*this; // use prefix operator implementation
129 return preval;
130 }
131
132 inline T1& operator*() {
133 #if DEVMODE
134 if (!isValid()) { // if iterator became invalidated
135 #if USE_EXCEPTIONS
136 throw std::runtime_error(__err_msg_iterator_invalidated);
137 #else
138 std::cerr << __err_msg_iterator_invalidated << std::endl << std::flush;
139 return *((T1*)NULL); // force segfault if iterator became invalidated
140 #endif // USE_EXCEPTIONS
141 }
142 #endif // DEVMODE
143 return *current->data;
144
145 }
146
147 inline T1* operator->() {
148 #if DEVMODE
149 if (!isValid()) { // if iterator became invalidated
150 #if USE_EXCEPTIONS
151 throw std::runtime_error(__err_msg_iterator_invalidated);
152 #else
153 std::cerr << __err_msg_iterator_invalidated << std::endl << std::flush;
154 return (T1*)NULL; // force segfault if iterator became invalidated
155 #endif // USE_EXCEPTIONS
156 }
157 #endif // DEVMODE
158 return current->data;
159 }
160
161 inline bool operator==(const _Iterator<T1> other) {
162 return current == other.current;
163 }
164
165 inline bool operator!=(const _Iterator<T1> other) {
166 return current != other.current;
167 }
168
169 inline operator bool() const {
170 return current && current->data;
171 }
172
173 inline bool operator!() const {
174 return !(current && current->data);
175 }
176
177 inline _Iterator moveToEndOf(RTListBase<T1>* pDstList) {
178 detach();
179 pDstList->append(*this);
180 _Iterator iterOnDstList = _Iterator(current);
181 current = fallback;
182 return iterOnDstList;
183 }
184
185 inline _Iterator moveToBeginOf(RTListBase<T1>* pDstList) {
186 detach();
187 pDstList->prepend(*this);
188 _Iterator iterOnDstList = _Iterator(current);
189 current = fallback;
190 return iterOnDstList;
191 }
192
193 #if DEVMODE
194 inline bool isValid() {
195 return current->list == list;
196 }
197 #endif // DEVMODE
198
199 protected:
200 Node* current;
201 Node* fallback;
202 enum dir_t {
203 dir_forward,
204 dir_backward
205 };
206 #if DEVMODE
207 RTListBase<T1>* list;
208 #endif // DEVMODE
209
210 _Iterator(Node* pNode, dir_t direction = dir_forward) {
211 current = pNode;
212 fallback = (direction == dir_forward) ? pNode->prev : pNode->next;
213 #if DEVMODE
214 list = pNode->list;
215 #endif // DEVMODE
216 }
217
218 inline Node* node() {
219 #if DEVMODE
220 #if USE_EXCEPTIONS
221 if (isValid()) return current;
222 else throw std::runtime_error(__err_msg_iterator_invalidated);
223 #else
224 return (isValid()) ? current : (Node*)NULL; // force segfault if iterator became invalidated
225 #endif // USE_EXCEPTIONS
226 #else
227 return current;
228 #endif // DEVMODE
229 }
230
231 inline void detach() {
232 RTListBase<T1>::detach(*this);
233 }
234
235 friend class RTListBase<T1>;
236 friend class RTList<T1>;
237 friend class Pool<T1>;
238 };
239 typedef _Iterator<T> Iterator;
240
241 inline Iterator first() {
242 return Iterator(_begin.next, Iterator::dir_forward);
243 }
244
245 inline Iterator last() {
246 return Iterator(_end.prev, Iterator::dir_backward);
247 }
248
249 inline Iterator begin() {
250 return Iterator(&_begin, Iterator::dir_forward);
251 }
252
253 inline Iterator end() {
254 return Iterator(&_end, Iterator::dir_backward);
255 }
256
257 inline bool isEmpty() {
258 return _begin.next == &_end;
259 }
260
261 protected:
262 Node _begin; // fake node (without data) which represents the begin of the list - not the first element!
263 Node _end; // fake node (without data) which represents the end of the list - not the last element!
264
265 RTListBase() {
266 // initialize boundary nodes
267 _begin.prev = &_begin;
268 _begin.next = &_end;
269 _begin.data = NULL;
270 _end.next = &_end;
271 _end.prev = &_begin;
272 _end.data = NULL;
273 #if DEVMODE
274 _begin.list = this;
275 _end.list = this;
276 #endif // DEVMODE
277 }
278
279 inline void append(Iterator itElement) {
280 Node* pNode = itElement.current;
281 Node* last = _end.prev;
282 last->next = pNode;
283 pNode->prev = last; // if a segfault happens here, then because 'itElement' Iterator became invalidated
284 pNode->next = &_end;
285 _end.prev = pNode;
286 #if DEVMODE
287 pNode->list = this;
288 #endif // DEVMODE
289 }
290
291 inline void append(Iterator itFirst, Iterator itLast) {
292 Node* pFirst = itFirst.current;
293 Node* pLast = itLast.current;
294 Node* last = _end.prev;
295 last->next = pFirst;
296 pFirst->prev = last; // if a segfault happens here, then because 'itFirst' Iterator became invalidated
297 pLast->next = &_end; // if a segfault happens here, then because 'itLast' Iterator became invalidated
298 _end.prev = pLast;
299 #if DEVMODE
300 for (Node* pNode = pFirst; true; pNode = pNode->next) {
301 pNode->list = this;
302 if (pNode == pLast) break;
303 }
304 #endif // DEVMODE
305 }
306
307 inline void prepend(Iterator itElement) {
308 Node* pNode = itElement.current;
309 Node* first = _begin.next;
310 _begin.next = pNode;
311 pNode->prev = &_begin; // if a segfault happens here, then because 'itElement' Iterator became invalidated
312 pNode->next = first;
313 first->prev = pNode;
314 #if DEVMODE
315 pNode->list = this;
316 #endif // DEVMODE
317 }
318
319 inline void prepend(Iterator itFirst, Iterator itLast) {
320 Node* pFirst = itFirst.current;
321 Node* pLast = itLast.current;
322 Node* first = _begin.next;
323 _begin.next = pFirst;
324 pFirst->prev = &_begin; // if a segfault happens here, then because 'itFirst' Iterator became invalidated
325 pLast->next = first; // if a segfault happens here, then because 'itLast' Iterator became invalidated
326 first->prev = pLast;
327 #if DEVMODE
328 for (Node* pNode = pFirst; true; pNode = pNode->next) {
329 pNode->list = this;
330 if (pNode == pLast) break;
331 }
332 #endif // DEVMODE
333 }
334
335 static inline void detach(Iterator itElement) {
336 Node* pNode = itElement.node();
337 Node* prev = pNode->prev; // if a segfault happens here, then because 'itElement' Iterator became invalidated
338 Node* next = pNode->next;
339 prev->next = next;
340 next->prev = prev;
341 }
342
343 static inline void detach(Iterator itFirst, Iterator itLast) {
344 Node* prev = itFirst.node()->prev; // if a segfault happens here, then because 'itFirst' Iterator became invalidated
345 Node* next = itLast.node()->next; // if a segfault happens here, then because 'itLast' Iterator became invalidated
346 prev->next = next;
347 next->prev = prev;
348 }
349
350 friend class _Iterator<T>;
351 friend class RTList<T>;
352 friend class Pool<T>;
353 };
354
355 template<typename T>
356 class RTList : public RTListBase<T> {
357 public:
358 typedef typename RTListBase<T>::Node Node;
359 typedef typename RTListBase<T>::Iterator Iterator;
360
361 /**
362 * Constructor
363 *
364 * @param pPool - pool this list uses for allocation and
365 * deallocation of elements
366 */
367 RTList(Pool<T>* pPool) : RTListBase<T>::RTListBase() {
368 this->pPool = pPool;
369 }
370
371 virtual ~RTList() {
372 clear();
373 }
374
375 inline bool poolIsEmpty() {
376 return pPool->poolIsEmpty();
377 }
378
379 inline Iterator allocAppend() {
380 if (pPool->poolIsEmpty()) return RTListBase<T>::begin();
381 Iterator element = pPool->alloc();
382 append(element);
383 #if DEVMODE
384 element.list = this;
385 #endif // DEVMODE
386 return element;
387 }
388
389 inline Iterator allocPrepend() {
390 if (pPool->poolIsEmpty()) return RTListBase<T>::end();
391 Iterator element = pPool->alloc();
392 prepend(element);
393 #if DEVMODE
394 element.list = this;
395 #endif // DEVMODE
396 return element;
397 }
398
399 inline void free(Iterator& itElement) {
400 itElement.detach();
401 pPool->freeToPool(itElement);
402 itElement.current = itElement.fallback;
403 }
404
405 inline void clear() {
406 if (!RTListBase<T>::isEmpty()) {
407 Node* first = RTListBase<T>::_begin.next;
408 Node* last = RTListBase<T>::_end.prev;
409 RTListBase<T>::detach(first, last);
410 pPool->freeToPool(first, last);
411 }
412 }
413
414 protected:
415 Pool<T>* pPool;
416 };
417
418 template<typename T>
419 class Pool : public RTList<T> {
420 public:
421 typedef typename RTList<T>::Node Node;
422 typedef typename RTList<T>::Iterator Iterator;
423
424 Node* nodes;
425 T* data;
426 RTListBase<T> freelist; // not yet allocated elements
427
428 Pool(int Elements) : RTList<T>::RTList(this) {
429 data = new T[Elements];
430 nodes = new Node[Elements];
431 for (int i = 0; i < Elements; i++) {
432 nodes[i].data = &data[i];
433 freelist.append(&nodes[i]);
434 }
435 }
436
437 virtual ~Pool() {
438 if (nodes) delete[] nodes;
439 if (data) delete[] data;
440 }
441
442 inline bool poolIsEmpty() {
443 return freelist.isEmpty();
444 }
445
446 protected:
447 // caution: assumes pool (that is freelist) is not empty!
448 inline Iterator alloc() {
449 Iterator element = freelist.last();
450 element.detach();
451 return element;
452 }
453
454 inline void freeToPool(Iterator itElement) {
455 freelist.append(itElement);
456 }
457
458 inline void freeToPool(Iterator itFirst, Iterator itLast) {
459 freelist.append(itFirst, itLast);
460 }
461
462 friend class RTList<T>;
463 };
464
465 #endif // __LS_POOL_H__

  ViewVC Help
Powered by ViewVC