QCAD
Open Source 2D CAD
Loading...
Searching...
No Matches
opennurbs_lookup.h
Go to the documentation of this file.
1/* $NoKeywords: $ */
2/*
3//
4// Copyright (c) 1993-2008 Robert McNeel & Associates. All rights reserved.
5// Rhinoceros is a registered trademark of Robert McNeel & Assoicates.
6//
7// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
8// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
9// MERCHANTABILITY ARE HEREBY DISCLAIMED.
10//
11// For complete openNURBS copyright information see <http://www.opennurbs.org>.
12//
14*/
15
16#if !defined(OPENNURBS_MAP_INC_)
17#define OPENNURBS_MAP_INC_
18
19/*
20Description:
21 ON_SerialNumberMap provides a way to map set of unique
22 serial number - uuid pairs to application defined values
23 so that adding, finding and removing serial numbers is
24 fast and efficient. The class is designed to handle
25 several millions of unique serial numbers. There are no
26 restrictions on what order numbers are added and removed.
27 The minimum memory footprint is less than 150KB and doesn't
28 increase until you have more than 8000 serial numbers.
29 It is possible to have an active serial number and an
30 inactive id.
31*/
33{
34public:
37
38 struct MAP_VALUE
39 {
41 union
42 {
43 void* ptr;
44 unsigned int ui;
45 int i;
46 } m_u;
47 };
48
50 {
52 //
53 // ID
54 //
56 struct SN_ELEMENT* m_next; // id hash table linked list
57
59 //
60 // Serial number:
61 //
62 unsigned int m_sn;
63
65 //
66 // Status flags:
67 //
68 // If m_id_active is 1, then m_sn_active must be 1.
69 // If m_sn_active = 1, then m_id_active can be 0 or 1.
70 //
71 unsigned char m_sn_active; // 1 = serial number is active
72 unsigned char m_id_active; // 1 = id is active
73 unsigned char m_reserved1;
74 unsigned char m_reserved2;
75
77 //
78 // User information:
79 //
80 // ON_SerialNumberMap does not use the m_value field.
81 // When a new element is added, m_value is memset to
82 // zero. Other than that, m_value is not changed by
83 // this class. The location of m_value in memory,
84 // (&m_value) may change at any time.
85 struct MAP_VALUE m_value;
86 };
87
88 /*
89 Returns:
90 Number of active serial numbers in the list.
91 */
92 size_t ActiveSerialNumberCount() const;
93
94 /*
95 Returns:
96 Number of active ids in the list. This number
97 is less than or equal to ActiveSerialNumberCount().
98 */
99 size_t ActiveIdCount() const;
100
101 /*
102 Returns:
103 The active element with the smallest serial number,
104 or null if the list is empty.
105 Restrictions:
106 The returned pointer may become invalid after any
107 subsequent calls to any function in this class.
108 If you need to save information in the returned
109 SN_ELEMENT for future use, you must copy the
110 information into storage you are managing.
111
112 You may change the value of the SN_ELEMENT's m_value
113 field. You must NEVER change any other SN_ELEMENT
114 fields or you will break searching and possibly cause
115 crashes.
116 */
117 struct SN_ELEMENT* FirstElement() const;
118
119 /*
120 Returns:
121 The active element with the biggest serial number,
122 or null if the list is empty.
123 Restrictions:
124 The returned pointer may become invalid after any
125 subsequent calls to any function in this class.
126 If you need to save information in the returned
127 SN_ELEMENT for future use, you must copy the
128 information into storage you are managing.
129
130 You may change the value of the SN_ELEMENT's m_value
131 field. You must NEVER change any other SN_ELEMENT
132 fields or you will break searching and possibly cause
133 crashes.
134 */
135 struct SN_ELEMENT* LastElement() const;
136
137 /*
138 Parameters:
139 sn - [in] serial number to search for.
140 Returns:
141 If the serial number is active, a pointer to
142 its element is returned.
143 Restrictions:
144 The returned pointer may become invalid after any
145 subsequent calls to any function in this class.
146 If you need to save information in the returned
147 SN_ELEMENT for future use, you must copy the
148 information into storage you are managing.
149
150 You may change the value of the SN_ELEMENT's m_value
151 field. You must NEVER change any other SN_ELEMENT
152 fields or you will break searching and possibly cause
153 crashes.
154 */
155 struct SN_ELEMENT* FindSerialNumber(unsigned int sn) const;
156
157 /*
158 Parameters:
159 id - [in] id number to search for.
160 Returns:
161 If the id is active, a pointer to
162 its element is returned.
163 Restrictions:
164 The returned pointer may become invalid after any
165 subsequent calls to any function in this class.
166 If you need to save information in the returned
167 SN_ELEMENT for future use, you must copy the
168 information into storage you are managing.
169
170 You may change the value of the SN_ELEMENT's m_value
171 field. You must NEVER change any other SN_ELEMENT
172 fields or you will break searching and possibly cause
173 crashes.
174 */
175 struct SN_ELEMENT* FindId(ON_UUID) const;
176
177 /*
178 Description:
179 Add a serial number to the map.
180 Parameters:
181 sn - [in] serial number to add.
182 Returns:
183 If the serial number is valid (>0), a pointer to its
184 element is returned. When a new element is added,
185 every byte of the m_value field is set to 0.
186 If the serial number was already active, its element is
187 also returned. If you need to distinguish between new
188 and previously existing elements, then change
189 m_value.m_u_type to something besides 0 after you add
190 a new serial number. The id associated with this
191 serial number will be zero and cannot be found using
192 FindId().
193 Restrictions:
194 The returned pointer may become invalid after any
195 subsequent calls to any function in this class.
196 If you need to save information in the returned
197 SN_ELEMENT for future use, you must copy the
198 information into storage you are managing.
199
200 You may change the value of the SN_ELEMENT's m_value
201 field. You must NEVER change any other SN_ELEMENT
202 fields or you will break searching and possibly cause
203 crashes.
204 */
205 struct SN_ELEMENT* AddSerialNumber(unsigned int sn);
206
207 /*
208 Parameters:
209 sn - [in] serial number to add.
210 id - [in] suggested id to add. If id is zero or
211 already in use, another id will be assigned
212 to the element.
213 Returns:
214 If the serial number is valid (>0), a pointer to its
215 element is returned. When a new element is added,
216 every byte of the m_value field is set to 0.
217 If the serial number was already active, its element is
218 also returned. If you need to distinguish between new
219 and previously existing elements, then change
220 m_value.m_u_type to something besides 0 after you add
221 a new serial number.
222 If the id parameter is zero, then a new uuid is created
223 and added. If the id parameter is non zero but is active
224 on another element, a new uuid is created and added.
225 You can inspect the value of m_id on the returned element
226 to determine the id AddSerialNumberAndId() assigned to
227 the element.
228 Restrictions:
229 The returned pointer may become invalid after any
230 subsequent calls to any function in this class.
231 If you need to save information in the returned
232 SN_ELEMENT for future use, you must copy the
233 information into storage you are managing.
234
235 You may change the value of the SN_ELEMENT's m_value
236 field. You must NEVER change any other SN_ELEMENT
237 fields or you will break searching and possibly cause
238 crashes.
239 */
240 struct SN_ELEMENT* AddSerialNumberAndId(unsigned int sn, ON_UUID id);
241
242 /*
243 Parameters:
244 sn - [in] serial number of the element to remove.
245 Returns:
246 If the serial number was active, it is removed
247 and a pointer to its element is returned. If
248 the element's id was active, the id is also removed.
249 Restrictions:
250 The returned pointer may become invalid after any
251 subsequent calls to any function in this class.
252 If you need to save information in the returned
253 SN_ELEMENT for future use, you must copy the
254 information into storage you are managing.
255
256 You may change the value of the SN_ELEMENT's m_value
257 field. You must NEVER change any other SN_ELEMENT
258 fields or you will break searching and possibly cause
259 crashes.
260 */
261 struct SN_ELEMENT* RemoveSerialNumberAndId(unsigned int sn);
262
263 /*
264 Parameters:
265 sn - [in] If > 0, this is the serial number
266 of the element with the id. If 0, the
267 field is ignored.
268 id - [in] id to search for.
269 Returns:
270 If the id was active, it is removed and a pointer
271 to its element is returned. The element's serial
272 remains active. To remove both the id and serial number,
273 use RemoveSerialNumberAndId().
274 Restrictions:
275 The returned pointer may become invalid after any
276 subsequent calls to any function in this class.
277 If you need to save information in the returned
278 SN_ELEMENT for future use, you must copy the
279 information into storage you are managing.
280
281 You may change the value of the SN_ELEMENT's m_value
282 field. You must NEVER change any other SN_ELEMENT
283 fields or you will break searching and possibly cause
284 crashes.
285 */
286 struct SN_ELEMENT* RemoveId(unsigned int sn, ON_UUID id);
287
288 /*
289 Description:
290 Finds all the elements whose serial numbers are
291 in the range sn0 <= sn <= sn1 and appends them
292 to the elements[] array. If max_count > 0, it
293 specifies the maximum number of elements to append.
294 Parameters:
295 sn0 - [in]
296 Minimum serial number.
297 sn1 - [in]
298 Maximum serial number
299 max_count - [in]
300 If max_count > 0, this parameter specifies the
301 maximum number of elements to append.
302 elements - [out]
303 Elements are appended to this array
304 Returns:
305 Number of elements appended to elements[] array.
306 Remarks:
307 When many elements are returned, GetElements() can be
308 substantially faster than repeated calls to FindElement().
309 */
310 size_t GetElements(
311 unsigned int sn0,
312 unsigned int sn1,
313 size_t max_count,
315 ) const;
316
317 /*
318 Description:
319 Empties the list.
320 */
321 void EmptyList();
322
323 /*
324 Description:
325 Returns true if the map is valid. Returns false if the
326 map is not valid. If an error is found and textlog
327 is not null, then a description of the problem is sent
328 to textlog.
329 Returns:
330 true if the list if valid.
331 */
332 bool IsValid(ON_TextLog* textlog) const;
333
334private:
335 // prohibit copy construction and operator=
336 // no implementation
339
340 enum
341 {
342 // These numbers are chosen so the ON_SerialNumberMap
343 // will be computationally efficient for up to
344 // 10 million entries.
345 SN_BLOCK_CAPACITY = 8192,
346 SN_PURGE_RATIO = 16,
347 ID_HASH_TABLE_COUNT = 8192
348 };
349
350 struct SN_BLOCK
351 {
352 size_t m_count; // used elements in m_sn[]
353 size_t m_purged; // number of purged elements in m_sn[]
354 unsigned int m_sorted; // 0 = no, 1 = yes
355 unsigned int m_sn0; // minimum sn in m_sn[]
356 unsigned int m_sn1; // maximum sn in m_sn[]
357 struct SN_ELEMENT m_sn[SN_BLOCK_CAPACITY];
358 void EmptyBlock();
359 void CullBlockHelper();
360 void SortBlockHelper();
361 bool IsValidBlock(ON_TextLog* textlog,struct SN_ELEMENT*const* hash_table,size_t* active_id_count) const;
362 struct SN_ELEMENT* BinarySearchBlockHelper(unsigned int sn);
363 static int CompareMaxSN(const void*,const void*);
364 size_t ActiveElementEstimate(unsigned int sn0, unsigned int sn1) const;
365 };
366
367 unsigned int m_maxsn; // largest sn stored anywhere
368 unsigned int m_reserved;
369
370 // All heap used in this class is allocated from this pool.
372
373 // Serial Number list counts
374 size_t m_sn_count; // total number of elements
375 size_t m_sn_purged; // total number of purged elements
376
377 // ID hash table counts (all ids in the hash table are active)
378 bool m_bHashTableIsValid; // true if m_hash_table[] is valid
379 size_t m_active_id_count; // number of active ids in the hash table
380 ON_UUID m_inactive_id; // frequently and id is removed and
381 // then added back. m_inactive_id
382 // records the most recently removed
383 // id so we don't have to waste time
384 // searching the hash table for
385 // an id that is not there.
386
387
388 // The blocks in m_sn_list[] are alwasy sorted, disjoint,
389 // and in increasing order. m_sn_list is used when
390 // m_sn_block0.m_sn[] is not large enough.
391 // The sn list is partitioned into blocks to avoid
392 // requiring large amounts of contiguous memory for
393 // situations with millions of serial numbers.
395 size_t m_snblk_list_capacity; // capacity of m_blk_list[]
396 size_t m_snblk_list_count; // used elements in m_snblk_list[]
397
398 // If FindElementHelper() returns a non-null pointer
399 // to an element, then m_e_blk points to the SN_BLOCK
400 // that contains the returned element. In all other
401 // situations the value in m_e_blk is undefined and
402 // m_e_blk must not be dereferenced.
404
405 // m_sn_block0 is where the new additions are added.
406 // When serial numbers are not added in increasing
407 // order, m_sn_block0.m_sn[] may not be sorted.
409
410 struct SN_ELEMENT* FindElementHelper(unsigned int sn);
411 void UpdateMaxSNHelper();
412 void GarbageCollectHelper();
413 size_t GarbageCollectMoveHelper(SN_BLOCK* dst,SN_BLOCK* src);
414
415 // When m_bHashTableIsValid is true, then m_hash_table[i] is
416 // a linked list of elements whose id satisfies
417 // i = HashIndex(&e->m_id). When m_bHashTableIsValid is false,
418 // m_hash_table[] is identically zero.
419 struct SN_ELEMENT* m_hash_table[ID_HASH_TABLE_COUNT];
420 size_t HashIndex(const ON_UUID*) const;
421 void InvalidateHashTableHelper(); // marks table as dirty
422 bool RemoveBlockFromHashTableHelper(const struct SN_BLOCK* blk);
423 void AddBlockToHashTableHelper(struct SN_BLOCK* blk);
424 void BuildHashTableHelper(); // prepares table for use
425};
426
427
428#endif
Definition opennurbs_lookup.h:33
ON_MEMORY_POOL * m_pool
Definition opennurbs_lookup.h:371
unsigned int m_maxsn
Definition opennurbs_lookup.h:367
size_t m_snblk_list_capacity
Definition opennurbs_lookup.h:395
size_t m_active_id_count
Definition opennurbs_lookup.h:379
ON_SerialNumberMap(const ON_SerialNumberMap &)
SN_BLOCK m_sn_block0
Definition opennurbs_lookup.h:408
ON_SerialNumberMap & operator=(const ON_SerialNumberMap &)
size_t m_sn_count
Definition opennurbs_lookup.h:374
struct SN_BLOCK ** m_snblk_list
Definition opennurbs_lookup.h:394
size_t m_snblk_list_count
Definition opennurbs_lookup.h:396
struct SN_BLOCK * m_e_blk
Definition opennurbs_lookup.h:403
size_t m_sn_purged
Definition opennurbs_lookup.h:375
unsigned int m_reserved
Definition opennurbs_lookup.h:368
ON_UUID m_inactive_id
Definition opennurbs_lookup.h:380
bool m_bHashTableIsValid
Definition opennurbs_lookup.h:378
Definition opennurbs_array.h:46
Definition opennurbs_textlog.h:20
Definition opennurbs_uuid.h:31
#define ON_CLASS
Definition opennurbs_defines.h:91
unsigned int ON__UINT32
Definition opennurbs_system.h:326
Definition opennurbs_lookup.h:39
void * ptr
Definition opennurbs_lookup.h:43
int i
Definition opennurbs_lookup.h:45
unsigned int ui
Definition opennurbs_lookup.h:44
ON__UINT32 m_u_type
Definition opennurbs_lookup.h:40
Definition opennurbs_lookup.h:351
size_t m_count
Definition opennurbs_lookup.h:352
unsigned int m_sorted
Definition opennurbs_lookup.h:354
unsigned int m_sn0
Definition opennurbs_lookup.h:355
size_t m_purged
Definition opennurbs_lookup.h:353
unsigned int m_sn1
Definition opennurbs_lookup.h:356
Definition opennurbs_lookup.h:50
ON_UUID m_id
Definition opennurbs_lookup.h:55
unsigned int m_sn
Definition opennurbs_lookup.h:62
unsigned char m_sn_active
Definition opennurbs_lookup.h:71
unsigned char m_reserved1
Definition opennurbs_lookup.h:73
unsigned char m_id_active
Definition opennurbs_lookup.h:72
struct SN_ELEMENT * m_next
Definition opennurbs_lookup.h:56
unsigned char m_reserved2
Definition opennurbs_lookup.h:74
Definition opennurbs_memory.h:207