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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2335 - (hide annotations) (download) (as text)
Sat Mar 17 06:19:01 2012 UTC (8 years, 8 months ago) by persson
File MIME type: text/x-c++hdr
File size: 19471 byte(s)
* fixed compilation with gcc 4.7

1 schoenebeck 271 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 persson 2335 * Copyright (C) 2005 - 2012 Christian Schoenebeck *
7 schoenebeck 271 * *
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 schoenebeck 554 #ifdef HAVE_CONFIG_H
28     # include <config.h>
29 schoenebeck 271 #endif
30    
31     // we just use exceptions for debugging, better not in the final realtime thread !
32 schoenebeck 554 #ifndef CONFIG_RT_EXCEPTIONS
33     # define CONFIG_RT_EXCEPTIONS 0
34 schoenebeck 271 #endif
35    
36 schoenebeck 554 #if CONFIG_RT_EXCEPTIONS
37 schoenebeck 271 # include <stdexcept>
38     # include <string>
39 schoenebeck 554 #endif // CONFIG_RT_EXCEPTIONS
40 schoenebeck 271
41 schoenebeck 554 #if CONFIG_DEVMODE
42     # include <string>
43     # include <iostream>
44 schoenebeck 472 const std::string __err_msg_iterator_invalidated = "Pool/RTList iterator invalidated";
45 schoenebeck 554 #endif // CONFIG_DEVMODE
46 schoenebeck 472
47 schoenebeck 1800 const std::string __err_msg_resize_while_in_use = "Pool::resizePool() ERROR: elements still in use!";
48    
49 schoenebeck 271 // 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 schoenebeck 361 template<typename T1>
57 schoenebeck 271 struct _Node {
58 schoenebeck 361 _Node<T1>* next;
59     _Node<T1>* prev;
60     T1* data;
61 schoenebeck 554 #if CONFIG_DEVMODE
62 schoenebeck 361 RTListBase<T1>* list; // list to which this node currently belongs to
63 schoenebeck 554 #endif // CONFIG_DEVMODE
64 schoenebeck 271
65     _Node() {
66     next = NULL;
67     prev = NULL;
68     data = NULL;
69 schoenebeck 554 #if CONFIG_DEVMODE
70 schoenebeck 271 list = NULL;
71 schoenebeck 554 #endif // CONFIG_DEVMODE
72 schoenebeck 271 }
73     };
74     typedef _Node<T> Node;
75    
76     public:
77 schoenebeck 361 template<typename T1>
78 schoenebeck 271 class _Iterator {
79     public:
80     _Iterator() {
81     current = NULL;
82     fallback = NULL;
83 schoenebeck 554 #if CONFIG_DEVMODE
84 schoenebeck 271 list = NULL;
85 schoenebeck 554 #endif // CONFIG_DEVMODE
86 schoenebeck 271 }
87    
88     /// prefix increment op.
89     inline _Iterator& operator++() {
90 schoenebeck 554 #if CONFIG_DEVMODE
91 schoenebeck 472 if (!isValid()) {
92 schoenebeck 554 #if CONFIG_RT_EXCEPTIONS
93 schoenebeck 472 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 schoenebeck 554 #endif // CONFIG_RT_EXCEPTIONS
98 schoenebeck 472 }
99 schoenebeck 554 #endif // CONFIG_DEVMODE
100 schoenebeck 271 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 schoenebeck 472 ++*this; // use prefix operator implementation
109 schoenebeck 271 return preval;
110     }
111    
112     /// prefix decrement op.
113     inline _Iterator& operator--() {
114 schoenebeck 554 #if CONFIG_DEVMODE
115 schoenebeck 472 if (!isValid()) {
116 schoenebeck 554 #if CONFIG_RT_EXCEPTIONS
117 schoenebeck 472 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 schoenebeck 554 #endif // CONFIG_RT_EXCEPTIONS
122     }
123     #endif // CONFIG_DEVMODE
124 schoenebeck 271 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 schoenebeck 472 --*this; // use prefix operator implementation
133 schoenebeck 271 return preval;
134     }
135    
136 schoenebeck 361 inline T1& operator*() {
137 schoenebeck 554 #if CONFIG_DEVMODE
138 schoenebeck 472 if (!isValid()) { // if iterator became invalidated
139 schoenebeck 554 #if CONFIG_RT_EXCEPTIONS
140 schoenebeck 472 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 schoenebeck 554 #endif // CONFIG_RT_EXCEPTIONS
145 schoenebeck 472 }
146 schoenebeck 554 #endif // CONFIG_DEVMODE
147 schoenebeck 271 return *current->data;
148 schoenebeck 554
149 schoenebeck 271 }
150    
151 schoenebeck 361 inline T1* operator->() {
152 schoenebeck 554 #if CONFIG_DEVMODE
153 schoenebeck 472 if (!isValid()) { // if iterator became invalidated
154 schoenebeck 554 #if CONFIG_RT_EXCEPTIONS
155 schoenebeck 472 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 schoenebeck 554 #endif // CONFIG_RT_EXCEPTIONS
160 schoenebeck 472 }
161 schoenebeck 554 #endif // CONFIG_DEVMODE
162     return current->data;
163 schoenebeck 271 }
164    
165 schoenebeck 361 inline bool operator==(const _Iterator<T1> other) {
166 schoenebeck 271 return current == other.current;
167     }
168    
169 schoenebeck 361 inline bool operator!=(const _Iterator<T1> other) {
170 schoenebeck 271 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 schoenebeck 361 inline _Iterator moveToEndOf(RTListBase<T1>* pDstList) {
182 schoenebeck 271 detach();
183     pDstList->append(*this);
184     _Iterator iterOnDstList = _Iterator(current);
185     current = fallback;
186     return iterOnDstList;
187     }
188    
189 schoenebeck 361 inline _Iterator moveToBeginOf(RTListBase<T1>* pDstList) {
190 schoenebeck 271 detach();
191     pDstList->prepend(*this);
192     _Iterator iterOnDstList = _Iterator(current);
193     current = fallback;
194     return iterOnDstList;
195     }
196    
197 schoenebeck 554 #if CONFIG_DEVMODE
198 schoenebeck 271 inline bool isValid() {
199     return current->list == list;
200     }
201 schoenebeck 554 #endif // CONFIG_DEVMODE
202 schoenebeck 271
203     protected:
204     Node* current;
205     Node* fallback;
206     enum dir_t {
207     dir_forward,
208     dir_backward
209     };
210 schoenebeck 554 #if CONFIG_DEVMODE
211 schoenebeck 361 RTListBase<T1>* list;
212 schoenebeck 554 #endif // CONFIG_DEVMODE
213 schoenebeck 271
214     _Iterator(Node* pNode, dir_t direction = dir_forward) {
215     current = pNode;
216     fallback = (direction == dir_forward) ? pNode->prev : pNode->next;
217 schoenebeck 554 #if CONFIG_DEVMODE
218 schoenebeck 271 list = pNode->list;
219 schoenebeck 554 #endif // CONFIG_DEVMODE
220 schoenebeck 271 }
221    
222     inline Node* node() {
223 schoenebeck 554 #if CONFIG_DEVMODE
224     #if CONFIG_RT_EXCEPTIONS
225 schoenebeck 271 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 schoenebeck 554 #endif // CONFIG_RT_EXCEPTIONS
230 schoenebeck 271 #else
231     return current;
232 schoenebeck 554 #endif // CONFIG_DEVMODE
233 schoenebeck 271 }
234    
235     inline void detach() {
236 schoenebeck 361 RTListBase<T1>::detach(*this);
237 schoenebeck 271 }
238    
239 schoenebeck 361 friend class RTListBase<T1>;
240     friend class RTList<T1>;
241     friend class Pool<T1>;
242 schoenebeck 271 };
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 schoenebeck 1800 inline int count() {
266     int elements = 0;
267     for (Iterator it = first(); it != end(); ++it) ++elements;
268     return elements;
269     }
270    
271 schoenebeck 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 schoenebeck 1800 init();
277     }
278    
279     void init() {
280 schoenebeck 271 // 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 schoenebeck 554 #if CONFIG_DEVMODE
288 schoenebeck 271 _begin.list = this;
289     _end.list = this;
290 schoenebeck 554 #endif // CONFIG_DEVMODE
291 schoenebeck 271 }
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 schoenebeck 554 #if CONFIG_DEVMODE
301 schoenebeck 271 pNode->list = this;
302 schoenebeck 554 #endif // CONFIG_DEVMODE
303 schoenebeck 271 }
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 schoenebeck 554 #if CONFIG_DEVMODE
314 schoenebeck 271 for (Node* pNode = pFirst; true; pNode = pNode->next) {
315     pNode->list = this;
316     if (pNode == pLast) break;
317     }
318 schoenebeck 554 #endif // CONFIG_DEVMODE
319 schoenebeck 271 }
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 schoenebeck 554 #if CONFIG_DEVMODE
329 schoenebeck 271 pNode->list = this;
330 schoenebeck 554 #endif // CONFIG_DEVMODE
331 schoenebeck 271 }
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 schoenebeck 554 #if CONFIG_DEVMODE
342 schoenebeck 271 for (Node* pNode = pFirst; true; pNode = pNode->next) {
343     pNode->list = this;
344     if (pNode == pLast) break;
345     }
346 schoenebeck 554 #endif // CONFIG_DEVMODE
347 schoenebeck 271 }
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 schoenebeck 277 friend class _Iterator<T>;
365     friend class RTList<T>;
366 schoenebeck 271 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 iliev 2244
385     /**
386     * Copy constructor
387     */
388     RTList(RTList<T>& list) : RTListBase<T>::RTListBase() {
389     this->pPool = list.pPool;
390 iliev 2247 Iterator it = list.first();
391     Iterator end = list.end();
392 iliev 2244 for(; it != end; ++it) {
393     if (poolIsEmpty()) break;
394     *(allocAppend()) = *it;
395     }
396     }
397 schoenebeck 271
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 persson 2335 this->append(element);
410 schoenebeck 554 #if CONFIG_DEVMODE
411 schoenebeck 271 element.list = this;
412 schoenebeck 554 #endif // CONFIG_DEVMODE
413 schoenebeck 271 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 schoenebeck 554 #if CONFIG_DEVMODE
421 schoenebeck 271 element.list = this;
422 schoenebeck 554 #endif // CONFIG_DEVMODE
423 schoenebeck 271 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 schoenebeck 1800 int poolsize;
455 schoenebeck 271
456     Pool(int Elements) : RTList<T>::RTList(this) {
457 schoenebeck 1800 _init(Elements);
458 schoenebeck 271 }
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 schoenebeck 1800 /**
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 schoenebeck 271 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 schoenebeck 1800
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 schoenebeck 271 };
539    
540     #endif // __LS_POOL_H__

  ViewVC Help
Powered by ViewVC