/[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 2878 by schoenebeck, Sun Apr 10 18:22:23 2016 UTC revision 2879 by schoenebeck, Tue Apr 19 14:07:53 2016 UTC
# Line 46  const std::string __err_msg_iterator_inv Line 46  const std::string __err_msg_iterator_inv
46    
47  const std::string __err_msg_resize_while_in_use = "Pool::resizePool() ERROR: elements still in use!";  const std::string __err_msg_resize_while_in_use = "Pool::resizePool() ERROR: elements still in use!";
48    
49    /**
50     * Unique numeric ID for exactly one incarnation of one element allocated from
51     * a Pool. As soon as the respective element is once freed back to the Pool,
52     * the ID becomes invalid. Such an ID may be used to safely store an abstract
53     * reference to one Pool element for longer time. Since the Pool classes
54     * automatically detect whether an ID became invalid, using such an ID is thus
55     * safer than storing an Iterator or even a raw pointer in use case scenarios of
56     * storing long term references to Pool elements.
57     *
58     * This ID type is currently set (constrained) to 32-bit because the current
59     * real-time instrument script infrastructure implementation, which heavily
60     * relies on element IDs, is currently using 32-bit for its integer script
61     * variable type.
62     */
63    typedef uint32_t pool_element_id_t;
64    
65  // just symbol prototyping  // just symbol prototyping
66  template<typename T> class Pool;  template<typename T> class Pool;
67  template<typename T> class RTList;  template<typename T> class RTList;
# Line 61  class RTListBase { Line 77  class RTListBase {
77              #if CONFIG_DEVMODE              #if CONFIG_DEVMODE
78              RTListBase<T1>* list; // list to which this node currently belongs to              RTListBase<T1>* list; // list to which this node currently belongs to
79              #endif // CONFIG_DEVMODE              #endif // CONFIG_DEVMODE
80              int reincarnation; // just for Pool::fromID()              uint reincarnation; // just for Pool::fromID()
81    
82              _Node() {              _Node() {
83                  next = NULL;                  next = NULL;
# Line 72  class RTListBase { Line 88  class RTListBase {
88                  #endif // CONFIG_DEVMODE                  #endif // CONFIG_DEVMODE
89                  reincarnation = 0;                  reincarnation = 0;
90              }              }
91    
92                inline void bumpReincarnation(uint bits) {
93                    reincarnation++;
94                    // constrain the bitrange of "reincarnation", because Pool::fromID() will shift up/down for pool_element_id_t and compare this bitwise
95                    reincarnation &= ((1 << bits) - 1);
96                }
97          };          };
98          typedef _Node<T> Node;          typedef _Node<T> Node;
99    
100      public:      public:
101            /**
102             * Pointer-like object which allows to iterate over elements of a RTList,
103             * similar to iterators of STL container classes. Note that the main
104             * purpose of this class is to access elements of a list / pool i.e.
105             * within a @c while() loop. If you rather want to keep a reference to
106             * one particular element (i.e. for longer time) then you might
107             * consider using @c pool_element_id_t variables instead.
108             */
109          template<typename T1>          template<typename T1>
110          class _Iterator {          class _Iterator {
111              public:              public:
# Line 626  class RTList : public RTListBase<T> { Line 656  class RTList : public RTListBase<T> {
656              return pPool->getID(&*it);              return pPool->getID(&*it);
657          }          }
658    
659          inline Iterator fromID(int id) const {          inline Iterator fromID(pool_element_id_t id) const {
660              return pPool->fromID(id);              return pPool->fromID(id);
661          }          }
662    
# Line 647  class Pool : public RTList<T> { Line 677  class Pool : public RTList<T> {
677          Node*         nodes;          Node*         nodes;
678          T*            data;          T*            data;
679          RTListBase<T> freelist; // not yet allocated elements          RTListBase<T> freelist; // not yet allocated elements
680          int           poolsize;          uint          poolsize;
681            // following 3 used for element ID generation (and vice versa)
682            uint          poolsizebits; ///< Amount of bits required to index all elements of this pool (according to current pool size).
683            uint          reservedbits; ///< 3rd party reserved bits on the left side of id (default: 0).
684            uint          reincarnationbits; ///< Amount of bits allowed for reincarnation counter.
685    
686          Pool(int Elements) : RTList<T>::RTList(this) {          Pool(int Elements) : RTList<T>::RTList(this), reservedbits(0) {
687              _init(Elements);              _init(Elements);
688          }          }
689    
# Line 670  class Pool : public RTList<T> { Line 704  class Pool : public RTList<T> {
704           *           *
705           * @see resizePool()           * @see resizePool()
706           */           */
707          int poolSize() const {          uint poolSize() const {
708              return poolsize;              return poolsize;
709          }          }
710    
# Line 704  class Pool : public RTList<T> { Line 738  class Pool : public RTList<T> {
738          }          }
739    
740          /**          /**
741             * Sets the amount of bits on the left hand side of pool_element_id_t
742             * numbers to be reserved for 3rd party usage. So if you pass @c 1 for
743             * argument @a bits for example, then all generated element IDs will be
744             * maximum 31 bit large.
745             *
746             * By default there are no reserved bits, and thus by default all IDs
747             * are max. 32 bit large.
748             *
749             * @param bits - amount of bits to reserve on every ID for other purposes
750             * @see pool_element_id_t
751             */
752            void setPoolElementIDsReservedBits(uint bits) {
753                reservedbits = bits;
754                updateReincarnationBits();
755            }
756    
757            /**
758           * Returns an abstract, unique numeric ID for the given object of           * Returns an abstract, unique numeric ID for the given object of
759           * this pool, it returns -1 in case the passed object is not a member           * this pool, it returns 0 in case the passed object is not a member
760           * of this Pool, i.e. because it is simply an invalid pointer or member           * of this Pool, i.e. because it is simply an invalid pointer or member
761           * of another Pool. The returned ID is unique among all elements of this           * of another Pool. The returned ID is unique among all elements of this
762           * Pool and it differs with each reincarnation of an object. That means           * Pool and it differs with each reincarnation of an object. That means
763           * each time you free an element to and allocate the same element back           * each time you free an element to and allocate the same element back
764           * from the Pool, it will have a different ID.           * from the Pool, it will have a different ID.
765             *
766             * A valid ID will never be zero, so you may use ID values of 0 in your
767             * data structures for special purposes (i.e. reflecting an invalid
768             * object ID or not yet assigned object).
769           *           *
770           * Members are always translated both, from Iterators/pointers to IDs,           * Members are always translated both, from Iterators/pointers to IDs,
771           * and from IDs to Iterators/pointers in constant time.           * and from IDs to Iterators/pointers in constant time.
# Line 723  class Pool : public RTList<T> { Line 778  class Pool : public RTList<T> {
778           * has already been freed / reallocated from the Pool in the meantime.           * has already been freed / reallocated from the Pool in the meantime.
779           *           *
780           * @param obj - raw pointer to a data member of this Pool           * @param obj - raw pointer to a data member of this Pool
781           * @returns unique numeric ID of @a obj or -1 if pointer was invalid           * @returns unique numeric ID (!= 0) of @a obj or 0 if pointer was invalid
782           */           */
783          int getID(const T* obj) const {          pool_element_id_t getID(const T* obj) const {
784              if (!poolsize) return -1;              if (!poolsize) return 0;
785              int index = obj - &data[0];              int index = obj - &data[0];
786              if (index < 0 || index >= poolsize) return -1;              if (index < 0 || index >= poolsize) return 0;
787              return (nodes[index].reincarnation << bitsForSize(poolsize)) | index;              return ((nodes[index].reincarnation << poolsizebits) | index) + 1;
788          }          }
789    
790          /**          /**
# Line 756  class Pool : public RTList<T> { Line 811  class Pool : public RTList<T> {
811           * bits vs. 64 bits). You can also detect this way whether the object           * bits vs. 64 bits). You can also detect this way whether the object
812           * has already been freed / reallocated from the Pool in the meantime.           * has already been freed / reallocated from the Pool in the meantime.
813           *           *
814           * @param id - unique ID of a Pool's data member           * @param id - unique ID (!= 0) of a Pool's data member
815           * @returns Iterator object pointing to Pool's data element, invalid           * @returns Iterator object pointing to Pool's data element, invalid
816           *          Iterator in case ID was invalid or data element was freed           *          Iterator in case ID was invalid or data element was freed
817           */           */
818          Iterator fromID(int id) const {          Iterator fromID(pool_element_id_t id) const {
819              if (id < 0) return Iterator(); // invalid iterator              //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
820              const uint bits = bitsForSize(poolsize);              if (id == 0 || id == -1) return Iterator(); // invalid iterator
821                id--;
822                const uint bits = poolsizebits;
823              uint index = id & ((1 << bits) - 1);              uint index = id & ((1 << bits) - 1);
824              if (index >= poolsize) return Iterator(); // invalid iterator              if (index >= poolsize) return Iterator(); // invalid iterator
825              Node* node = &nodes[index];              Node* node = &nodes[index];
826              int reincarnation = uint(id) >> bits;              uint reincarnation = id >> bits;
827              if (reincarnation != node->reincarnation) return Iterator(); // invalid iterator              if (reincarnation != node->reincarnation) return Iterator(); // invalid iterator
828              return Iterator(node);              return Iterator(node);
829          }          }
# Line 797  class Pool : public RTList<T> { Line 854  class Pool : public RTList<T> {
854          }          }
855    
856          inline void freeToPool(Iterator itElement) {          inline void freeToPool(Iterator itElement) {
857              itElement.node()->reincarnation++;              itElement.node()->bumpReincarnation(reincarnationbits);
858              freelist.append(itElement);              freelist.append(itElement);
859          }          }
860    
861          inline void freeToPool(Iterator itFirst, Iterator itLast) {          inline void freeToPool(Iterator itFirst, Iterator itLast) {
862              for (Node* n = itFirst.node(); true; n = n->next) {              for (Node* n = itFirst.node(); true; n = n->next) {
863                  n->reincarnation++;                  n->bumpReincarnation(reincarnationbits);
864                  if (n == itLast.node()) break;                  if (n == itLast.node()) break;
865              }              }
866              freelist.append(itFirst, itLast);              freelist.append(itFirst, itLast);
# Line 820  class Pool : public RTList<T> { Line 877  class Pool : public RTList<T> {
877                  freelist.append(&nodes[i]);                  freelist.append(&nodes[i]);
878              }              }
879              poolsize = Elements;              poolsize = Elements;
880                poolsizebits = bitsForSize(poolsize + 1); // +1 here just because IDs are always incremented by one (to avoid them ever being zero)
881                updateReincarnationBits();
882            }
883    
884            inline void updateReincarnationBits() {
885                reincarnationbits = sizeof(pool_element_id_t) * 8 - poolsizebits - reservedbits;
886          }          }
887    
888          inline static int bitsForSize(int size) {          inline static int bitsForSize(int size) {

Legend:
Removed from v.2878  
changed lines
  Added in v.2879

  ViewVC Help
Powered by ViewVC