/[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 554 by schoenebeck, Thu May 19 19:25:14 2005 UTC revision 3548 by schoenebeck, Wed Jul 31 09:35:10 2019 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 Christian Schoenebeck                              *   *   Copyright (C) 2005 - 2019 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 38  Line 38 
38  # include <string>  # include <string>
39  #endif // CONFIG_RT_EXCEPTIONS  #endif // CONFIG_RT_EXCEPTIONS
40    
41    #include <iostream>
42    
43  #if CONFIG_DEVMODE  #if CONFIG_DEVMODE
44  # include <string>  # include <string>
45  # include <iostream>  # include <stdexcept>
46  const std::string __err_msg_iterator_invalidated = "Pool/RTList iterator invalidated";  const std::string __err_msg_iterator_invalidated = "Pool/RTList iterator invalidated";
47  #endif // CONFIG_DEVMODE  #endif // CONFIG_DEVMODE
48    
49    const std::string __err_msg_resize_while_in_use = "Pool::resizePool() ERROR: elements still in use!";
50    
51    /**
52     * Unique numeric ID for exactly one incarnation of one element allocated from
53     * a Pool. As soon as the respective element is once freed back to the Pool,
54     * the ID becomes invalid. Such an ID may be used to safely store an abstract
55     * reference to one Pool element for longer time. Since the Pool classes
56     * automatically detect whether an ID became invalid, using such an ID is thus
57     * safer than storing an Iterator or even a raw pointer in use case scenarios of
58     * storing long term references to Pool elements.
59     *
60     * This ID type is currently set (constrained) to 32-bit because the current
61     * real-time instrument script infrastructure implementation, which heavily
62     * relies on element IDs, is currently using 32-bit for its integer script
63     * variable type.
64     */
65    typedef uint32_t pool_element_id_t;
66    
67  // just symbol prototyping  // just symbol prototyping
68  template<typename T> class Pool;  template<typename T> class Pool;
69  template<typename T> class RTList;  template<typename T> class RTList;
# Line 59  class RTListBase { Line 79  class RTListBase {
79              #if CONFIG_DEVMODE              #if CONFIG_DEVMODE
80              RTListBase<T1>* list; // list to which this node currently belongs to              RTListBase<T1>* list; // list to which this node currently belongs to
81              #endif // CONFIG_DEVMODE              #endif // CONFIG_DEVMODE
82                uint reincarnation; // just for Pool::fromID()
83    
84              _Node() {              _Node() {
85                  next = NULL;                  next = NULL;
# Line 67  class RTListBase { Line 88  class RTListBase {
88                  #if CONFIG_DEVMODE                  #if CONFIG_DEVMODE
89                  list = NULL;                  list = NULL;
90                  #endif // CONFIG_DEVMODE                  #endif // CONFIG_DEVMODE
91                    reincarnation = 0;
92                }
93    
94                inline void bumpReincarnation(uint bits) {
95                    reincarnation++;
96                    // constrain the bitrange of "reincarnation", because Pool::fromID() will shift up/down for pool_element_id_t and compare this bitwise
97                    reincarnation &= ((1 << bits) - 1);
98              }              }
99          };          };
100          typedef _Node<T> Node;          typedef _Node<T> Node;
101    
102      public:      public:
103            /**
104             * Pointer-like object which allows to iterate over elements of a RTList,
105             * similar to iterators of STL container classes. Note that the main
106             * purpose of this class is to access elements of a list / pool i.e.
107             * within a @c while() loop. If you rather want to keep a reference to
108             * one particular element (i.e. for longer time) then you might
109             * consider using @c pool_element_id_t variables instead.
110             */
111          template<typename T1>          template<typename T1>
112          class _Iterator {          class _Iterator {
113              public:              public:
# Line 143  class RTListBase { Line 179  class RTListBase {
179                      }                      }
180                      #endif // CONFIG_DEVMODE                      #endif // CONFIG_DEVMODE
181                      return *current->data;                      return *current->data;
182                    }
183    
184                    inline const T1& operator*() const {
185                        #if CONFIG_DEVMODE
186                        if (!isValid()) { // if iterator became invalidated
187                            #if CONFIG_RT_EXCEPTIONS
188                            throw std::runtime_error(__err_msg_iterator_invalidated);
189                            #else
190                            std::cerr << __err_msg_iterator_invalidated << std::endl << std::flush;
191                            return *((const T1*)NULL); // force segfault if iterator became invalidated
192                            #endif // CONFIG_RT_EXCEPTIONS
193                        }
194                        #endif // CONFIG_DEVMODE
195                        return *current->data;
196                  }                  }
197    
198                  inline T1* operator->() {                  inline T1* operator->() {
# Line 160  class RTListBase { Line 209  class RTListBase {
209                      return current->data;                      return current->data;
210                  }                  }
211    
212                  inline bool operator==(const _Iterator<T1> other) {                  inline const T1* operator->() const {
213                        #if CONFIG_DEVMODE
214                        if (!isValid()) { // if iterator became invalidated
215                            #if CONFIG_RT_EXCEPTIONS
216                            throw std::runtime_error(__err_msg_iterator_invalidated);
217                            #else
218                            std::cerr << __err_msg_iterator_invalidated << std::endl << std::flush;
219                            return (const T1*)NULL; // force segfault if iterator became invalidated
220                            #endif // CONFIG_RT_EXCEPTIONS
221                        }
222                        #endif // CONFIG_DEVMODE
223                        return current->data;
224                    }
225    
226                    inline bool operator==(const _Iterator<T1> other) const {
227                      return current == other.current;                      return current == other.current;
228                  }                  }
229    
230                  inline bool operator!=(const _Iterator<T1> other) {                  inline bool operator!=(const _Iterator<T1> other) const {
231                      return current != other.current;                      return current != other.current;
232                  }                  }
233    
# Line 176  class RTListBase { Line 239  class RTListBase {
239                      return !(current && current->data);                      return !(current && current->data);
240                  }                  }
241    
242                    /**
243                     * Moves the element pointed by this Iterator from its current
244                     * list to the beginning of the destination list @a pDstList.
245                     *
246                     * @b CAUTION: When this method returns, this Iterator does
247                     * @b NOT point to the element on the new list anymore, instead it
248                     * points at a completely different element! In case of a
249                     * forward Iterator this Iterator object will point to the
250                     * previous element on the source list, in case of a backward
251                     * Iterator it will point to the subsequent element on the
252                     * source list. This behavior is enforced to avoid breaking an
253                     * active loop code working with this Iterator object.
254                     *
255                     * Thus if you intend to continue working with the same element,
256                     * you should do like this:
257                     * @code
258                     * it = it.moveToEndOf(anotherList);
259                     * @endcode
260                     *
261                     * @param pDstList - destination list
262                     * @returns Iterator object pointing at the moved element on
263                     *          the destination list
264                     */
265                  inline _Iterator moveToEndOf(RTListBase<T1>* pDstList) {                  inline _Iterator moveToEndOf(RTListBase<T1>* pDstList) {
266                      detach();                      detach();
267                      pDstList->append(*this);                      pDstList->append(*this);
# Line 184  class RTListBase { Line 270  class RTListBase {
270                      return iterOnDstList;                      return iterOnDstList;
271                  }                  }
272    
273                    /**
274                     * Moves the element pointed by this Iterator from its current
275                     * list to the end of destination list @a pDstList.
276                     *
277                     * @b CAUTION: When this method returns, this Iterator does
278                     * @b NOT point to the element on the new list anymore, instead it
279                     * points at a completely different element! In case of a
280                     * forward Iterator this Iterator object will point to the
281                     * previous element on the source list, in case of a backward
282                     * Iterator it will point to the subsequent element on the
283                     * source list. This behavior is enforced to avoid breaking an
284                     * active loop code working with this Iterator object.
285                     *
286                     * Thus if you intend to continue working with the same element,
287                     * you should do like this:
288                     * @code
289                     * it = it.moveToBeginOf(anotherList);
290                     * @endcode
291                     *
292                     * @param pDstList - destination list
293                     * @returns Iterator object pointing at the moved element on
294                     *          the destination list
295                     */
296                  inline _Iterator moveToBeginOf(RTListBase<T1>* pDstList) {                  inline _Iterator moveToBeginOf(RTListBase<T1>* pDstList) {
297                      detach();                      detach();
298                      pDstList->prepend(*this);                      pDstList->prepend(*this);
# Line 192  class RTListBase { Line 301  class RTListBase {
301                      return iterOnDstList;                      return iterOnDstList;
302                  }                  }
303    
304                    /**
305                     * Moves the element pointed by this Iterator from its current
306                     * position to the position right before @a itDst. That move
307                     * may either be from and to the same list, or to a another
308                     * list.
309                     *
310                     * @b CAUTION: When this method returns, this Iterator does
311                     * @b NOT point to the element on the new list anymore, instead it
312                     * points at a completely different element! In case of a
313                     * forward Iterator this Iterator object will point to the
314                     * previous element on the source list, in case of a backward
315                     * Iterator it will point to the subsequent element on the
316                     * source list. This behavior is enforced to avoid breaking an
317                     * active loop code working with this Iterator object.
318                     *
319                     * Thus if you intend to continue working with the same element,
320                     * you should do like this:
321                     * @code
322                     * itSourceElement = itSourceElement.moveBefore(itDestinationElement);
323                     * @endcode
324                     *
325                     * @param itDst - destination element to be inserted before
326                     * @returns Iterator object pointing at the moved element on
327                     *          the destination list
328                     */
329                    inline _Iterator moveBefore(_Iterator<T1> itDst) {
330                        detach();
331                        RTList<T1>::prependBefore(*this, itDst);
332                        _Iterator iterOnDstList = _Iterator(current);
333                        current = fallback;
334                        return iterOnDstList;
335                    }
336    
337                    /**
338                     * Moves the element pointed by this Iterator from its current
339                     * position to the position right after @a itDst. That move
340                     * may either be from and to the same list, or to a another
341                     * list.
342                     *
343                     * @b CAUTION: When this method returns, this Iterator does
344                     * @b NOT point to the element on the new list anymore, instead it
345                     * points at a completely different element! In case of a
346                     * forward Iterator this Iterator object will point to the
347                     * previous element on the source list, in case of a backward
348                     * Iterator it will point to the subsequent element on the
349                     * source list. This behavior is enforced to avoid breaking an
350                     * active loop code working with this Iterator object.
351                     *
352                     * Thus if you intend to continue working with the same element,
353                     * you should do like this:
354                     * @code
355                     * itSourceElement = itSourceElement.moveAfter(itDestinationElement);
356                     * @endcode
357                     *
358                     * @param itDst - destination element to be inserted after
359                     * @returns Iterator object pointing at the moved element on
360                     *          the destination list
361                     */
362                    inline _Iterator moveAfter(_Iterator<T1> itDst) {
363                        detach();
364                        RTList<T1>::appendAfter(*this, itDst);
365                        _Iterator iterOnDstList = _Iterator(current);
366                        current = fallback;
367                        return iterOnDstList;
368                    }
369    
370                  #if CONFIG_DEVMODE                  #if CONFIG_DEVMODE
371                  inline bool isValid() {                  inline bool isValid() const {
372                      return current->list == list;                      return current->list == list;
373                  }                  }
374                  #endif // CONFIG_DEVMODE                  #endif // CONFIG_DEVMODE
# Line 230  class RTListBase { Line 405  class RTListBase {
405                      #endif // CONFIG_DEVMODE                      #endif // CONFIG_DEVMODE
406                  }                  }
407    
408                    inline const Node* node() const {
409                        #if CONFIG_DEVMODE
410                        #if CONFIG_RT_EXCEPTIONS
411                        if (isValid()) return current;
412                        else throw std::runtime_error(__err_msg_iterator_invalidated);
413                        #else
414                        return (isValid()) ? current : (const Node*)NULL; // force segfault if iterator became invalidated
415                        #endif // CONFIG_RT_EXCEPTIONS
416                        #else
417                        return current;
418                        #endif // CONFIG_DEVMODE
419                    }
420    
421                  inline void detach() {                  inline void detach() {
422                      RTListBase<T1>::detach(*this);                      RTListBase<T1>::detach(*this);
423                  }                  }
# Line 256  class RTListBase { Line 444  class RTListBase {
444              return Iterator(&_end, Iterator::dir_backward);              return Iterator(&_end, Iterator::dir_backward);
445          }          }
446    
447          inline bool isEmpty() {          inline bool isEmpty() const {
448              return _begin.next == &_end;              return _begin.next == &_end;
449          }          }
450    
451            inline int count() {
452                int elements = 0;
453                for (Iterator it = first(); it != end(); ++it) ++elements;
454                return elements;
455            }
456    
457      protected:      protected:
458          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!
459          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!
460    
461          RTListBase() {          RTListBase() {
462                init();
463            }
464    
465            void init() {
466              // initialize boundary nodes              // initialize boundary nodes
467              _begin.prev = &_begin;              _begin.prev = &_begin;
468              _begin.next = &_end;              _begin.next = &_end;
# Line 334  class RTListBase { Line 532  class RTListBase {
532              #endif // CONFIG_DEVMODE              #endif // CONFIG_DEVMODE
533          }          }
534    
535            static inline void prependBefore(Iterator itSrc, Iterator itDst) {
536                Node* src = itSrc.current;
537                Node* dst = itDst.current;
538                Node* prev = dst->prev;
539                prev->next = src;
540                dst->prev  = src;
541                src->prev  = prev;
542                src->next  = dst;
543                #if CONFIG_DEVMODE
544                src->list = dst->list;
545                #endif // CONFIG_DEVMODE
546            }
547    
548            static inline void appendAfter(Iterator itSrc, Iterator itDst) {
549                Node* src = itSrc.current;
550                Node* dst = itDst.current;
551                Node* next = dst->next;
552                next->prev = src;
553                dst->next  = src;
554                src->prev  = dst;
555                src->next  = next;
556                #if CONFIG_DEVMODE
557                src->list = dst->list;
558                #endif // CONFIG_DEVMODE
559            }
560    
561          static inline void detach(Iterator itElement) {          static inline void detach(Iterator itElement) {
562              Node* pNode = itElement.node();              Node* pNode = itElement.node();
563              Node* prev = pNode->prev; // if a segfault happens here, then because 'itElement' Iterator became invalidated              Node* prev = pNode->prev; // if a segfault happens here, then because 'itElement' Iterator became invalidated
# Line 369  class RTList : public RTListBase<T> { Line 593  class RTList : public RTListBase<T> {
593          RTList(Pool<T>* pPool) : RTListBase<T>::RTListBase() {          RTList(Pool<T>* pPool) : RTListBase<T>::RTListBase() {
594              this->pPool = pPool;              this->pPool = pPool;
595          }          }
596            
597            /**
598             * Copy constructor
599             */
600            RTList(RTList<T>& list) : RTListBase<T>::RTListBase() {
601                this->pPool = list.pPool;
602                Iterator it = list.first();
603                Iterator end = list.end();
604                for(; it != end; ++it) {
605                    if (poolIsEmpty()) break;
606                    *(allocAppend()) = *it;
607                }
608            }
609    
610          virtual ~RTList() {          virtual ~RTList() {
611              clear();              clear();
612          }          }
613    
614          inline bool poolIsEmpty() {          inline bool poolIsEmpty() const {
615              return pPool->poolIsEmpty();              return pPool->poolIsEmpty();
616          }          }
617    
618          inline Iterator allocAppend() {          inline Iterator allocAppend() {
619              if (pPool->poolIsEmpty()) return RTListBase<T>::begin();              if (pPool->poolIsEmpty()) return RTListBase<T>::begin();
620              Iterator element = pPool->alloc();              Iterator element = pPool->alloc();
621              append(element);              this->append(element);
622              #if CONFIG_DEVMODE              #if CONFIG_DEVMODE
623              element.list = this;              element.list = this;
624              #endif // CONFIG_DEVMODE              #endif // CONFIG_DEVMODE
# Line 391  class RTList : public RTListBase<T> { Line 628  class RTList : public RTListBase<T> {
628          inline Iterator allocPrepend() {          inline Iterator allocPrepend() {
629              if (pPool->poolIsEmpty()) return RTListBase<T>::end();              if (pPool->poolIsEmpty()) return RTListBase<T>::end();
630              Iterator element = pPool->alloc();              Iterator element = pPool->alloc();
631              prepend(element);              this->prepend(element);
632              #if CONFIG_DEVMODE              #if CONFIG_DEVMODE
633              element.list = this;              element.list = this;
634              #endif // CONFIG_DEVMODE              #endif // CONFIG_DEVMODE
# Line 413  class RTList : public RTListBase<T> { Line 650  class RTList : public RTListBase<T> {
650              }              }
651          }          }
652    
653            inline pool_element_id_t getID(const T* obj) const {
654                return pPool->getID(obj);
655            }
656    
657            inline pool_element_id_t getID(const Iterator& it) const {
658                return pPool->getID(&*it);
659            }
660    
661            inline Iterator fromID(pool_element_id_t id) const {
662                return pPool->fromID(id);
663            }
664    
665            inline Iterator fromPtr(const T* obj) const {
666                return pPool->fromPtr(obj);
667            }
668    
669      protected:      protected:
670          Pool<T>* pPool;          Pool<T>* pPool;
671  };  };
# Line 426  class Pool : public RTList<T> { Line 679  class Pool : public RTList<T> {
679          Node*         nodes;          Node*         nodes;
680          T*            data;          T*            data;
681          RTListBase<T> freelist; // not yet allocated elements          RTListBase<T> freelist; // not yet allocated elements
682            uint          poolsize;
683            // following 3 used for element ID generation (and vice versa)
684            uint          poolsizebits; ///< Amount of bits required to index all elements of this pool (according to current pool size).
685            uint          reservedbits; ///< 3rd party reserved bits on the left side of id (default: 0).
686            uint          reincarnationbits; ///< Amount of bits allowed for reincarnation counter.
687    
688          Pool(int Elements) : RTList<T>::RTList(this) {          Pool(int Elements) : RTList<T>::RTList(this), reservedbits(0) {
689              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]);  
             }  
690          }          }
691    
692          virtual ~Pool() {          virtual ~Pool() {
# Line 441  class Pool : public RTList<T> { Line 694  class Pool : public RTList<T> {
694              if (data)  delete[] data;              if (data)  delete[] data;
695          }          }
696    
697          inline bool poolIsEmpty() {          /**
698             * Returns true if there is at least one free element that could be
699             * allocated from the pool with i.e. allocAppend() or allocPreprend().
700             *
701             * @see poolHasFreeElements()
702             */
703            inline bool poolIsEmpty() const {
704              return freelist.isEmpty();              return freelist.isEmpty();
705          }          }
706    
707            /**
708             * Returns true if at least the requested amount of free @a elements is
709             * currently available for being allocated from the pool with i.e.
710             * allocAppend() or allocPreprend().
711             *
712             * @see poolIsEmpty()
713             */
714            bool poolHasFreeElements(int elements) {
715                for (Iterator it = freelist.first(); it != freelist.end() && elements >= 0; ++it)
716                    --elements;
717                return elements <= 0;
718            }
719    
720            int countFreeElements() {
721                return freelist.count();
722            }
723    
724            /**
725             * Returns the current size of the pool, that is the amount of
726             * pre-allocated elements from the operating system. It equals the
727             * amount of elements given to the constructor unless resizePool()
728             * is called.
729             *
730             * @see resizePool()
731             */
732            uint poolSize() const {
733                return poolsize;
734            }
735    
736            /**
737             * Alters the amount of elements to be pre-allocated from the
738             * operating system for this pool object.
739             *
740             * @e CAUTION: you MUST free all elements in use before calling this
741             * method ( e.g. by calling clear() )! Also make sure that no
742             * references of elements before this call will still be used after this
743             * call, since all elements will be reallocated and their old memory
744             * addresses become invalid!
745             *
746             * @see poolSize()
747             */
748            void resizePool(int Elements) {
749                if (freelist.count() != poolsize) {
750                    #if CONFIG_DEVMODE
751                    throw std::runtime_error(__err_msg_resize_while_in_use);
752                    #else
753                    std::cerr << __err_msg_resize_while_in_use << std::endl << std::flush;
754                    // if we're here something's terribly wrong, but we try to do the best
755                    RTList<T>::clear();
756                    #endif
757                }
758                if (nodes) delete[] nodes;
759                if (data)  delete[] data;
760                freelist.init();
761                RTListBase<T>::init();
762                _init(Elements);
763            }
764    
765            /**
766             * Sets the amount of bits on the left hand side of pool_element_id_t
767             * numbers to be reserved for 3rd party usage. So if you pass @c 1 for
768             * argument @a bits for example, then all generated element IDs will be
769             * maximum 31 bit large.
770             *
771             * By default there are no reserved bits, and thus by default all IDs
772             * are max. 32 bit large.
773             *
774             * @param bits - amount of bits to reserve on every ID for other purposes
775             * @see pool_element_id_t
776             */
777            void setPoolElementIDsReservedBits(uint bits) {
778                reservedbits = bits;
779                updateReincarnationBits();
780            }
781    
782            /**
783             * Returns an abstract, unique numeric ID for the given object of
784             * this pool, it returns 0 in case the passed object is not a member
785             * of this Pool, i.e. because it is simply an invalid pointer or member
786             * of another Pool. The returned ID is unique among all elements of this
787             * Pool and it differs with each reincarnation of an object. That means
788             * each time you free an element to and allocate the same element back
789             * from the Pool, it will have a different ID.
790             *
791             * A valid ID will never be zero, so you may use ID values of 0 in your
792             * data structures for special purposes (i.e. reflecting an invalid
793             * object ID or not yet assigned object).
794             *
795             * Members are always translated both, from Iterators/pointers to IDs,
796             * and from IDs to Iterators/pointers in constant time.
797             *
798             * You might want to use this alternative approach of referencing Pool
799             * members under certain scenarios. For example if you need to expose
800             * an ID to the end user and/or if you want to represent an object of
801             * this pool by a smaller number instead of a native pointer (i.e. 16
802             * bits vs. 64 bits). You can also detect this way whether the object
803             * has already been freed / reallocated from the Pool in the meantime.
804             *
805             * @param obj - raw pointer to a data member of this Pool
806             * @returns unique numeric ID (!= 0) of @a obj or 0 if pointer was invalid
807             */
808            pool_element_id_t getID(const T* obj) const {
809                if (!poolsize) return 0;
810                int index = int( obj - &data[0] );
811                if (index < 0 || index >= poolsize) return 0;
812                return ((nodes[index].reincarnation << poolsizebits) | index) + 1;
813            }
814    
815            /**
816             * Overridden convenience method, behaves like the method above.
817             */
818            pool_element_id_t getID(const Iterator& it) const {
819                return getID(&*it);
820            }
821    
822            /**
823             * Returns an Iterator object of the Pool data member reflected by the
824             * given abstract, unique numeric ID, it returns an invalid Iterator in
825             * case the ID is invalid or if the Pool's data element reflected by
826             * given ID was at least once released/freed back to the Pool in the
827             * meantime.
828             *
829             * Members are always translated both, from Iterators/pointers to IDs,
830             * and from IDs to Iterators/pointers in constant time.
831             *
832             * You might want to use this alternative approach of referencing Pool
833             * members under certain scenarios. For example if you need to expose
834             * an ID to the end user and/or if you want to represent an object of
835             * this pool by a smaller number instead of a native pointer (i.e. 16
836             * bits vs. 64 bits). You can also detect this way whether the object
837             * has already been freed / reallocated from the Pool in the meantime.
838             *
839             * @param id - unique ID (!= 0) of a Pool's data member
840             * @returns Iterator object pointing to Pool's data element, invalid
841             *          Iterator in case ID was invalid or data element was freed
842             */
843            Iterator fromID(pool_element_id_t id) const {
844                //TODO: -1 check here is a relict from older versions of Pool.h, once it is certain that no existing code base is still using -1 for "invalid" Pool elements then this -1 check can be removed
845                if (id == 0 || id == -1) return Iterator(); // invalid iterator
846                id--;
847                const uint bits = poolsizebits;
848                uint index = id & ((1 << bits) - 1);
849                if (index >= poolsize) return Iterator(); // invalid iterator
850                Node* node = &nodes[index];
851                uint reincarnation = id >> bits;
852                if (reincarnation != node->reincarnation) return Iterator(); // invalid iterator
853                return Iterator(node);
854            }
855    
856            /**
857             * Returns an Iterator object for the object pointed by @a obj. This
858             * method will check whether the supplied object is actually part of
859             * this pool, and if it is not part of this pool an invalid Iterator is
860             * returned instead.
861             *
862             * @param obj - raw pointer to an object managed by this pool
863             * @returns Iterator object pointing to the supplied object, invalid
864             *          Iterator in case object is not part of this pool
865             */
866            Iterator fromPtr(const T* obj) const {
867                if (!poolsize) return Iterator(); // invalid iterator
868                int index = int( obj - &data[0] );
869                if (index < 0 || index >= poolsize) return Iterator(); // invalid iterator
870                return Iterator(&nodes[index]);
871            }
872    
873      protected:      protected:
874          // caution: assumes pool (that is freelist) is not empty!          // caution: assumes pool (that is freelist) is not empty!
875          inline Iterator alloc() {          inline Iterator alloc() {
# Line 454  class Pool : public RTList<T> { Line 879  class Pool : public RTList<T> {
879          }          }
880    
881          inline void freeToPool(Iterator itElement) {          inline void freeToPool(Iterator itElement) {
882                itElement.node()->bumpReincarnation(reincarnationbits);
883              freelist.append(itElement);              freelist.append(itElement);
884          }          }
885    
886          inline void freeToPool(Iterator itFirst, Iterator itLast) {          inline void freeToPool(Iterator itFirst, Iterator itLast) {
887                for (Node* n = itFirst.node(); true; n = n->next) {
888                    n->bumpReincarnation(reincarnationbits);
889                    if (n == itLast.node()) break;
890                }
891              freelist.append(itFirst, itLast);              freelist.append(itFirst, itLast);
892          }          }
893    
894          friend class RTList<T>;          friend class RTList<T>;
895    
896        private:
897            void _init(int Elements) {
898                data  = new T[Elements];
899                nodes = new Node[Elements];
900                for (int i = 0; i < Elements; i++) {
901                    nodes[i].data = &data[i];
902                    freelist.append(&nodes[i]);
903                }
904                poolsize = Elements;
905                poolsizebits = bitsForSize(poolsize + 1); // +1 here just because IDs are always incremented by one (to avoid them ever being zero)
906                updateReincarnationBits();
907            }
908    
909            inline void updateReincarnationBits() {
910                reincarnationbits = sizeof(pool_element_id_t) * 8 - poolsizebits - reservedbits;
911            }
912    
913            inline static int bitsForSize(int size) {
914                if (!size) return 0;
915                size--;
916                int bits = 0;
917                for (; size > 1; bits += 2, size >>= 2);
918                return bits + size;
919            }
920  };  };
921    
922  #endif // __LS_POOL_H__  #endif // __LS_POOL_H__

Legend:
Removed from v.554  
changed lines
  Added in v.3548

  ViewVC Help
Powered by ViewVC