GitHub Actions: Try MSVC builds with /std:c++17 and 20
[ACE_TAO.git] / ACE / ace / Map_Manager.cpp
blobecb34ab503bf8c9cac749084935c8a525403d010
1 #ifndef ACE_MAP_MANAGER_CPP
2 #define ACE_MAP_MANAGER_CPP
4 #include "ace/Map_Manager.h"
6 #if !defined (ACE_LACKS_PRAGMA_ONCE)
7 # pragma once
8 #endif /* ACE_LACKS_PRAGMA_ONCE */
10 #include "ace/Malloc_Base.h"
12 #if !defined (__ACE_INLINE__)
13 #include "ace/Map_Manager.inl"
14 #endif /* __ACE_INLINE__ */
16 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
18 ACE_ALLOC_HOOK_DEFINE_Tcc(ACE_Map_Entry)
19 ACE_ALLOC_HOOK_DEFINE_Tccc(ACE_Map_Manager)
20 ACE_ALLOC_HOOK_DEFINE_Tccc(ACE_Map_Const_Iterator_Base)
21 ACE_ALLOC_HOOK_DEFINE_Tccc(ACE_Map_Iterator_Base)
22 ACE_ALLOC_HOOK_DEFINE_Tccc(ACE_Map_Const_Iterator)
23 ACE_ALLOC_HOOK_DEFINE_Tccc(ACE_Map_Iterator)
24 ACE_ALLOC_HOOK_DEFINE_Tccc(ACE_Map_Reverse_Iterator)
26 template <class EXT_ID, class INT_ID, class ACE_LOCK> int
27 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::open (size_t size,
28 ACE_Allocator *alloc)
30 ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
32 // Close old map (if any).
33 this->close_i ();
35 // Use the user specified allocator or the default singleton one.
36 if (alloc == 0)
37 alloc = ACE_Allocator::instance ();
39 this->allocator_ = alloc;
41 // This assertion is here to help track a situation that shouldn't
42 // happen.
43 ACE_ASSERT (size != 0);
45 // Active_Map_Manager depends on the <slot_index_> being of fixed
46 // size. It cannot be size_t because size_t is 64-bits on 64-bit
47 // platform and 32-bits on 32-bit platforms. Size of the <slot_index_>
48 // has to be consistent across platforms. ACE_UIN32 is chosen as
49 // ACE_UIN32_MAX is big enough. The assert is to ensure that the user
50 // doesn't open the ACE_Map_Manager with a bigger size than we can
51 // handle.
52 ACE_ASSERT (size <= ACE_UINT32_MAX);
54 // Resize from 0 to <size>. Note that this will also set up the
55 // circular free list.
56 return this->resize_i ((ACE_UINT32) size);
59 template <class EXT_ID, class INT_ID, class ACE_LOCK> int
60 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::close_i (void)
62 // Free entries.
63 this->free_search_structure ();
65 // Reset sizes.
66 this->total_size_ = 0;
67 this->cur_size_ = 0;
69 // Reset circular free list.
70 this->free_list_.next (this->free_list_id ());
71 this->free_list_.prev (this->free_list_id ());
73 // Reset circular occupied list.
74 this->occupied_list_.next (this->occupied_list_id ());
75 this->occupied_list_.prev (this->occupied_list_id ());
77 return 0;
80 template <class EXT_ID, class INT_ID, class ACE_LOCK> int
81 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::bind_i (const EXT_ID &ext_id,
82 const INT_ID &int_id)
84 // Try to find the key.
85 ACE_UINT32 slot = 0;
86 int result = this->find_and_return_index (ext_id,
87 slot);
89 if (result == 0)
90 // We found the key. Nothing to change.
91 return 1;
92 else
93 // We didn't find the key.
94 return this->shared_bind (ext_id,
95 int_id);
98 template <class EXT_ID, class INT_ID, class ACE_LOCK> int
99 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::next_free (ACE_UINT32 &free_slot)
101 // Look in the free list for an empty slot.
102 free_slot = this->free_list_.next ();
104 // If we do find a free slot, return successfully.
105 if (free_slot != this->free_list_id ())
106 return 0;
108 #if defined (ACE_HAS_LAZY_MAP_MANAGER)
110 // Move any free slots from occupied list to free list.
111 this->move_all_free_slots_from_occupied_list ();
113 // Try again in case we found any free slots in the occupied list.
114 free_slot = this->free_list_.next ();
116 // If we do find a free slot, return successfully.
117 if (free_slot != this->free_list_id ())
118 return 0;
120 #endif /* ACE_HAS_LAZY_MAP_MANAGER */
122 // Resize the map.
123 int result = this->resize_i (this->new_size ());
125 // Check for errors.
126 if (result == 0)
127 // New free slot.
128 free_slot = this->free_list_.next ();
130 return result;
133 #if defined (ACE_HAS_LAZY_MAP_MANAGER)
135 template <class EXT_ID, class INT_ID, class ACE_LOCK> void
136 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::move_all_free_slots_from_occupied_list (void)
139 // In the case of lazy map managers, the movement of free slots from
140 // the occupied list to the free list is delayed until we run out of
141 // free slots in the free list.
144 // Go through the entire occupied list, moving free slots to the
145 // free list. Note that all free slots in the occupied list are
146 // moved in this loop.
147 for (ACE_UINT32 i = this->occupied_list_.next ();
148 i != this->occupied_list_id ();
152 // Note the trick used here: Information about the current slot
153 // is first noted; <i> then moves to the next occupied slot;
154 // only after this is the slot (potentially) moved from the
155 // occupied list to the free list. This order of things, i.e.,
156 // moving <i> before moving the free slot is necessary,
157 // otherwise we'll forget which our next occupied slot is.
160 // Note information about current slot.
161 ACE_Map_Entry<EXT_ID, INT_ID> &current_slot = this->search_structure_[i];
162 ACE_UINT32 position_of_current_slot = i;
164 // Move <i> to next occupied slot.
165 i = this->search_structure_[i].next ();
167 // If current slot is free
168 if (current_slot.free_)
170 // Reset free flag to zero before moving to free list.
171 current_slot.free_ = false;
173 // Move from occupied list to free list.
174 this->move_from_occupied_list_to_free_list (position_of_current_slot);
179 #endif /* ACE_HAS_LAZY_MAP_MANAGER */
181 template <class EXT_ID, class INT_ID, class ACE_LOCK> void
182 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::shared_move (ACE_UINT32 slot,
183 ACE_Map_Entry<EXT_ID, INT_ID> &current_list,
184 ACE_UINT32 current_list_id,
185 ACE_Map_Entry<EXT_ID, INT_ID> &new_list,
186 ACE_UINT32 new_list_id)
188 // Grab the entry.
189 ENTRY &entry = this->search_structure_[slot];
191 // Remove from current list.
193 // Fix the entry before us.
194 ACE_UINT32 current_list_prev = entry.prev ();
196 if (current_list_prev == current_list_id)
197 current_list.next (entry.next ());
198 else
199 this->search_structure_[current_list_prev].next (entry.next ());
201 // Fix the entry after us.
202 ACE_UINT32 current_list_next = entry.next ();
204 if (current_list_next == current_list_id)
205 current_list.prev (entry.prev ());
206 else
207 this->search_structure_[current_list_next].prev (entry.prev ());
209 // Add to new list.
211 // Fix us.
212 ACE_UINT32 new_list_next = new_list.next ();
213 entry.next (new_list_next);
214 entry.prev (new_list_id);
216 // Fix entry before us.
217 new_list.next (slot);
219 // Fix entry after us.
220 if (new_list_next == new_list_id)
221 new_list.prev (slot);
222 else
223 this->search_structure_[new_list_next].prev (slot);
226 template <class EXT_ID, class INT_ID, class ACE_LOCK> int
227 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::shared_bind (const EXT_ID &ext_id,
228 const INT_ID &int_id)
230 // This function assumes that the find() has already been done, and
231 // therefore, simply adds to the map.
233 // Find an empty slot.
234 ACE_UINT32 slot = 0;
235 int result = this->next_free (slot);
237 if (result == 0)
239 // Copy key and value.
240 this->search_structure_[slot].int_id_ = int_id;
241 this->search_structure_[slot].ext_id_ = ext_id;
243 // Move from free list to occupied list
244 this->move_from_free_list_to_occupied_list (slot);
246 // Update the current size.
247 ++this->cur_size_;
250 return result;
253 template <class EXT_ID, class INT_ID, class ACE_LOCK> int
254 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::rebind_i (const EXT_ID &ext_id,
255 const INT_ID &int_id,
256 EXT_ID &old_ext_id,
257 INT_ID &old_int_id)
259 // First try to find the key.
260 ACE_UINT32 slot = 0;
261 int result = this->find_and_return_index (ext_id,
262 slot);
263 if (result == 0)
265 // We found it, so make copies of the old entries and rebind
266 // current entries.
267 ENTRY &ss = this->search_structure_[slot];
268 old_ext_id = ss.ext_id_;
269 old_int_id = ss.int_id_;
270 ss.ext_id_ = ext_id;
271 ss.int_id_ = int_id;
273 // Sync changed entry.
274 this->allocator_->sync (&ss, sizeof ss);
276 return 1;
278 else
279 // We didn't find it, so let's add it.
280 return this->shared_bind (ext_id,
281 int_id);
284 template <class EXT_ID, class INT_ID, class ACE_LOCK> int
285 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::rebind_i (const EXT_ID &ext_id,
286 const INT_ID &int_id,
287 INT_ID &old_int_id)
289 // First try to find the key.
290 ACE_UINT32 slot = 0;
291 int result = this->find_and_return_index (ext_id,
292 slot);
293 if (result == 0)
295 // We found it, so make copies of the old entries and rebind
296 // current entries.
297 ENTRY &ss = this->search_structure_[slot];
298 old_int_id = ss.int_id_;
299 ss.ext_id_ = ext_id;
300 ss.int_id_ = int_id;
302 // Sync changed entry.
303 this->allocator_->sync (&ss, sizeof ss);
305 return 1;
307 else
308 // We didn't find it, so let's add it.
309 return this->shared_bind (ext_id,
310 int_id);
313 template <class EXT_ID, class INT_ID, class ACE_LOCK> int
314 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::rebind_i (const EXT_ID &ext_id,
315 const INT_ID &int_id)
317 // First try to find the key.
318 ACE_UINT32 slot = 0;
319 int result = this->find_and_return_index (ext_id,
320 slot);
321 if (result == 0)
323 // We found it, so rebind current entries.
324 ENTRY &ss = this->search_structure_[slot];
325 ss.ext_id_ = ext_id;
326 ss.int_id_ = int_id;
328 // Sync changed entry.
329 this->allocator_->sync (&ss, sizeof ss);
331 return 1;
333 else
334 // We didn't find it, so let's add it.
335 return this->shared_bind (ext_id,
336 int_id);
339 template <class EXT_ID, class INT_ID, class ACE_LOCK> int
340 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::trybind_i (const EXT_ID &ext_id,
341 INT_ID &int_id)
343 // Try to find the key.
344 ACE_UINT32 slot = 0;
345 int result = this->find_and_return_index (ext_id,
346 slot);
347 if (result == 0)
349 // Key was found. Make a copy of value, but *don't* update
350 // anything in the map!
351 int_id = this->search_structure_[slot].int_id_;
352 return 1;
354 else
355 // We didn't find it, so let's bind it!
356 return this->bind_i (ext_id,
357 int_id);
360 template <class EXT_ID, class INT_ID, class ACE_LOCK> int
361 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::find_and_return_index (const EXT_ID &ext_id,
362 ACE_UINT32 &slot)
364 // Go through the entire occupied list looking for the key.
365 for (ACE_UINT32 i = this->occupied_list_.next ();
366 i != this->occupied_list_id ();
367 i = this->search_structure_[i].next ())
369 #if defined (ACE_HAS_LAZY_MAP_MANAGER)
370 if (this->search_structure_[i].free_)
371 continue;
372 #endif /* ACE_HAS_LAZY_MAP_MANAGER */
374 if (this->equal (this->search_structure_[i].ext_id_,
375 ext_id))
377 // If found, return slot.
378 slot = i;
379 return 0;
383 // Key was not found.
384 return -1;
387 template <class EXT_ID, class INT_ID, class ACE_LOCK> void
388 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::unbind_all (void)
390 // Go through the entire occupied list.
391 for (ACE_UINT32 i = this->occupied_list_.next ();
392 i != this->occupied_list_id ();
396 // Note the trick used here: Information about the current slot
397 // is first noted; <i> then moves to the next occupied slot;
398 // only after this is the slot (potentially) moved from the
399 // occupied list to the free list. This order of things, i.e.,
400 // moving <i> before moving the free slot is necessary,
401 // otherwise we'll forget which our next occupied slot is.
404 // Note information about current slot.
405 ACE_Map_Entry<EXT_ID, INT_ID> &current_slot =
406 this->search_structure_[i];
407 ACE_UINT32 position_of_current_slot = i;
409 // Move <i> to next occupied slot.
410 i = current_slot.next ();
412 #if defined (ACE_HAS_LAZY_MAP_MANAGER)
413 if (current_slot.free_)
414 continue;
415 #endif /* ACE_HAS_LAZY_MAP_MANAGER */
417 this->unbind_slot (position_of_current_slot);
421 template <class EXT_ID, class INT_ID, class ACE_LOCK> int
422 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::find_i (const EXT_ID &ext_id,
423 INT_ID &int_id)
425 // Try to find the key.
426 ACE_UINT32 slot = 0;
427 int result = this->find_and_return_index (ext_id,
428 slot);
429 if (result == 0)
430 // Key was found. Make a copy of value.
431 int_id = this->search_structure_[slot].int_id_;
433 return result;
436 template <class EXT_ID, class INT_ID, class ACE_LOCK> int
437 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::unbind_and_return_index (const EXT_ID &ext_id,
438 ACE_UINT32 &slot)
440 // Try to find the key.
441 int result = this->find_and_return_index (ext_id,
442 slot);
444 if (result == 0)
445 this->unbind_slot (slot);
447 return result;
450 template <class EXT_ID, class INT_ID, class ACE_LOCK> void
451 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::unbind_slot (ACE_UINT32 slot)
454 #if defined (ACE_HAS_LAZY_MAP_MANAGER)
457 // In the case of lazy map managers, the movement of free slots
458 // from the occupied list to the free list is delayed until we
459 // run out of free slots in the free list.
462 this->search_structure_[slot].free_ = true;
464 #else
466 // Move from occupied list to free list.
467 this->move_from_occupied_list_to_free_list (slot);
469 #endif /* ACE_HAS_LAZY_MAP_MANAGER */
471 // Update the current size.
472 --this->cur_size_;
475 template <class EXT_ID, class INT_ID, class ACE_LOCK> int
476 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::unbind_i (const EXT_ID &ext_id,
477 INT_ID &int_id)
479 // Unbind the entry.
480 ACE_UINT32 slot = 0;
481 int result = this->unbind_and_return_index (ext_id,
482 slot);
483 if (result == 0)
484 // If found, copy the value.
485 int_id = this->search_structure_[slot].int_id_;
487 return result;
490 template <class EXT_ID, class INT_ID, class ACE_LOCK> int
491 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::resize_i (ACE_UINT32 new_size)
493 ACE_UINT32 i;
494 ENTRY *temp = 0;
496 // Allocate new memory.
497 ACE_ALLOCATOR_RETURN (temp,
498 (ENTRY *) this->allocator_->malloc (new_size * sizeof (ENTRY)),
499 -1);
501 // Copy over the occupied entires.
502 for (i = this->occupied_list_.next ();
503 i != this->occupied_list_id ();
504 i = this->search_structure_[i].next ())
505 // Call the copy constructor using operator placement new.
506 new (&(temp[i])) ENTRY (this->search_structure_[i]);
508 // Copy over the free entires.
509 for (i = this->free_list_.next ();
510 i != this->free_list_id ();
511 i = this->search_structure_[i].next ())
512 // Call the copy constructor using operator placement new.
513 new (&(temp[i])) ENTRY (this->search_structure_[i]);
515 // Construct the new elements.
516 for (i = this->total_size_; i < new_size; i++)
518 // Call the constructor for each element in the array using
519 // operator placement new. Note that this requires a default
520 // constructor for <EXT_ID> and <INT_ID>.
521 new (&(temp[i])) ENTRY;
522 temp[i].next (i + 1);
523 temp[i].prev (i - 1);
525 #if defined (ACE_HAS_LAZY_MAP_MANAGER)
527 // Even though this slot is initially free, we need the <free_>
528 // flag to be zero so that we don't have to set it when the slot
529 // is moved to the occupied list. In addition, this flag has no
530 // meaning while this slot is in the free list.
531 temp[i].free_ = false;
533 #endif /* ACE_HAS_LAZY_MAP_MANAGER */
537 // Add new entries to the free list.
538 this->free_list_.next (this->total_size_);
539 this->free_list_.prev (new_size - 1);
540 temp[new_size - 1].next (this->free_list_id ());
541 temp[this->total_size_].prev (this->free_list_id ());
543 // Remove/free old elements, update the new totoal size.
544 this->free_search_structure ();
545 this->total_size_ = new_size;
547 // Start using new elements.
548 this->search_structure_ = temp;
550 return 0;
553 template <class EXT_ID, class INT_ID, class ACE_LOCK> ACE_UINT32
554 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::new_size (void)
556 // Calculate the new size.
557 ACE_UINT32 current_size = this->total_size_;
559 if (current_size < MAX_EXPONENTIAL)
560 // Exponentially increase if we haven't reached MAX_EXPONENTIAL.
561 current_size *= 2;
562 else
563 // Linear increase if we have reached MAX_EXPONENTIAL.
564 current_size += LINEAR_INCREASE;
566 // This should be the new size.
567 return current_size;
570 template <class EXT_ID, class INT_ID, class ACE_LOCK> void
571 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::free_search_structure (void)
573 // Free up the structure.
574 if (this->search_structure_ != 0)
576 for (ACE_UINT32 i = 0; i < this->total_size_; i++)
577 // Explicitly call the destructor.
579 ENTRY *ss = &this->search_structure_[i];
580 // The "if" second argument results in a no-op instead of
581 // deallocation.
582 ACE_DES_FREE_TEMPLATE2 (ss, ACE_NOOP,
583 ACE_Map_Entry, EXT_ID, INT_ID);
586 // Actually free the memory.
587 this->allocator_->free (this->search_structure_);
588 this->search_structure_ = 0;
592 template <class EXT_ID, class INT_ID> void
593 ACE_Map_Entry<EXT_ID, INT_ID>::dump (void) const
595 #if defined (ACE_HAS_DUMP)
596 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
597 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("next_ = %d"), this->next_));
598 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("prev_ = %d"), this->prev_));
600 #if defined (ACE_HAS_LAZY_MAP_MANAGER)
601 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("free_ = %d"), this->free_));
602 #endif /* ACE_HAS_LAZY_MAP_MANAGER */
604 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
605 #endif /* ACE_HAS_DUMP */
608 template <class EXT_ID, class INT_ID, class ACE_LOCK> void
609 ACE_Map_Manager<EXT_ID, INT_ID, ACE_LOCK>::dump (void) const
611 #if defined (ACE_HAS_DUMP)
612 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
613 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("total_size_ = %d"), this->total_size_));
614 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\ncur_size_ = %d"), this->cur_size_));
615 this->allocator_->dump ();
616 this->lock_.dump ();
617 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
618 #endif /* ACE_HAS_DUMP */
621 template <class EXT_ID, class INT_ID, class ACE_LOCK> void
622 ACE_Map_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::dump_i (void) const
624 #if defined (ACE_HAS_DUMP)
625 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
626 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("next_ = %d"), this->next_));
627 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
628 #endif /* ACE_HAS_DUMP */
631 template <class EXT_ID, class INT_ID, class ACE_LOCK> void
632 ACE_Map_Const_Iterator_Base<EXT_ID, INT_ID, ACE_LOCK>::dump_i (void) const
634 #if defined (ACE_HAS_DUMP)
635 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
636 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("next_ = %d"), this->next_));
637 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
638 #endif /* ACE_HAS_DUMP */
641 template <class EXT_ID, class INT_ID, class ACE_LOCK> void
642 ACE_Map_Iterator<EXT_ID, INT_ID, ACE_LOCK>::dump (void) const
644 #if defined (ACE_HAS_DUMP)
645 this->dump_i ();
646 #endif /* ACE_HAS_DUMP */
649 template <class EXT_ID, class INT_ID, class ACE_LOCK> void
650 ACE_Map_Const_Iterator<EXT_ID, INT_ID, ACE_LOCK>::dump (void) const
652 #if defined (ACE_HAS_DUMP)
653 this->dump_i ();
654 #endif /* ACE_HAS_DUMP */
657 template <class EXT_ID, class INT_ID, class ACE_LOCK> void
658 ACE_Map_Reverse_Iterator<EXT_ID, INT_ID, ACE_LOCK>::dump (void) const
660 #if defined (ACE_HAS_DUMP)
661 this->dump_i ();
662 #endif /* ACE_HAS_DUMP */
665 ACE_END_VERSIONED_NAMESPACE_DECL
667 #endif /* ACE_MAP_MANAGER_CPP */