/[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 361 - (hide annotations) (download) (as text)
Wed Feb 9 01:22:18 2005 UTC (19 years, 2 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 16038 byte(s)
* bunch of fixes for OSX (patch by Stephane Letz)

1 schoenebeck 271 /***************************************************************************
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     const std::string __err_msg_iterator_invalidated = "Pool/RTList iterator invalidated";
39     #endif // USE_EXCEPTIONS
40    
41     // just symbol prototyping
42     template<typename T> class Pool;
43     template<typename T> class RTList;
44    
45     template<typename T>
46     class RTListBase {
47     protected:
48 schoenebeck 361 template<typename T1>
49 schoenebeck 271 struct _Node {
50 schoenebeck 361 _Node<T1>* next;
51     _Node<T1>* prev;
52     T1* data;
53 schoenebeck 271 #if DEVMODE
54 schoenebeck 361 RTListBase<T1>* list; // list to which this node currently belongs to
55 schoenebeck 271 #endif // DEVMODE
56    
57     _Node() {
58     next = NULL;
59     prev = NULL;
60     data = NULL;
61     #if DEVMODE
62     list = NULL;
63     #endif // DEVMODE
64     }
65     };
66     typedef _Node<T> Node;
67    
68     public:
69 schoenebeck 361 template<typename T1>
70 schoenebeck 271 class _Iterator {
71     public:
72     _Iterator() {
73     current = NULL;
74     fallback = NULL;
75     #if DEVMODE
76     list = NULL;
77     #endif // DEVMODE
78     }
79    
80     /// prefix increment op.
81     inline _Iterator& operator++() {
82     #if DEVMODE
83     #if USE_EXCEPTIONS
84     if (!isValid()) throw std::runtime_error(__err_msg_iterator_invalidated);
85     #else
86     if (!isValid()) return *(_Iterator*)NULL; // force segfault if iterator became invalidated
87     #endif // USE_EXCEPTIONS
88     #endif // DEVMODE
89     fallback = current;
90     current = current->next;
91     return *this;
92     }
93    
94     /// postfix increment op.
95     inline _Iterator operator++(int) {
96     _Iterator preval = *this;
97     ++*this;
98     return preval;
99     }
100    
101     /// prefix decrement op.
102     inline _Iterator& operator--() {
103     #if DEVMODE
104     #if USE_EXCEPTIONS
105     if (!isValid()) throw std::runtime_error(__err_msg_iterator_invalidated);
106     #else
107     if (!isValid()) return *(_Iterator*)NULL; // force segfault if iterator became invalidated
108     #endif // USE_EXCEPTIONS
109     #endif // DEVMODE
110     fallback = current;
111     current = current->prev;
112     return *this;
113     }
114    
115     /// postfix decrement op.
116     inline _Iterator operator--(int) {
117     _Iterator preval = *this;
118     --*this;
119     return preval;
120     }
121    
122 schoenebeck 361 inline T1& operator*() {
123 schoenebeck 271 #if DEVMODE
124     #if USE_EXCEPTIONS
125     if (isValid()) return *current->data;
126     else throw std::runtime_error(__err_msg_iterator_invalidated);
127     #else
128 schoenebeck 361 return *(isValid() ? current->data : (T1*)NULL); // force segfault if iterator became invalidated
129 schoenebeck 271 #endif // USE_EXCEPTIONS
130     #else
131     return *current->data;
132     #endif // DEVMODE
133     }
134    
135 schoenebeck 361 inline T1* operator->() {
136 schoenebeck 271 #if DEVMODE
137     #if USE_EXCEPTIONS
138     if (isValid()) return current->data;
139     else throw std::runtime_error(__err_msg_iterator_invalidated);
140     #else
141 schoenebeck 361 return isValid() ? current->data : (T1*)NULL; // force segfault if iterator became invalidated
142 schoenebeck 271 #endif // USE_EXCEPTIONS
143     #else
144     return current->data;
145     #endif // DEVMODE
146     }
147    
148 schoenebeck 361 inline bool operator==(const _Iterator<T1> other) {
149 schoenebeck 271 return current == other.current;
150     }
151    
152 schoenebeck 361 inline bool operator!=(const _Iterator<T1> other) {
153 schoenebeck 271 return current != other.current;
154     }
155    
156     inline operator bool() const {
157     return current && current->data;
158     }
159    
160     inline bool operator!() const {
161     return !(current && current->data);
162     }
163    
164 schoenebeck 361 inline _Iterator moveToEndOf(RTListBase<T1>* pDstList) {
165 schoenebeck 271 detach();
166     pDstList->append(*this);
167     _Iterator iterOnDstList = _Iterator(current);
168     current = fallback;
169     return iterOnDstList;
170     }
171    
172 schoenebeck 361 inline _Iterator moveToBeginOf(RTListBase<T1>* pDstList) {
173 schoenebeck 271 detach();
174     pDstList->prepend(*this);
175     _Iterator iterOnDstList = _Iterator(current);
176     current = fallback;
177     return iterOnDstList;
178     }
179    
180     #if DEVMODE
181     inline bool isValid() {
182     return current->list == list;
183     }
184     #endif // DEVMODE
185    
186     protected:
187     Node* current;
188     Node* fallback;
189     enum dir_t {
190     dir_forward,
191     dir_backward
192     };
193     #if DEVMODE
194 schoenebeck 361 RTListBase<T1>* list;
195 schoenebeck 271 #endif // DEVMODE
196    
197     _Iterator(Node* pNode, dir_t direction = dir_forward) {
198     current = pNode;
199     fallback = (direction == dir_forward) ? pNode->prev : pNode->next;
200     #if DEVMODE
201     list = pNode->list;
202     #endif // DEVMODE
203     }
204    
205     inline Node* node() {
206     #if DEVMODE
207     #if USE_EXCEPTIONS
208     if (isValid()) return current;
209     else throw std::runtime_error(__err_msg_iterator_invalidated);
210     #else
211     return (isValid()) ? current : (Node*)NULL; // force segfault if iterator became invalidated
212     #endif // USE_EXCEPTIONS
213     #else
214     return current;
215     #endif // DEVMODE
216     }
217    
218     inline void detach() {
219 schoenebeck 361 RTListBase<T1>::detach(*this);
220 schoenebeck 271 }
221    
222 schoenebeck 361 friend class RTListBase<T1>;
223     friend class RTList<T1>;
224     friend class Pool<T1>;
225 schoenebeck 271 };
226     typedef _Iterator<T> Iterator;
227    
228     inline Iterator first() {
229     return Iterator(_begin.next, Iterator::dir_forward);
230     }
231    
232     inline Iterator last() {
233     return Iterator(_end.prev, Iterator::dir_backward);
234     }
235    
236     inline Iterator begin() {
237     return Iterator(&_begin, Iterator::dir_forward);
238     }
239    
240     inline Iterator end() {
241     return Iterator(&_end, Iterator::dir_backward);
242     }
243    
244     inline bool isEmpty() {
245     return _begin.next == &_end;
246     }
247    
248     protected:
249     Node _begin; // fake node (without data) which represents the begin of the list - not the first element!
250     Node _end; // fake node (without data) which represents the end of the list - not the last element!
251    
252     RTListBase() {
253     // initialize boundary nodes
254     _begin.prev = &_begin;
255     _begin.next = &_end;
256     _begin.data = NULL;
257     _end.next = &_end;
258     _end.prev = &_begin;
259     _end.data = NULL;
260     #if DEVMODE
261     _begin.list = this;
262     _end.list = this;
263     #endif // DEVMODE
264     }
265    
266     inline void append(Iterator itElement) {
267     Node* pNode = itElement.current;
268     Node* last = _end.prev;
269     last->next = pNode;
270     pNode->prev = last; // if a segfault happens here, then because 'itElement' Iterator became invalidated
271     pNode->next = &_end;
272     _end.prev = pNode;
273     #if DEVMODE
274     pNode->list = this;
275     #endif // DEVMODE
276     }
277    
278     inline void append(Iterator itFirst, Iterator itLast) {
279     Node* pFirst = itFirst.current;
280     Node* pLast = itLast.current;
281     Node* last = _end.prev;
282     last->next = pFirst;
283     pFirst->prev = last; // if a segfault happens here, then because 'itFirst' Iterator became invalidated
284     pLast->next = &_end; // if a segfault happens here, then because 'itLast' Iterator became invalidated
285     _end.prev = pLast;
286     #if DEVMODE
287     for (Node* pNode = pFirst; true; pNode = pNode->next) {
288     pNode->list = this;
289     if (pNode == pLast) break;
290     }
291     #endif // DEVMODE
292     }
293    
294     inline void prepend(Iterator itElement) {
295     Node* pNode = itElement.current;
296     Node* first = _begin.next;
297     _begin.next = pNode;
298     pNode->prev = &_begin; // if a segfault happens here, then because 'itElement' Iterator became invalidated
299     pNode->next = first;
300     first->prev = pNode;
301     #if DEVMODE
302     pNode->list = this;
303     #endif // DEVMODE
304     }
305    
306     inline void prepend(Iterator itFirst, Iterator itLast) {
307     Node* pFirst = itFirst.current;
308     Node* pLast = itLast.current;
309     Node* first = _begin.next;
310     _begin.next = pFirst;
311     pFirst->prev = &_begin; // if a segfault happens here, then because 'itFirst' Iterator became invalidated
312     pLast->next = first; // if a segfault happens here, then because 'itLast' Iterator became invalidated
313     first->prev = pLast;
314     #if DEVMODE
315     for (Node* pNode = pFirst; true; pNode = pNode->next) {
316     pNode->list = this;
317     if (pNode == pLast) break;
318     }
319     #endif // DEVMODE
320     }
321    
322     static inline void detach(Iterator itElement) {
323     Node* pNode = itElement.node();
324     Node* prev = pNode->prev; // if a segfault happens here, then because 'itElement' Iterator became invalidated
325     Node* next = pNode->next;
326     prev->next = next;
327     next->prev = prev;
328     }
329    
330     static inline void detach(Iterator itFirst, Iterator itLast) {
331     Node* prev = itFirst.node()->prev; // if a segfault happens here, then because 'itFirst' Iterator became invalidated
332     Node* next = itLast.node()->next; // if a segfault happens here, then because 'itLast' Iterator became invalidated
333     prev->next = next;
334     next->prev = prev;
335     }
336    
337 schoenebeck 277 friend class _Iterator<T>;
338     friend class RTList<T>;
339 schoenebeck 271 friend class Pool<T>;
340     };
341    
342     template<typename T>
343     class RTList : public RTListBase<T> {
344     public:
345     typedef typename RTListBase<T>::Node Node;
346     typedef typename RTListBase<T>::Iterator Iterator;
347    
348     /**
349     * Constructor
350     *
351     * @param pPool - pool this list uses for allocation and
352     * deallocation of elements
353     */
354     RTList(Pool<T>* pPool) : RTListBase<T>::RTListBase() {
355     this->pPool = pPool;
356     }
357    
358     virtual ~RTList() {
359     clear();
360     }
361    
362     inline bool poolIsEmpty() {
363     return pPool->poolIsEmpty();
364     }
365    
366     inline Iterator allocAppend() {
367     if (pPool->poolIsEmpty()) return RTListBase<T>::begin();
368     Iterator element = pPool->alloc();
369     append(element);
370     #if DEVMODE
371     element.list = this;
372     #endif // DEVMODE
373     return element;
374     }
375    
376     inline Iterator allocPrepend() {
377     if (pPool->poolIsEmpty()) return RTListBase<T>::end();
378     Iterator element = pPool->alloc();
379     prepend(element);
380     #if DEVMODE
381     element.list = this;
382     #endif // DEVMODE
383     return element;
384     }
385    
386     inline void free(Iterator& itElement) {
387     itElement.detach();
388     pPool->freeToPool(itElement);
389     itElement.current = itElement.fallback;
390     }
391    
392     inline void clear() {
393     if (!RTListBase<T>::isEmpty()) {
394     Node* first = RTListBase<T>::_begin.next;
395     Node* last = RTListBase<T>::_end.prev;
396     RTListBase<T>::detach(first, last);
397     pPool->freeToPool(first, last);
398     }
399     }
400    
401     protected:
402     Pool<T>* pPool;
403     };
404    
405     template<typename T>
406     class Pool : public RTList<T> {
407     public:
408     typedef typename RTList<T>::Node Node;
409     typedef typename RTList<T>::Iterator Iterator;
410    
411     Node* nodes;
412     T* data;
413     RTListBase<T> freelist; // not yet allocated elements
414    
415     Pool(int Elements) : RTList<T>::RTList(this) {
416     data = new T[Elements];
417     nodes = new Node[Elements];
418     for (int i = 0; i < Elements; i++) {
419     nodes[i].data = &data[i];
420     freelist.append(&nodes[i]);
421     }
422     }
423    
424     virtual ~Pool() {
425     if (nodes) delete[] nodes;
426     if (data) delete[] data;
427     }
428    
429     inline bool poolIsEmpty() {
430     return freelist.isEmpty();
431     }
432    
433     protected:
434     // caution: assumes pool (that is freelist) is not empty!
435     inline Iterator alloc() {
436     Iterator element = freelist.last();
437     element.detach();
438     return element;
439     }
440    
441     inline void freeToPool(Iterator itElement) {
442     freelist.append(itElement);
443     }
444    
445     inline void freeToPool(Iterator itFirst, Iterator itLast) {
446     freelist.append(itFirst, itLast);
447     }
448    
449     friend class RTList<T>;
450     };
451    
452     #endif // __LS_POOL_H__

  ViewVC Help
Powered by ViewVC