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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 271 by schoenebeck, Fri Oct 8 20:51:39 2004 UTC revision 2871 by schoenebeck, Sun Apr 10 18:22:23 2016 UTC
# Line 3  Line 3 
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 - 2016 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  *
# Line 23  Line 24 
24  #ifndef __LS_POOL_H__  #ifndef __LS_POOL_H__
25  #define __LS_POOL_H__  #define __LS_POOL_H__
26    
27  #ifndef DEVMODE  #ifdef HAVE_CONFIG_H
28  # include "global.h" // just to check if we should compile in 'DEVMODE'  # include <config.h>
29  #endif  #endif
30    
31  // we just use exceptions for debugging, better not in the final realtime thread !  // we just use exceptions for debugging, better not in the final realtime thread !
32  #ifndef USE_EXCEPTIONS  #ifndef CONFIG_RT_EXCEPTIONS
33  # define USE_EXCEPTIONS 0  # define CONFIG_RT_EXCEPTIONS 0
34  #endif  #endif
35    
36  #if USE_EXCEPTIONS  #if CONFIG_RT_EXCEPTIONS
37  # include <stdexcept>  # include <stdexcept>
38  # include <string>  # 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";  const std::string __err_msg_iterator_invalidated = "Pool/RTList iterator invalidated";
45  #endif // USE_EXCEPTIONS  #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  // just symbol prototyping
50  template<typename T> class Pool;  template<typename T> class Pool;
# Line 45  template<typename T> class RTList; Line 53  template<typename T> class RTList;
53  template<typename T>  template<typename T>
54  class RTListBase {  class RTListBase {
55      protected:      protected:
56          template<typename _T>          template<typename T1>
57          struct _Node {          struct _Node {
58              _Node<_T>* next;              _Node<T1>* next;
59              _Node<_T>* prev;              _Node<T1>* prev;
60              _T* data;              T1* data;
61              #if DEVMODE              #if CONFIG_DEVMODE
62              RTListBase<_T>* list; // list to which this node currently belongs to              RTListBase<T1>* list; // list to which this node currently belongs to
63              #endif // DEVMODE              #endif // CONFIG_DEVMODE
64                int reincarnation; // just for Pool::fromID()
65    
66              _Node() {              _Node() {
67                  next = NULL;                  next = NULL;
68                  prev = NULL;                  prev = NULL;
69                  data = NULL;                  data = NULL;
70                  #if DEVMODE                  #if CONFIG_DEVMODE
71                  list = NULL;                  list = NULL;
72                  #endif // DEVMODE                  #endif // CONFIG_DEVMODE
73                    reincarnation = 0;
74              }              }
75          };          };
76          typedef _Node<T> Node;          typedef _Node<T> Node;
77    
78      public:      public:
79          template<typename _T>          template<typename T1>
80          class _Iterator {          class _Iterator {
81              public:              public:
82                  _Iterator() {                  _Iterator() {
83                      current  = NULL;                      current  = NULL;
84                      fallback = NULL;                      fallback = NULL;
85                      #if DEVMODE                      #if CONFIG_DEVMODE
86                      list = NULL;                      list = NULL;
87                      #endif // DEVMODE                      #endif // CONFIG_DEVMODE
88                  }                  }
89    
90                  /// prefix increment op.                  /// prefix increment op.
91                  inline _Iterator& operator++() {                  inline _Iterator& operator++() {
92                      #if DEVMODE                      #if CONFIG_DEVMODE
93                      #if USE_EXCEPTIONS                      if (!isValid()) {
94                      if (!isValid()) throw std::runtime_error(__err_msg_iterator_invalidated);                          #if CONFIG_RT_EXCEPTIONS
95                      #else                          throw std::runtime_error(__err_msg_iterator_invalidated);
96                      if (!isValid()) return *(_Iterator*)NULL; // force segfault if iterator became invalidated                          #else
97                      #endif // USE_EXCEPTIONS                          std::cerr << __err_msg_iterator_invalidated << std::endl << std::flush;
98                      #endif // DEVMODE                          return *(_Iterator*)NULL; // force segfault if iterator became invalidated
99                            #endif // CONFIG_RT_EXCEPTIONS
100                        }
101                        #endif // CONFIG_DEVMODE
102                      fallback = current;                      fallback = current;
103                      current  = current->next;                      current  = current->next;
104                      return *this;                      return *this;
# Line 94  class RTListBase { Line 107  class RTListBase {
107                  /// postfix increment op.                  /// postfix increment op.
108                  inline _Iterator operator++(int) {                  inline _Iterator operator++(int) {
109                      _Iterator preval = *this;                      _Iterator preval = *this;
110                      ++*this;                      ++*this; // use prefix operator implementation
111                      return preval;                      return preval;
112                  }                  }
113    
114                  /// prefix decrement op.                  /// prefix decrement op.
115                  inline _Iterator& operator--() {                  inline _Iterator& operator--() {
116                      #if DEVMODE                      #if CONFIG_DEVMODE
117                      #if USE_EXCEPTIONS                      if (!isValid()) {
118                      if (!isValid()) throw std::runtime_error(__err_msg_iterator_invalidated);                          #if CONFIG_RT_EXCEPTIONS
119                      #else                          throw std::runtime_error(__err_msg_iterator_invalidated);
120                      if (!isValid()) return *(_Iterator*)NULL; // force segfault if iterator became invalidated                          #else
121                      #endif // USE_EXCEPTIONS                          std::cerr << __err_msg_iterator_invalidated << std::endl << std::flush;
122                      #endif // DEVMODE                          return *(_Iterator*)NULL; // force segfault if iterator became invalidated
123                            #endif // CONFIG_RT_EXCEPTIONS
124                        }
125                        #endif // CONFIG_DEVMODE
126                      fallback = current;                      fallback = current;
127                      current  = current->prev;                      current  = current->prev;
128                      return *this;                      return *this;
# Line 115  class RTListBase { Line 131  class RTListBase {
131                  /// postfix decrement op.                  /// postfix decrement op.
132                  inline _Iterator operator--(int) {                  inline _Iterator operator--(int) {
133                      _Iterator preval = *this;                      _Iterator preval = *this;
134                      --*this;                      --*this; // use prefix operator implementation
135                      return preval;                      return preval;
136                  }                  }
137    
138                  inline _T& operator*() {                  inline T1& operator*() {
139                      #if DEVMODE                      #if CONFIG_DEVMODE
140                      #if USE_EXCEPTIONS                      if (!isValid()) { // if iterator became invalidated
141                      if (isValid()) return *current->data;                          #if CONFIG_RT_EXCEPTIONS
142                      else throw std::runtime_error(__err_msg_iterator_invalidated);                          throw std::runtime_error(__err_msg_iterator_invalidated);
143                      #else                          #else
144                      return *(isValid() ? current->data : (_T*)NULL); // force segfault if iterator became invalidated                          std::cerr << __err_msg_iterator_invalidated << std::endl << std::flush;
145                      #endif // USE_EXCEPTIONS                          return *((T1*)NULL); // force segfault if iterator became invalidated
146                      #else                          #endif // CONFIG_RT_EXCEPTIONS
147                        }
148                        #endif // CONFIG_DEVMODE
149                      return *current->data;                      return *current->data;
                     #endif // DEVMODE  
150                  }                  }
151    
152                  inline _T* operator->() {                  inline const T1& operator*() const {
153                      #if DEVMODE                      #if CONFIG_DEVMODE
154                      #if USE_EXCEPTIONS                      if (!isValid()) { // if iterator became invalidated
155                      if (isValid()) return current->data;                          #if CONFIG_RT_EXCEPTIONS
156                      else throw std::runtime_error(__err_msg_iterator_invalidated);                          throw std::runtime_error(__err_msg_iterator_invalidated);
157                      #else                          #else
158                      return isValid() ? current->data : (_T*)NULL; // force segfault if iterator became invalidated                          std::cerr << __err_msg_iterator_invalidated << std::endl << std::flush;
159                      #endif // USE_EXCEPTIONS                          return *((const T1*)NULL); // force segfault if iterator became invalidated
160                      #else                          #endif // CONFIG_RT_EXCEPTIONS
161                        }
162                        #endif // CONFIG_DEVMODE
163                        return *current->data;
164                    }
165    
166                    inline T1* operator->() {
167                        #if CONFIG_DEVMODE
168                        if (!isValid()) { // if iterator became invalidated
169                            #if CONFIG_RT_EXCEPTIONS
170                            throw std::runtime_error(__err_msg_iterator_invalidated);
171                            #else
172                            std::cerr << __err_msg_iterator_invalidated << std::endl << std::flush;
173                            return (T1*)NULL; // force segfault if iterator became invalidated
174                            #endif // CONFIG_RT_EXCEPTIONS
175                        }
176                        #endif // CONFIG_DEVMODE
177                      return current->data;                      return current->data;
                     #endif // DEVMODE  
178                  }                  }
179    
180                  inline bool operator==(const _Iterator<_T> 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<_T> other) {                  inline bool operator!=(const _Iterator<T1> other) const {
199                      return current != other.current;                      return current != other.current;
200                  }                  }
201    
# Line 161  class RTListBase { Line 207  class RTListBase {
207                      return !(current && current->data);                      return !(current && current->data);
208                  }                  }
209    
210                  inline _Iterator moveToEndOf(RTListBase<_T>* pDstList) {                  /**
211                     * Moves the element pointed by this Iterator from its current
212                     * list to the beginning of the destination list @a pDstList.
213                     *
214                     * @b CAUTION: When this method returns, this Iterator does
215                     * @b NOT point to the element on the new list anymore, instead it
216                     * points at a completely different element! In case of a
217                     * forward Iterator this Iterator object will point to the
218                     * previous element on the source list, in case of a backward
219                     * Iterator it will point to the subsequent element on the
220                     * source list. This behavior is enforced to avoid breaking an
221                     * active loop code working with this Iterator object.
222                     *
223                     * Thus if you intend to continue working with the same element,
224                     * you should do like this:
225                     * @code
226                     * it = it.moveToEndOf(anotherList);
227                     * @endcode
228                     *
229                     * @param pDstList - destination list
230                     * @returns Iterator object pointing at the moved element on
231                     *          the destination list
232                     */
233                    inline _Iterator moveToEndOf(RTListBase<T1>* pDstList) {
234                      detach();                      detach();
235                      pDstList->append(*this);                      pDstList->append(*this);
236                      _Iterator iterOnDstList = _Iterator(current);                      _Iterator iterOnDstList = _Iterator(current);
# Line 169  class RTListBase { Line 238  class RTListBase {
238                      return iterOnDstList;                      return iterOnDstList;
239                  }                  }
240    
241                  inline _Iterator moveToBeginOf(RTListBase<_T>* pDstList) {                  /**
242                     * Moves the element pointed by this Iterator from its current
243                     * list to the end of destination list @a pDstList.
244                     *
245                     * @b CAUTION: When this method returns, this Iterator does
246                     * @b NOT point to the element on the new list anymore, instead it
247                     * points at a completely different element! In case of a
248                     * forward Iterator this Iterator object will point to the
249                     * previous element on the source list, in case of a backward
250                     * Iterator it will point to the subsequent element on the
251                     * source list. This behavior is enforced to avoid breaking an
252                     * active loop code working with this Iterator object.
253                     *
254                     * Thus if you intend to continue working with the same element,
255                     * you should do like this:
256                     * @code
257                     * it = it.moveToBeginOf(anotherList);
258                     * @endcode
259                     *
260                     * @param pDstList - destination list
261                     * @returns Iterator object pointing at the moved element on
262                     *          the destination list
263                     */
264                    inline _Iterator moveToBeginOf(RTListBase<T1>* pDstList) {
265                      detach();                      detach();
266                      pDstList->prepend(*this);                      pDstList->prepend(*this);
267                      _Iterator iterOnDstList = _Iterator(current);                      _Iterator iterOnDstList = _Iterator(current);
# Line 177  class RTListBase { Line 269  class RTListBase {
269                      return iterOnDstList;                      return iterOnDstList;
270                  }                  }
271    
272                  #if DEVMODE                  /**
273                  inline bool isValid() {                   * Moves the element pointed by this Iterator from its current
274                     * position to the position right before @a itDst. That move
275                     * may either be from and to the same list, or to a another
276                     * list.
277                     *
278                     * @b CAUTION: When this method returns, this Iterator does
279                     * @b NOT point to the element on the new list anymore, instead it
280                     * points at a completely different element! In case of a
281                     * forward Iterator this Iterator object will point to the
282                     * previous element on the source list, in case of a backward
283                     * Iterator it will point to the subsequent element on the
284                     * source list. This behavior is enforced to avoid breaking an
285                     * active loop code working with this Iterator object.
286                     *
287                     * Thus if you intend to continue working with the same element,
288                     * you should do like this:
289                     * @code
290                     * itSourceElement = itSourceElement.moveBefore(itDestinationElement);
291                     * @endcode
292                     *
293                     * @param itDst - destination element to be inserted before
294                     * @returns Iterator object pointing at the moved element on
295                     *          the destination list
296                     */
297                    inline _Iterator moveBefore(_Iterator<T1> itDst) {
298                        detach();
299                        RTList<T1>::prependBefore(*this, itDst);
300                        _Iterator iterOnDstList = _Iterator(current);
301                        current = fallback;
302                        return iterOnDstList;
303                    }
304    
305                    /**
306                     * Moves the element pointed by this Iterator from its current
307                     * position to the position right after @a itDst. That move
308                     * may either be from and to the same list, or to a another
309                     * list.
310                     *
311                     * @b CAUTION: When this method returns, this Iterator does
312                     * @b NOT point to the element on the new list anymore, instead it
313                     * points at a completely different element! In case of a
314                     * forward Iterator this Iterator object will point to the
315                     * previous element on the source list, in case of a backward
316                     * Iterator it will point to the subsequent element on the
317                     * source list. This behavior is enforced to avoid breaking an
318                     * active loop code working with this Iterator object.
319                     *
320                     * Thus if you intend to continue working with the same element,
321                     * you should do like this:
322                     * @code
323                     * itSourceElement = itSourceElement.moveAfter(itDestinationElement);
324                     * @endcode
325                     *
326                     * @param itDst - destination element to be inserted after
327                     * @returns Iterator object pointing at the moved element on
328                     *          the destination list
329                     */
330                    inline _Iterator moveAfter(_Iterator<T1> itDst) {
331                        detach();
332                        RTList<T1>::appendAfter(*this, itDst);
333                        _Iterator iterOnDstList = _Iterator(current);
334                        current = fallback;
335                        return iterOnDstList;
336                    }
337    
338                    #if CONFIG_DEVMODE
339                    inline bool isValid() const {
340                      return current->list == list;                      return current->list == list;
341                  }                  }
342                  #endif // DEVMODE                  #endif // CONFIG_DEVMODE
343    
344              protected:              protected:
345                  Node* current;                  Node* current;
# Line 190  class RTListBase { Line 348  class RTListBase {
348                      dir_forward,                      dir_forward,
349                      dir_backward                      dir_backward
350                  };                  };
351                  #if DEVMODE                  #if CONFIG_DEVMODE
352                  RTListBase<_T>* list;                  RTListBase<T1>* list;
353                  #endif // DEVMODE                  #endif // CONFIG_DEVMODE
354    
355                  _Iterator(Node* pNode, dir_t direction = dir_forward) {                  _Iterator(Node* pNode, dir_t direction = dir_forward) {
356                      current  = pNode;                      current  = pNode;
357                      fallback = (direction == dir_forward) ? pNode->prev : pNode->next;                      fallback = (direction == dir_forward) ? pNode->prev : pNode->next;
358                      #if DEVMODE                      #if CONFIG_DEVMODE
359                      list = pNode->list;                      list = pNode->list;
360                      #endif // DEVMODE                      #endif // CONFIG_DEVMODE
361                  }                  }
362    
363                  inline Node* node() {                  inline Node* node() {
364                      #if DEVMODE                      #if CONFIG_DEVMODE
365                      #if USE_EXCEPTIONS                      #if CONFIG_RT_EXCEPTIONS
366                      if (isValid()) return current;                      if (isValid()) return current;
367                      else throw std::runtime_error(__err_msg_iterator_invalidated);                      else throw std::runtime_error(__err_msg_iterator_invalidated);
368                      #else                      #else
369                      return (isValid()) ? current : (Node*)NULL; // force segfault if iterator became invalidated                      return (isValid()) ? current : (Node*)NULL; // force segfault if iterator became invalidated
370                      #endif // USE_EXCEPTIONS                      #endif // CONFIG_RT_EXCEPTIONS
371                        #else
372                        return current;
373                        #endif // CONFIG_DEVMODE
374                    }
375    
376                    inline const Node* node() const {
377                        #if CONFIG_DEVMODE
378                        #if CONFIG_RT_EXCEPTIONS
379                        if (isValid()) return current;
380                        else throw std::runtime_error(__err_msg_iterator_invalidated);
381                        #else
382                        return (isValid()) ? current : (const Node*)NULL; // force segfault if iterator became invalidated
383                        #endif // CONFIG_RT_EXCEPTIONS
384                      #else                      #else
385                      return current;                      return current;
386                      #endif // DEVMODE                      #endif // CONFIG_DEVMODE
387                  }                  }
388    
389                  inline void detach() {                  inline void detach() {
390                      RTListBase<_T>::detach(*this);                      RTListBase<T1>::detach(*this);
391                  }                  }
392    
393                  friend class RTListBase<_T>;                  friend class RTListBase<T1>;
394                  friend class RTList<_T>;                  friend class RTList<T1>;
395                  friend class Pool<_T>;                  friend class Pool<T1>;
396          };          };
397          typedef _Iterator<T> Iterator;          typedef _Iterator<T> Iterator;
398    
# Line 241  class RTListBase { Line 412  class RTListBase {
412              return Iterator(&_end, Iterator::dir_backward);              return Iterator(&_end, Iterator::dir_backward);
413          }          }
414    
415          inline bool isEmpty() {          inline bool isEmpty() const {
416              return _begin.next == &_end;              return _begin.next == &_end;
417          }          }
418    
419            inline int count() {
420                int elements = 0;
421                for (Iterator it = first(); it != end(); ++it) ++elements;
422                return elements;
423            }
424    
425      protected:      protected:
426          Node _begin; // fake node (without data) which represents the begin of the list - not the first element!          Node _begin; // fake node (without data) which represents the begin of the list - not the first element!
427          Node _end;   // fake node (without data) which represents the end of the list - not the last element!          Node _end;   // fake node (without data) which represents the end of the list - not the last element!
428    
429          RTListBase() {          RTListBase() {
430                init();
431            }
432    
433            void init() {
434              // initialize boundary nodes              // initialize boundary nodes
435              _begin.prev = &_begin;              _begin.prev = &_begin;
436              _begin.next = &_end;              _begin.next = &_end;
# Line 257  class RTListBase { Line 438  class RTListBase {
438              _end.next = &_end;              _end.next = &_end;
439              _end.prev = &_begin;              _end.prev = &_begin;
440              _end.data = NULL;              _end.data = NULL;
441              #if DEVMODE              #if CONFIG_DEVMODE
442              _begin.list = this;              _begin.list = this;
443              _end.list   = this;              _end.list   = this;
444              #endif // DEVMODE              #endif // CONFIG_DEVMODE
445          }          }
446    
447          inline void append(Iterator itElement) {          inline void append(Iterator itElement) {
# Line 270  class RTListBase { Line 451  class RTListBase {
451              pNode->prev = last; // if a segfault happens here, then because 'itElement' Iterator became invalidated              pNode->prev = last; // if a segfault happens here, then because 'itElement' Iterator became invalidated
452              pNode->next = &_end;              pNode->next = &_end;
453              _end.prev   = pNode;              _end.prev   = pNode;
454              #if DEVMODE              #if CONFIG_DEVMODE
455              pNode->list = this;              pNode->list = this;
456              #endif // DEVMODE              #endif // CONFIG_DEVMODE
457          }          }
458    
459          inline void append(Iterator itFirst, Iterator itLast) {          inline void append(Iterator itFirst, Iterator itLast) {
# Line 283  class RTListBase { Line 464  class RTListBase {
464              pFirst->prev = last;  // if a segfault happens here, then because 'itFirst' Iterator became invalidated              pFirst->prev = last;  // if a segfault happens here, then because 'itFirst' Iterator became invalidated
465              pLast->next  = &_end; // if a segfault happens here, then because 'itLast' Iterator became invalidated              pLast->next  = &_end; // if a segfault happens here, then because 'itLast' Iterator became invalidated
466              _end.prev    = pLast;              _end.prev    = pLast;
467              #if DEVMODE              #if CONFIG_DEVMODE
468              for (Node* pNode = pFirst; true; pNode = pNode->next) {              for (Node* pNode = pFirst; true; pNode = pNode->next) {
469                  pNode->list = this;                  pNode->list = this;
470                  if (pNode == pLast) break;                  if (pNode == pLast) break;
471              }              }
472              #endif // DEVMODE              #endif // CONFIG_DEVMODE
473          }          }
474    
475          inline void prepend(Iterator itElement) {          inline void prepend(Iterator itElement) {
# Line 298  class RTListBase { Line 479  class RTListBase {
479              pNode->prev = &_begin; // if a segfault happens here, then because 'itElement' Iterator became invalidated              pNode->prev = &_begin; // if a segfault happens here, then because 'itElement' Iterator became invalidated
480              pNode->next = first;              pNode->next = first;
481              first->prev = pNode;              first->prev = pNode;
482              #if DEVMODE              #if CONFIG_DEVMODE
483              pNode->list = this;              pNode->list = this;
484              #endif // DEVMODE              #endif // CONFIG_DEVMODE
485          }          }
486    
487          inline void prepend(Iterator itFirst, Iterator itLast) {          inline void prepend(Iterator itFirst, Iterator itLast) {
# Line 311  class RTListBase { Line 492  class RTListBase {
492              pFirst->prev = &_begin; // if a segfault happens here, then because 'itFirst' Iterator became invalidated              pFirst->prev = &_begin; // if a segfault happens here, then because 'itFirst' Iterator became invalidated
493              pLast->next  = first;   // if a segfault happens here, then because 'itLast' Iterator became invalidated              pLast->next  = first;   // if a segfault happens here, then because 'itLast' Iterator became invalidated
494              first->prev  = pLast;              first->prev  = pLast;
495              #if DEVMODE              #if CONFIG_DEVMODE
496              for (Node* pNode = pFirst; true; pNode = pNode->next) {              for (Node* pNode = pFirst; true; pNode = pNode->next) {
497                  pNode->list = this;                  pNode->list = this;
498                  if (pNode == pLast) break;                  if (pNode == pLast) break;
499              }              }
500              #endif // DEVMODE              #endif // CONFIG_DEVMODE
501            }
502    
503            static inline void prependBefore(Iterator itSrc, Iterator itDst) {
504                Node* src = itSrc.current;
505                Node* dst = itDst.current;
506                Node* prev = dst->prev;
507                prev->next = src;
508                dst->prev  = src;
509                src->prev  = prev;
510                src->next  = dst;
511                #if CONFIG_DEVMODE
512                src->list = this;
513                #endif // CONFIG_DEVMODE
514            }
515    
516            static inline void appendAfter(Iterator itSrc, Iterator itDst) {
517                Node* src = itSrc.current;
518                Node* dst = itDst.current;
519                Node* next = dst->next;
520                next->prev = src;
521                dst->next  = src;
522                src->prev  = dst;
523                src->next  = next;
524                #if CONFIG_DEVMODE
525                src->list = this;
526                #endif // CONFIG_DEVMODE
527          }          }
528    
529          static inline void detach(Iterator itElement) {          static inline void detach(Iterator itElement) {
# Line 334  class RTListBase { Line 541  class RTListBase {
541              next->prev = prev;              next->prev = prev;
542          }          }
543    
544            friend class _Iterator<T>;
545            friend class RTList<T>;
546          friend class Pool<T>;          friend class Pool<T>;
547  };  };
548    
# Line 352  class RTList : public RTListBase<T> { Line 561  class RTList : public RTListBase<T> {
561          RTList(Pool<T>* pPool) : RTListBase<T>::RTListBase() {          RTList(Pool<T>* pPool) : RTListBase<T>::RTListBase() {
562              this->pPool = pPool;              this->pPool = pPool;
563          }          }
564            
565            /**
566             * Copy constructor
567             */
568            RTList(RTList<T>& list) : RTListBase<T>::RTListBase() {
569                this->pPool = list.pPool;
570                Iterator it = list.first();
571                Iterator end = list.end();
572                for(; it != end; ++it) {
573                    if (poolIsEmpty()) break;
574                    *(allocAppend()) = *it;
575                }
576            }
577    
578          virtual ~RTList() {          virtual ~RTList() {
579              clear();              clear();
580          }          }
581    
582          inline bool poolIsEmpty() {          inline bool poolIsEmpty() const {
583              return pPool->poolIsEmpty();              return pPool->poolIsEmpty();
584          }          }
585    
586          inline Iterator allocAppend() {          inline Iterator allocAppend() {
587              if (pPool->poolIsEmpty()) return RTListBase<T>::begin();              if (pPool->poolIsEmpty()) return RTListBase<T>::begin();
588              Iterator element = pPool->alloc();              Iterator element = pPool->alloc();
589              append(element);              this->append(element);
590              #if DEVMODE              #if CONFIG_DEVMODE
591              element.list = this;              element.list = this;
592              #endif // DEVMODE              #endif // CONFIG_DEVMODE
593              return element;              return element;
594          }          }
595    
# Line 375  class RTList : public RTListBase<T> { Line 597  class RTList : public RTListBase<T> {
597              if (pPool->poolIsEmpty()) return RTListBase<T>::end();              if (pPool->poolIsEmpty()) return RTListBase<T>::end();
598              Iterator element = pPool->alloc();              Iterator element = pPool->alloc();
599              prepend(element);              prepend(element);
600              #if DEVMODE              #if CONFIG_DEVMODE
601              element.list = this;              element.list = this;
602              #endif // DEVMODE              #endif // CONFIG_DEVMODE
603              return element;              return element;
604          }          }
605    
# Line 396  class RTList : public RTListBase<T> { Line 618  class RTList : public RTListBase<T> {
618              }              }
619          }          }
620    
621            inline int getID(const T* obj) const {
622                return pPool->getID(obj);
623            }
624    
625            inline int getID(const Iterator& it) const {
626                return pPool->getID(&*it);
627            }
628    
629            inline Iterator fromID(int id) const {
630                return pPool->fromID(id);
631            }
632    
633            inline Iterator fromPtr(const T* obj) const {
634                return pPool->fromPtr(obj);
635            }
636    
637      protected:      protected:
638          Pool<T>* pPool;          Pool<T>* pPool;
639  };  };
# Line 409  class Pool : public RTList<T> { Line 647  class Pool : public RTList<T> {
647          Node*         nodes;          Node*         nodes;
648          T*            data;          T*            data;
649          RTListBase<T> freelist; // not yet allocated elements          RTListBase<T> freelist; // not yet allocated elements
650            int           poolsize;
651    
652          Pool(int Elements) : RTList<T>::RTList(this) {          Pool(int Elements) : RTList<T>::RTList(this) {
653              data  = new T[Elements];              _init(Elements);
             nodes = new Node[Elements];  
             for (int i = 0; i < Elements; i++) {  
                 nodes[i].data = &data[i];  
                 freelist.append(&nodes[i]);  
             }  
654          }          }
655    
656          virtual ~Pool() {          virtual ~Pool() {
# Line 424  class Pool : public RTList<T> { Line 658  class Pool : public RTList<T> {
658              if (data)  delete[] data;              if (data)  delete[] data;
659          }          }
660    
661          inline bool poolIsEmpty() {          inline bool poolIsEmpty() const {
662              return freelist.isEmpty();              return freelist.isEmpty();
663          }          }
664    
665            /**
666             * Returns the current size of the pool, that is the amount of
667             * pre-allocated elements from the operating system. It equals the
668             * amount of elements given to the constructor unless resizePool()
669             * is called.
670             *
671             * @see resizePool()
672             */
673            int poolSize() const {
674                return poolsize;
675            }
676    
677            /**
678             * Alters the amount of elements to be pre-allocated from the
679             * operating system for this pool object.
680             *
681             * @e CAUTION: you MUST free all elements in use before calling this
682             * method ( e.g. by calling clear() )! Also make sure that no
683             * references of elements before this call will still be used after this
684             * call, since all elements will be reallocated and their old memory
685             * addresses become invalid!
686             *
687             * @see poolSize()
688             */
689            void resizePool(int Elements) {
690                if (freelist.count() != poolsize) {
691                    #if CONFIG_DEVMODE
692                    throw std::runtime_error(__err_msg_resize_while_in_use);
693                    #else
694                    std::cerr << __err_msg_resize_while_in_use << std::endl << std::flush;
695                    // if we're here something's terribly wrong, but we try to do the best
696                    RTList<T>::clear();
697                    #endif
698                }
699                if (nodes) delete[] nodes;
700                if (data)  delete[] data;
701                freelist.init();
702                RTListBase<T>::init();
703                _init(Elements);
704            }
705    
706            /**
707             * Returns an abstract, unique numeric ID for the given object of
708             * this pool, it returns -1 in case the passed object is not a member
709             * of this Pool, i.e. because it is simply an invalid pointer or member
710             * of another Pool. The returned ID is unique among all elements of this
711             * Pool and it differs with each reincarnation of an object. That means
712             * each time you free an element to and allocate the same element back
713             * from the Pool, it will have a different ID.
714             *
715             * Members are always translated both, from Iterators/pointers to IDs,
716             * and from IDs to Iterators/pointers in constant time.
717             *
718             * You might want to use this alternative approach of referencing Pool
719             * members under certain scenarios. For example if you need to expose
720             * an ID to the end user and/or if you want to represent an object of
721             * this pool by a smaller number instead of a native pointer (i.e. 16
722             * bits vs. 64 bits). You can also detect this way whether the object
723             * has already been freed / reallocated from the Pool in the meantime.
724             *
725             * @param obj - raw pointer to a data member of this Pool
726             * @returns unique numeric ID of @a obj or -1 if pointer was invalid
727             */
728            int getID(const T* obj) const {
729                if (!poolsize) return -1;
730                int index = obj - &data[0];
731                if (index < 0 || index >= poolsize) return -1;
732                return (nodes[index].reincarnation << bitsForSize(poolsize)) | index;
733            }
734    
735            /**
736             * Overridden convenience method, behaves like the method above.
737             */
738            int getID(const Iterator& it) const {
739                return getID(&*it);
740            }
741    
742            /**
743             * Returns an Iterator object of the Pool data member reflected by the
744             * given abstract, unique numeric ID, it returns an invalid Iterator in
745             * case the ID is invalid or if the Pool's data element reflected by
746             * given ID was at least once released/freed back to the Pool in the
747             * meantime.
748             *
749             * Members are always translated both, from Iterators/pointers to IDs,
750             * and from IDs to Iterators/pointers in constant time.
751             *
752             * You might want to use this alternative approach of referencing Pool
753             * members under certain scenarios. For example if you need to expose
754             * an ID to the end user and/or if you want to represent an object of
755             * this pool by a smaller number instead of a native pointer (i.e. 16
756             * bits vs. 64 bits). You can also detect this way whether the object
757             * has already been freed / reallocated from the Pool in the meantime.
758             *
759             * @param id - unique ID of a Pool's data member
760             * @returns Iterator object pointing to Pool's data element, invalid
761             *          Iterator in case ID was invalid or data element was freed
762             */
763            Iterator fromID(int id) const {
764                if (id < 0) return Iterator(); // invalid iterator
765                const uint bits = bitsForSize(poolsize);
766                uint index = id & ((1 << bits) - 1);
767                if (index >= poolsize) return Iterator(); // invalid iterator
768                Node* node = &nodes[index];
769                int reincarnation = uint(id) >> bits;
770                if (reincarnation != node->reincarnation) return Iterator(); // invalid iterator
771                return Iterator(node);
772            }
773    
774            /**
775             * Returns an Iterator object for the object pointed by @a obj. This
776             * method will check whether the supplied object is actually part of
777             * this pool, and if it is not part of this pool an invalid Iterator is
778             * returned instead.
779             *
780             * @param obj - raw pointer to an object managed by this pool
781             * @returns Iterator object pointing to the supplied object, invalid
782             *          Iterator in case object is not part of this pool
783             */
784            Iterator fromPtr(const T* obj) const {
785                if (!poolsize) return Iterator(); // invalid iterator
786                int index = obj - &data[0];
787                if (index < 0 || index >= poolsize) return Iterator(); // invalid iterator
788                return Iterator(&nodes[index]);
789            }
790    
791      protected:      protected:
792          // caution: assumes pool (that is freelist) is not empty!          // caution: assumes pool (that is freelist) is not empty!
793          inline Iterator alloc() {          inline Iterator alloc() {
# Line 437  class Pool : public RTList<T> { Line 797  class Pool : public RTList<T> {
797          }          }
798    
799          inline void freeToPool(Iterator itElement) {          inline void freeToPool(Iterator itElement) {
800                itElement.node()->reincarnation++;
801              freelist.append(itElement);              freelist.append(itElement);
802          }          }
803    
804          inline void freeToPool(Iterator itFirst, Iterator itLast) {          inline void freeToPool(Iterator itFirst, Iterator itLast) {
805                for (Node* n = itFirst.node(); true; n = n->next) {
806                    n->reincarnation++;
807                    if (n == itLast.node()) break;
808                }
809              freelist.append(itFirst, itLast);              freelist.append(itFirst, itLast);
810          }          }
811    
812          friend class RTList<T>;          friend class RTList<T>;
813    
814        private:
815            void _init(int Elements) {
816                data  = new T[Elements];
817                nodes = new Node[Elements];
818                for (int i = 0; i < Elements; i++) {
819                    nodes[i].data = &data[i];
820                    freelist.append(&nodes[i]);
821                }
822                poolsize = Elements;
823            }
824    
825            inline static int bitsForSize(int size) {
826                if (!size) return 0;
827                size--;
828                int bits = 0;
829                for (; size > 1; bits += 2, size >>= 2);
830                return bits + size;
831            }
832  };  };
833    
834  #endif // __LS_POOL_H__  #endif // __LS_POOL_H__

Legend:
Removed from v.271  
changed lines
  Added in v.2871

  ViewVC Help
Powered by ViewVC