/[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 2247 - (show annotations) (download) (as text)
Fri Aug 19 11:26:40 2011 UTC (12 years, 7 months ago) by iliev
File MIME type: text/x-c++hdr
File size: 19465 byte(s)
* possibly fixes a compile error on Windows and Mac OS X
  introduced in the previous commit

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

  ViewVC Help
Powered by ViewVC