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)
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
,
30 ACE_WRITE_GUARD_RETURN (ACE_LOCK
, ace_mon
, this->lock_
, -1);
32 // Close old map (if any).
35 // Use the user specified allocator or the default singleton one.
37 alloc
= ACE_Allocator::instance ();
39 this->allocator_
= alloc
;
41 // This assertion is here to help track a situation that shouldn't
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
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)
63 this->free_search_structure ();
66 this->total_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 ());
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
,
84 // Try to find the key.
86 int result
= this->find_and_return_index (ext_id
,
90 // We found the key. Nothing to change.
93 // We didn't find the key.
94 return this->shared_bind (ext_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 ())
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 ())
120 #endif /* ACE_HAS_LAZY_MAP_MANAGER */
123 int result
= this->resize_i (this->new_size ());
128 free_slot
= this->free_list_
.next ();
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
> ¤t_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
> ¤t_list
,
184 ACE_UINT32 current_list_id
,
185 ACE_Map_Entry
<EXT_ID
, INT_ID
> &new_list
,
186 ACE_UINT32 new_list_id
)
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 ());
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 ());
207 this->search_structure_
[current_list_next
].prev (entry
.prev ());
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
);
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.
235 int result
= this->next_free (slot
);
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.
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
,
259 // First try to find the key.
261 int result
= this->find_and_return_index (ext_id
,
265 // We found it, so make copies of the old entries and rebind
267 ENTRY
&ss
= this->search_structure_
[slot
];
268 old_ext_id
= ss
.ext_id_
;
269 old_int_id
= ss
.int_id_
;
273 // Sync changed entry.
274 this->allocator_
->sync (&ss
, sizeof ss
);
279 // We didn't find it, so let's add it.
280 return this->shared_bind (ext_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
,
289 // First try to find the key.
291 int result
= this->find_and_return_index (ext_id
,
295 // We found it, so make copies of the old entries and rebind
297 ENTRY
&ss
= this->search_structure_
[slot
];
298 old_int_id
= ss
.int_id_
;
302 // Sync changed entry.
303 this->allocator_
->sync (&ss
, sizeof ss
);
308 // We didn't find it, so let's add it.
309 return this->shared_bind (ext_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.
319 int result
= this->find_and_return_index (ext_id
,
323 // We found it, so rebind current entries.
324 ENTRY
&ss
= this->search_structure_
[slot
];
328 // Sync changed entry.
329 this->allocator_
->sync (&ss
, sizeof ss
);
334 // We didn't find it, so let's add it.
335 return this->shared_bind (ext_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
,
343 // Try to find the key.
345 int result
= this->find_and_return_index (ext_id
,
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_
;
355 // We didn't find it, so let's bind it!
356 return this->bind_i (ext_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
,
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_
)
372 #endif /* ACE_HAS_LAZY_MAP_MANAGER */
374 if (this->equal (this->search_structure_
[i
].ext_id_
,
377 // If found, return slot.
383 // Key was not found.
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
> ¤t_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_
)
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
,
425 // Try to find the key.
427 int result
= this->find_and_return_index (ext_id
,
430 // Key was found. Make a copy of value.
431 int_id
= this->search_structure_
[slot
].int_id_
;
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
,
440 // Try to find the key.
441 int result
= this->find_and_return_index (ext_id
,
445 this->unbind_slot (slot
);
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;
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.
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
,
481 int result
= this->unbind_and_return_index (ext_id
,
484 // If found, copy the value.
485 int_id
= this->search_structure_
[slot
].int_id_
;
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
)
496 // Allocate new memory.
497 ACE_ALLOCATOR_RETURN (temp
,
498 (ENTRY
*) this->allocator_
->malloc (new_size
* sizeof (ENTRY
)),
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
;
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.
563 // Linear increase if we have reached MAX_EXPONENTIAL.
564 current_size
+= LINEAR_INCREASE
;
566 // This should be the new 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
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 ();
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)
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)
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)
662 #endif /* ACE_HAS_DUMP */
665 ACE_END_VERSIONED_NAMESPACE_DECL
667 #endif /* ACE_MAP_MANAGER_CPP */