/[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 554 - (show annotations) (download) (as text)
Thu May 19 19:25:14 2005 UTC (18 years, 10 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 17042 byte(s)
* All compile time options are now centrally alterable as arguments to the
  ./configure script. All options are C Macros beginning with CONFIG_
  prefix and will be placed into auto generated config.h file.

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

  ViewVC Help
Powered by ViewVC