3 |
* LinuxSampler - modular, streaming capable sampler * |
* LinuxSampler - modular, streaming capable sampler * |
4 |
* * |
* * |
5 |
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
* Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck * |
6 |
* Copyright (C) 2005 - 2012 Christian Schoenebeck * |
* Copyright (C) 2005 - 2014 Christian Schoenebeck * |
7 |
* * |
* * |
8 |
* This program is free software; you can redistribute it and/or modify * |
* 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 * |
* it under the terms of the GNU General Public License as published by * |
61 |
#if CONFIG_DEVMODE |
#if CONFIG_DEVMODE |
62 |
RTListBase<T1>* list; // list to which this node currently belongs to |
RTListBase<T1>* list; // list to which this node currently belongs to |
63 |
#endif // CONFIG_DEVMODE |
#endif // CONFIG_DEVMODE |
64 |
|
int reincarnation; // just for Pool::fromID() |
65 |
|
|
66 |
_Node() { |
_Node() { |
67 |
next = NULL; |
next = NULL; |
70 |
#if CONFIG_DEVMODE |
#if CONFIG_DEVMODE |
71 |
list = NULL; |
list = NULL; |
72 |
#endif // CONFIG_DEVMODE |
#endif // CONFIG_DEVMODE |
73 |
|
reincarnation = 0; |
74 |
} |
} |
75 |
}; |
}; |
76 |
typedef _Node<T> Node; |
typedef _Node<T> Node; |
147 |
} |
} |
148 |
#endif // CONFIG_DEVMODE |
#endif // CONFIG_DEVMODE |
149 |
return *current->data; |
return *current->data; |
150 |
|
} |
151 |
|
|
152 |
|
inline const T1& operator*() const { |
153 |
|
#if CONFIG_DEVMODE |
154 |
|
if (!isValid()) { // if iterator became invalidated |
155 |
|
#if CONFIG_RT_EXCEPTIONS |
156 |
|
throw std::runtime_error(__err_msg_iterator_invalidated); |
157 |
|
#else |
158 |
|
std::cerr << __err_msg_iterator_invalidated << std::endl << std::flush; |
159 |
|
return *((const T1*)NULL); // force segfault if iterator became invalidated |
160 |
|
#endif // CONFIG_RT_EXCEPTIONS |
161 |
|
} |
162 |
|
#endif // CONFIG_DEVMODE |
163 |
|
return *current->data; |
164 |
} |
} |
165 |
|
|
166 |
inline T1* operator->() { |
inline T1* operator->() { |
177 |
return current->data; |
return current->data; |
178 |
} |
} |
179 |
|
|
180 |
inline bool operator==(const _Iterator<T1> other) { |
inline const T1* operator->() const { |
181 |
|
#if CONFIG_DEVMODE |
182 |
|
if (!isValid()) { // if iterator became invalidated |
183 |
|
#if CONFIG_RT_EXCEPTIONS |
184 |
|
throw std::runtime_error(__err_msg_iterator_invalidated); |
185 |
|
#else |
186 |
|
std::cerr << __err_msg_iterator_invalidated << std::endl << std::flush; |
187 |
|
return (const T1*)NULL; // force segfault if iterator became invalidated |
188 |
|
#endif // CONFIG_RT_EXCEPTIONS |
189 |
|
} |
190 |
|
#endif // CONFIG_DEVMODE |
191 |
|
return current->data; |
192 |
|
} |
193 |
|
|
194 |
|
inline bool operator==(const _Iterator<T1> other) const { |
195 |
return current == other.current; |
return current == other.current; |
196 |
} |
} |
197 |
|
|
198 |
inline bool operator!=(const _Iterator<T1> other) { |
inline bool operator!=(const _Iterator<T1> other) const { |
199 |
return current != other.current; |
return current != other.current; |
200 |
} |
} |
201 |
|
|
224 |
} |
} |
225 |
|
|
226 |
#if CONFIG_DEVMODE |
#if CONFIG_DEVMODE |
227 |
inline bool isValid() { |
inline bool isValid() const { |
228 |
return current->list == list; |
return current->list == list; |
229 |
} |
} |
230 |
#endif // CONFIG_DEVMODE |
#endif // CONFIG_DEVMODE |
261 |
#endif // CONFIG_DEVMODE |
#endif // CONFIG_DEVMODE |
262 |
} |
} |
263 |
|
|
264 |
|
inline const Node* node() const { |
265 |
|
#if CONFIG_DEVMODE |
266 |
|
#if CONFIG_RT_EXCEPTIONS |
267 |
|
if (isValid()) return current; |
268 |
|
else throw std::runtime_error(__err_msg_iterator_invalidated); |
269 |
|
#else |
270 |
|
return (isValid()) ? current : (const Node*)NULL; // force segfault if iterator became invalidated |
271 |
|
#endif // CONFIG_RT_EXCEPTIONS |
272 |
|
#else |
273 |
|
return current; |
274 |
|
#endif // CONFIG_DEVMODE |
275 |
|
} |
276 |
|
|
277 |
inline void detach() { |
inline void detach() { |
278 |
RTListBase<T1>::detach(*this); |
RTListBase<T1>::detach(*this); |
279 |
} |
} |
300 |
return Iterator(&_end, Iterator::dir_backward); |
return Iterator(&_end, Iterator::dir_backward); |
301 |
} |
} |
302 |
|
|
303 |
inline bool isEmpty() { |
inline bool isEmpty() const { |
304 |
return _begin.next == &_end; |
return _begin.next == &_end; |
305 |
} |
} |
306 |
|
|
441 |
clear(); |
clear(); |
442 |
} |
} |
443 |
|
|
444 |
inline bool poolIsEmpty() { |
inline bool poolIsEmpty() const { |
445 |
return pPool->poolIsEmpty(); |
return pPool->poolIsEmpty(); |
446 |
} |
} |
447 |
|
|
480 |
} |
} |
481 |
} |
} |
482 |
|
|
483 |
|
inline int getID(const T* obj) const { |
484 |
|
return pPool->getID(obj); |
485 |
|
} |
486 |
|
|
487 |
|
inline int getID(const Iterator& it) const { |
488 |
|
return pPool->getID(&*it); |
489 |
|
} |
490 |
|
|
491 |
|
inline Iterator fromID(int id) const { |
492 |
|
return pPool->fromID(id); |
493 |
|
} |
494 |
|
|
495 |
protected: |
protected: |
496 |
Pool<T>* pPool; |
Pool<T>* pPool; |
497 |
}; |
}; |
516 |
if (data) delete[] data; |
if (data) delete[] data; |
517 |
} |
} |
518 |
|
|
519 |
inline bool poolIsEmpty() { |
inline bool poolIsEmpty() const { |
520 |
return freelist.isEmpty(); |
return freelist.isEmpty(); |
521 |
} |
} |
522 |
|
|
561 |
_init(Elements); |
_init(Elements); |
562 |
} |
} |
563 |
|
|
564 |
|
/** |
565 |
|
* Returns an abstract, unique numeric ID for the given object of |
566 |
|
* this pool, it returns -1 in case the passed object is not a member |
567 |
|
* of this Pool, i.e. because it is simply an invalid pointer or member |
568 |
|
* of another Pool. The returned ID is unique among all elements of this |
569 |
|
* Pool and it differs with each reincarnation of an object. That means |
570 |
|
* each time you free an element to and allocate the same element back |
571 |
|
* from the Pool, it will have a different ID. |
572 |
|
* |
573 |
|
* Members are always translated both, from Iterators/pointers to IDs, |
574 |
|
* and from IDs to Iterators/pointers in constant time. |
575 |
|
* |
576 |
|
* You might want to use this alternative approach of referencing Pool |
577 |
|
* members under certain scenarios. For example if you need to expose |
578 |
|
* an ID to the end user and/or if you want to represent an object of |
579 |
|
* this pool by a smaller number instead of a native pointer (i.e. 16 |
580 |
|
* bits vs. 64 bits). You can also detect this way whether the object |
581 |
|
* has already been freed / reallocated from the Pool in the meantime. |
582 |
|
* |
583 |
|
* @param obj - raw pointer to a data member of this Pool |
584 |
|
* @returns unique numeric ID of @a obj or -1 if pointer was invalid |
585 |
|
*/ |
586 |
|
int getID(const T* obj) const { |
587 |
|
if (!poolsize) return -1; |
588 |
|
int index = obj - &data[0]; |
589 |
|
if (index < 0 || index >= poolsize) return -1; |
590 |
|
return (nodes[index].reincarnation << bitsForSize(poolsize)) | index; |
591 |
|
} |
592 |
|
|
593 |
|
/** |
594 |
|
* Overridden convenience method, behaves like the method above. |
595 |
|
*/ |
596 |
|
int getID(const Iterator& it) const { |
597 |
|
return getID(&*it); |
598 |
|
} |
599 |
|
|
600 |
|
/** |
601 |
|
* Returns an Iterator object of the Pool data member reflected by the |
602 |
|
* given abstract, unique numeric ID, it returns an invalid Iterator in |
603 |
|
* case the ID is invalid or if the Pool's data element reflected by |
604 |
|
* given ID was at least once released/freed back to the Pool in the |
605 |
|
* meantime. |
606 |
|
* |
607 |
|
* Members are always translated both, from Iterators/pointers to IDs, |
608 |
|
* and from IDs to Iterators/pointers in constant time. |
609 |
|
* |
610 |
|
* You might want to use this alternative approach of referencing Pool |
611 |
|
* members under certain scenarios. For example if you need to expose |
612 |
|
* an ID to the end user and/or if you want to represent an object of |
613 |
|
* this pool by a smaller number instead of a native pointer (i.e. 16 |
614 |
|
* bits vs. 64 bits). You can also detect this way whether the object |
615 |
|
* has already been freed / reallocated from the Pool in the meantime. |
616 |
|
* |
617 |
|
* @param id - unique ID of a Pool's data member |
618 |
|
* @returns Iterator object pointing to Pool's data element, invalid |
619 |
|
* Iterator in case ID was invalid or data element was freed |
620 |
|
*/ |
621 |
|
Iterator fromID(int id) const { |
622 |
|
if (id < 0) return Iterator(); // invalid iterator |
623 |
|
const uint bits = bitsForSize(poolsize); |
624 |
|
uint index = id & ((1 << bits) - 1); |
625 |
|
if (index >= poolsize) return Iterator(); // invalid iterator |
626 |
|
Node* node = &nodes[index]; |
627 |
|
int reincarnation = uint(id) >> bits; |
628 |
|
if (reincarnation != node->reincarnation) return Iterator(); // invalid iterator |
629 |
|
return Iterator(node); |
630 |
|
} |
631 |
|
|
632 |
protected: |
protected: |
633 |
// caution: assumes pool (that is freelist) is not empty! |
// caution: assumes pool (that is freelist) is not empty! |
634 |
inline Iterator alloc() { |
inline Iterator alloc() { |
638 |
} |
} |
639 |
|
|
640 |
inline void freeToPool(Iterator itElement) { |
inline void freeToPool(Iterator itElement) { |
641 |
|
itElement.node()->reincarnation++; |
642 |
freelist.append(itElement); |
freelist.append(itElement); |
643 |
} |
} |
644 |
|
|
645 |
inline void freeToPool(Iterator itFirst, Iterator itLast) { |
inline void freeToPool(Iterator itFirst, Iterator itLast) { |
646 |
|
for (Node* n = itFirst.node(); true; n = n->next) { |
647 |
|
n->reincarnation++; |
648 |
|
if (n == itLast.node()) break; |
649 |
|
} |
650 |
freelist.append(itFirst, itLast); |
freelist.append(itFirst, itLast); |
651 |
} |
} |
652 |
|
|
662 |
} |
} |
663 |
poolsize = Elements; |
poolsize = Elements; |
664 |
} |
} |
665 |
|
|
666 |
|
inline static int bitsForSize(int size) { |
667 |
|
if (!size) return 0; |
668 |
|
size--; |
669 |
|
int bits = 0; |
670 |
|
for (; size > 1; bits += 2, size >>= 2); |
671 |
|
return bits + size; |
672 |
|
} |
673 |
}; |
}; |
674 |
|
|
675 |
#endif // __LS_POOL_H__ |
#endif // __LS_POOL_H__ |