opennurbs_lookup.h
Go to the documentation of this file.
00001 /* $NoKeywords: $ */
00002 /*
00003 //
00004 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
00005 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
00006 // McNeel & Associates.
00007 //
00008 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
00009 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
00010 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
00011 //                              
00012 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
00013 //
00015 */
00016 
00017 #if !defined(OPENNURBS_MAP_INC_)
00018 #define OPENNURBS_MAP_INC_
00019 
00020 /*
00021 Description:
00022   ON_SerialNumberMap provides a way to map set of unique 
00023   serial number - uuid pairs to application defined values
00024   so that adding, finding and removing serial numbers is 
00025   fast and efficient.  The class is designed to handle
00026   several millions of unique serial numbers.  There are no
00027   restrictions on what order numbers are added and removed.
00028   The minimum memory footprint is less than 150KB and doesn't
00029   increase until you have more than 8000 serial numbers.
00030   It is possible to have an active serial number and an
00031   inactive id.
00032 */
00033 class ON_CLASS ON_SerialNumberMap
00034 {
00035 public:
00036   ON_SerialNumberMap( ON_MEMORY_POOL* pool = 0 );
00037   ~ON_SerialNumberMap();
00038 
00039   struct MAP_VALUE
00040   {
00041     ON__UINT32 m_u_type;
00042     union
00043     {
00044       void* ptr;
00045       unsigned int ui;
00046       int i;
00047     } m_u;
00048   };
00049 
00050   struct SN_ELEMENT
00051   {
00053     //
00054     // ID
00055     //
00056     ON_UUID m_id;
00057     struct SN_ELEMENT* m_next; // id hash table linked list
00058 
00060     //
00061     // Serial number:
00062     //
00063     unsigned int m_sn;
00064 
00066     //
00067     // Status flags:
00068     //
00069     // If m_id_active is 1, then m_sn_active must be 1.
00070     // If m_sn_active = 1, then m_id_active can be 0 or 1.
00071     //
00072     unsigned char m_sn_active; // 1 = serial number is active
00073     unsigned char m_id_active; // 1 = id is active
00074     unsigned char m_reserved1;
00075     unsigned char m_reserved2;
00076 
00078     //
00079     // User information:
00080     //
00081     //   ON_SerialNumberMap does not use the m_value field.
00082     //   When a new element is added, m_value is memset to
00083     //   zero.  Other than that, m_value is not changed by
00084     //   this class.  The location of m_value in memory,
00085     //   (&m_value) may change at any time.
00086     struct MAP_VALUE m_value;
00087 
00088     void Dump(ON_TextLog&) const;
00089   };
00090 
00091   /*
00092   Returns:
00093     Number of active serial numbers in the list.
00094   */
00095   size_t ActiveSerialNumberCount() const;
00096 
00097   /*
00098   Returns:
00099     Number of active ids in the list.  This number
00100     is less than or equal to ActiveSerialNumberCount().
00101   */
00102   size_t ActiveIdCount() const;
00103 
00104   /*
00105   Returns:
00106     The active element with the smallest serial number, 
00107     or null if the list is empty.
00108   Restrictions:
00109     The returned pointer may become invalid after any
00110     subsequent calls to any function in this class.  
00111     If you need to save information in the returned
00112     SN_ELEMENT for future use, you must copy the 
00113     information into storage you are managing.
00114 
00115     You may change the value of the SN_ELEMENT's m_value
00116     field.  You must NEVER change any other SN_ELEMENT
00117     fields or you will break searching and possibly cause
00118     crashes.
00119   */
00120   struct SN_ELEMENT* FirstElement() const;
00121 
00122   /*
00123   Returns:
00124     The active element with the biggest serial number,
00125     or null if the list is empty.
00126   Restrictions:
00127     The returned pointer may become invalid after any
00128     subsequent calls to any function in this class.  
00129     If you need to save information in the returned
00130     SN_ELEMENT for future use, you must copy the 
00131     information into storage you are managing.
00132 
00133     You may change the value of the SN_ELEMENT's m_value
00134     field.  You must NEVER change any other SN_ELEMENT
00135     fields or you will break searching and possibly cause
00136     crashes.
00137   */
00138   struct SN_ELEMENT* LastElement() const;
00139 
00140   /*
00141   Parameters:
00142     sn - [in] serial number to search for.
00143   Returns:
00144     If the serial number is active, a pointer to
00145     its element is returned.
00146   Restrictions:
00147     The returned pointer may become invalid after any
00148     subsequent calls to any function in this class.  
00149     If you need to save information in the returned
00150     SN_ELEMENT for future use, you must copy the 
00151     information into storage you are managing.
00152 
00153     You may change the value of the SN_ELEMENT's m_value
00154     field.  You must NEVER change any other SN_ELEMENT
00155     fields or you will break searching and possibly cause
00156     crashes.
00157   */
00158   struct SN_ELEMENT* FindSerialNumber(unsigned int sn) const;
00159 
00160   /*
00161   Parameters:
00162     id - [in] id number to search for.
00163   Returns:
00164     If the id is active, a pointer to
00165     its element is returned.
00166   Restrictions:
00167     The returned pointer may become invalid after any
00168     subsequent calls to any function in this class.  
00169     If you need to save information in the returned
00170     SN_ELEMENT for future use, you must copy the 
00171     information into storage you are managing.
00172 
00173     You may change the value of the SN_ELEMENT's m_value
00174     field.  You must NEVER change any other SN_ELEMENT
00175     fields or you will break searching and possibly cause
00176     crashes.
00177   */
00178   struct SN_ELEMENT* FindId(ON_UUID) const;
00179 
00180   /*
00181   Description:
00182     Add a serial number to the map.
00183   Parameters:
00184     sn - [in] serial number to add.
00185   Returns:
00186     If the serial number is valid (>0), a pointer to its
00187     element is returned.  When a new element is added, 
00188     every byte of the m_value field is set to 0.
00189     If the serial number was already active, its element is
00190     also returned.  If you need to distinguish between new
00191     and previously existing elements, then change  
00192     m_value.m_u_type to something besides 0 after you add
00193     a new serial number.  The id associated with this
00194     serial number will be zero and cannot be found using
00195     FindId().
00196   Restrictions:
00197     The returned pointer may become invalid after any
00198     subsequent calls to any function in this class.  
00199     If you need to save information in the returned
00200     SN_ELEMENT for future use, you must copy the 
00201     information into storage you are managing.
00202 
00203     You may change the value of the SN_ELEMENT's m_value
00204     field.  You must NEVER change any other SN_ELEMENT
00205     fields or you will break searching and possibly cause
00206     crashes.
00207   */
00208   struct SN_ELEMENT* AddSerialNumber(unsigned int sn);
00209 
00210   /*
00211   Parameters:
00212     sn - [in] serial number to add.
00213     id - [in] suggested id to add. If id is zero or
00214               already in use, another id will be assigned
00215               to the element.
00216   Returns:
00217     If the serial number is valid (>0), a pointer to its
00218     element is returned.  When a new element is added, 
00219     every byte of the m_value field is set to 0.
00220     If the serial number was already active, its element is
00221     also returned.  If you need to distinguish between new
00222     and previously existing elements, then change  
00223     m_value.m_u_type to something besides 0 after you add
00224     a new serial number. 
00225     If the id parameter is zero, then a new uuid is created
00226     and added. If the id parameter is non zero but is active
00227     on another element, a new uuid is created and added.
00228     You can inspect the value of m_id on the returned element
00229     to determine the id AddSerialNumberAndId() assigned to
00230     the element.
00231   Restrictions:
00232     The returned pointer may become invalid after any
00233     subsequent calls to any function in this class.  
00234     If you need to save information in the returned
00235     SN_ELEMENT for future use, you must copy the 
00236     information into storage you are managing.
00237 
00238     You may change the value of the SN_ELEMENT's m_value
00239     field.  You must NEVER change any other SN_ELEMENT
00240     fields or you will break searching and possibly cause
00241     crashes.
00242   */
00243   struct SN_ELEMENT* AddSerialNumberAndId(unsigned int sn, ON_UUID id);
00244 
00245   /*
00246   Parameters:
00247     sn - [in] serial number of the element to remove.
00248   Returns:
00249     If the serial number was active, it is removed
00250     and a pointer to its element is returned.  If
00251     the element's id was active, the id is also removed.
00252   Restrictions:
00253     The returned pointer may become invalid after any
00254     subsequent calls to any function in this class.  
00255     If you need to save information in the returned
00256     SN_ELEMENT for future use, you must copy the 
00257     information into storage you are managing.
00258 
00259     You may change the value of the SN_ELEMENT's m_value
00260     field.  You must NEVER change any other SN_ELEMENT
00261     fields or you will break searching and possibly cause
00262     crashes.
00263   */
00264   struct SN_ELEMENT* RemoveSerialNumberAndId(unsigned int sn);
00265 
00266   /*
00267   Parameters:
00268     sn - [in] If > 0, this is the serial number
00269               of the element with the id. If 0, the
00270               field is ignored.
00271     id - [in] id to search for.
00272   Returns:
00273     If the id was active, it is removed and a pointer
00274     to its element is returned.  The element's serial
00275     remains active. To remove both the id and serial number,
00276     use RemoveSerialNumberAndId().
00277   Restrictions:
00278     The returned pointer may become invalid after any
00279     subsequent calls to any function in this class.  
00280     If you need to save information in the returned
00281     SN_ELEMENT for future use, you must copy the 
00282     information into storage you are managing.
00283 
00284     You may change the value of the SN_ELEMENT's m_value
00285     field.  You must NEVER change any other SN_ELEMENT
00286     fields or you will break searching and possibly cause
00287     crashes.
00288   */
00289   struct SN_ELEMENT* RemoveId(unsigned int sn, ON_UUID id);
00290 
00291   /*
00292   Description:
00293     Finds all the elements whose serial numbers are
00294     in the range sn0 <= sn <= sn1 and appends them
00295     to the elements[] array.  If max_count > 0, it
00296     specifies the maximum number of elements to append.
00297   Parameters:
00298     sn0 - [in]
00299       Minimum serial number.
00300     sn1 - [in]
00301       Maximum serial number
00302     max_count - [in]
00303       If max_count > 0, this parameter specifies the
00304       maximum number of elements to append.
00305     elements - [out]
00306       Elements are appended to this array
00307   Returns:
00308     Number of elements appended to elements[] array.
00309   Remarks:
00310     When many elements are returned, GetElements() can be
00311     substantially faster than repeated calls to FindElement().
00312   */
00313   size_t GetElements(
00314           unsigned int sn0,
00315           unsigned int sn1, 
00316           size_t max_count,
00317           ON_SimpleArray<SN_ELEMENT>& elements
00318           ) const;
00319 
00320   /*
00321   Description:
00322     Empties the list.
00323   */
00324   void EmptyList();
00325 
00326   /*
00327   Description:
00328     Returns true if the map is valid.  Returns false if the
00329     map is not valid.  If an error is found and textlog
00330     is not null, then a description of the problem is sent
00331     to textlog.
00332   Returns:
00333     true if the list if valid.
00334   */
00335   bool IsValid(ON_TextLog* textlog) const;
00336 
00337   void Dump(ON_TextLog& text_log) const;
00338 
00339 private:
00340   // prohibit copy construction and operator=
00341   // no implementation
00342   ON_SerialNumberMap(const ON_SerialNumberMap&);
00343   ON_SerialNumberMap& operator=(const ON_SerialNumberMap&);
00344 
00345   enum
00346   {
00347     // These numbers are chosen so the ON_SerialNumberMap
00348     // will be computationally efficient for up to
00349     // 10 million entries.
00350     SN_BLOCK_CAPACITY = 8192,
00351     SN_PURGE_RATIO = 16,
00352     ID_HASH_TABLE_COUNT = 8192
00353   };
00354 
00355   struct SN_BLOCK
00356   {
00357     size_t m_count;  // used elements in m_sn[]
00358     size_t m_purged; // number of purged elements in m_sn[]
00359     unsigned int m_sorted; // 0 = no, 1 = yes
00360     unsigned int m_sn0; // minimum sn in m_sn[]
00361     unsigned int m_sn1; // maximum sn in m_sn[]
00362     struct SN_ELEMENT m_sn[SN_BLOCK_CAPACITY];
00363     void EmptyBlock();
00364     void CullBlockHelper();
00365     void SortBlockHelper();
00366     bool IsValidBlock(ON_TextLog* textlog,struct SN_ELEMENT*const* hash_table,size_t* active_id_count) const;
00367     struct SN_ELEMENT* BinarySearchBlockHelper(unsigned int sn);
00368     static int CompareMaxSN(const void*,const void*);
00369     size_t ActiveElementEstimate(unsigned int sn0, unsigned int sn1) const;
00370     void Dump(ON_TextLog&) const;
00371   };
00372 
00373   unsigned int m_maxsn; // largest sn stored anywhere
00374   unsigned int m_reserved;
00375 
00376   // All heap used in this class is allocated from this pool.
00377   ON_MEMORY_POOL* m_pool;
00378 
00379   // Serial Number list counts
00380   size_t m_sn_count;   // total number of elements                       
00381   size_t m_sn_purged;  // total number of purged elements
00382 
00383   // ID hash table counts (all ids in the hash table are active)
00384   bool m_bHashTableIsValid; // true if m_hash_table[] is valid
00385   size_t m_active_id_count; // number of active ids in the hash table
00386   ON_UUID m_inactive_id;    // frequently and id is removed and
00387                             // then added back.  m_inactive_id
00388                             // records the most recently removed
00389                             // id so we don't have to waste time
00390                             // searching the hash table for
00391                             // an id that is not there.
00392                             
00393 
00394   // The blocks in m_sn_list[] are alwasy sorted, disjoint,
00395   // and in increasing order.  m_sn_list is used when
00396   // m_sn_block0.m_sn[] is not large enough.
00397   // The sn list is partitioned into blocks to avoid
00398   // requiring large amounts of contiguous memory for
00399   // situations with millions of serial numbers.
00400   struct SN_BLOCK** m_snblk_list;
00401   size_t m_snblk_list_capacity; // capacity of m_blk_list[]
00402   size_t m_snblk_list_count;    // used elements in m_snblk_list[]
00403 
00404   // If FindElementHelper() returns a non-null pointer
00405   // to an element, then m_e_blk points to the SN_BLOCK
00406   // that contains the returned element.  In all other
00407   // situations the value in m_e_blk is undefined and
00408   // m_e_blk must not be dereferenced.
00409   struct SN_BLOCK* m_e_blk;
00410 
00411   // m_sn_block0 is where the new additions are added.
00412   // When serial numbers are not added in increasing
00413   // order, m_sn_block0.m_sn[] may not be sorted.
00414   SN_BLOCK m_sn_block0;
00415 
00416   struct SN_ELEMENT* FindElementHelper(unsigned int sn);
00417   void UpdateMaxSNHelper();
00418   void GarbageCollectHelper();
00419   size_t GarbageCollectMoveHelper(SN_BLOCK* dst,SN_BLOCK* src);
00420 
00421   // When m_bHashTableIsValid is true, then m_hash_table[i] is 
00422   // a linked list of elements whose id satisfies 
00423   // i = HashIndex(&e->m_id).  When m_bHashTableIsValid is false,
00424   // m_hash_table[] is identically zero.
00425   struct SN_ELEMENT* m_hash_table[ID_HASH_TABLE_COUNT];
00426   size_t HashIndex(const ON_UUID*) const;
00427   void InvalidateHashTableHelper(); // marks table as dirty
00428   bool RemoveBlockFromHashTableHelper(const struct SN_BLOCK* blk);
00429   void AddBlockToHashTableHelper(struct SN_BLOCK* blk);
00430   void BuildHashTableHelper();      // prepares table for use
00431 };
00432 
00433 
00434 #endif


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:27:01