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 ()
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 ()
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 ()
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
)
453 #if defined (ACE_HAS_LAZY_MAP_MANAGER)
456 // In the case of lazy map managers, the movement of free slots
457 // from the occupied list to the free list is delayed until we
458 // run out of free slots in the free list.
461 this->search_structure_
[slot
].free_
= true;
465 // Move from occupied list to free list.
466 this->move_from_occupied_list_to_free_list (slot
);
468 #endif /* ACE_HAS_LAZY_MAP_MANAGER */
470 // Update the current size.
474 template <class EXT_ID
, class INT_ID
, class ACE_LOCK
> int
475 ACE_Map_Manager
<EXT_ID
, INT_ID
, ACE_LOCK
>::unbind_i (const EXT_ID
&ext_id
,
480 int result
= this->unbind_and_return_index (ext_id
,
483 // If found, copy the value.
484 int_id
= this->search_structure_
[slot
].int_id_
;
489 template <class EXT_ID
, class INT_ID
, class ACE_LOCK
> int
490 ACE_Map_Manager
<EXT_ID
, INT_ID
, ACE_LOCK
>::resize_i (ACE_UINT32 new_size
)
495 // Allocate new memory.
496 ACE_ALLOCATOR_RETURN (temp
,
497 (ENTRY
*) this->allocator_
->malloc (new_size
* sizeof (ENTRY
)),
500 // Copy over the occupied entires.
501 for (i
= this->occupied_list_
.next ();
502 i
!= this->occupied_list_id ();
503 i
= this->search_structure_
[i
].next ())
504 // Call the copy constructor using operator placement new.
505 new (&(temp
[i
])) ENTRY (this->search_structure_
[i
]);
507 // Copy over the free entires.
508 for (i
= this->free_list_
.next ();
509 i
!= this->free_list_id ();
510 i
= this->search_structure_
[i
].next ())
511 // Call the copy constructor using operator placement new.
512 new (&(temp
[i
])) ENTRY (this->search_structure_
[i
]);
514 // Construct the new elements.
515 for (i
= this->total_size_
; i
< new_size
; i
++)
517 // Call the constructor for each element in the array using
518 // operator placement new. Note that this requires a default
519 // constructor for <EXT_ID> and <INT_ID>.
520 new (&(temp
[i
])) ENTRY
;
521 temp
[i
].next (i
+ 1);
522 temp
[i
].prev (i
- 1);
524 #if defined (ACE_HAS_LAZY_MAP_MANAGER)
526 // Even though this slot is initially free, we need the <free_>
527 // flag to be zero so that we don't have to set it when the slot
528 // is moved to the occupied list. In addition, this flag has no
529 // meaning while this slot is in the free list.
530 temp
[i
].free_
= false;
532 #endif /* ACE_HAS_LAZY_MAP_MANAGER */
536 // Add new entries to the free list.
537 this->free_list_
.next (this->total_size_
);
538 this->free_list_
.prev (new_size
- 1);
539 temp
[new_size
- 1].next (this->free_list_id ());
540 temp
[this->total_size_
].prev (this->free_list_id ());
542 // Remove/free old elements, update the new totoal size.
543 this->free_search_structure ();
544 this->total_size_
= new_size
;
546 // Start using new elements.
547 this->search_structure_
= temp
;
552 template <class EXT_ID
, class INT_ID
, class ACE_LOCK
> ACE_UINT32
553 ACE_Map_Manager
<EXT_ID
, INT_ID
, ACE_LOCK
>::new_size ()
555 // Calculate the new size.
556 ACE_UINT32 current_size
= this->total_size_
;
558 if (current_size
< MAX_EXPONENTIAL
)
559 // Exponentially increase if we haven't reached MAX_EXPONENTIAL.
562 // Linear increase if we have reached MAX_EXPONENTIAL.
563 current_size
+= LINEAR_INCREASE
;
565 // This should be the new size.
569 template <class EXT_ID
, class INT_ID
, class ACE_LOCK
> void
570 ACE_Map_Manager
<EXT_ID
, INT_ID
, ACE_LOCK
>::free_search_structure ()
572 // Free up the structure.
573 if (this->search_structure_
!= 0)
575 for (ACE_UINT32 i
= 0; i
< this->total_size_
; i
++)
576 // Explicitly call the destructor.
578 ENTRY
*ss
= &this->search_structure_
[i
];
579 // The "if" second argument results in a no-op instead of
581 ACE_DES_FREE_TEMPLATE2 (ss
, ACE_NOOP
,
582 ACE_Map_Entry
, EXT_ID
, INT_ID
);
585 // Actually free the memory.
586 this->allocator_
->free (this->search_structure_
);
587 this->search_structure_
= 0;
591 template <class EXT_ID
, class INT_ID
> void
592 ACE_Map_Entry
<EXT_ID
, INT_ID
>::dump () const
594 #if defined (ACE_HAS_DUMP)
595 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
596 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("next_ = %d"), this->next_
));
597 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("prev_ = %d"), this->prev_
));
599 #if defined (ACE_HAS_LAZY_MAP_MANAGER)
600 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("free_ = %d"), this->free_
));
601 #endif /* ACE_HAS_LAZY_MAP_MANAGER */
603 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
604 #endif /* ACE_HAS_DUMP */
607 template <class EXT_ID
, class INT_ID
, class ACE_LOCK
> void
608 ACE_Map_Manager
<EXT_ID
, INT_ID
, ACE_LOCK
>::dump () const
610 #if defined (ACE_HAS_DUMP)
611 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
612 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("total_size_ = %d"), this->total_size_
));
613 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("\ncur_size_ = %d"), this->cur_size_
));
614 this->allocator_
->dump ();
616 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
617 #endif /* ACE_HAS_DUMP */
620 template <class EXT_ID
, class INT_ID
, class ACE_LOCK
> void
621 ACE_Map_Iterator_Base
<EXT_ID
, INT_ID
, ACE_LOCK
>::dump_i () const
623 #if defined (ACE_HAS_DUMP)
624 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
625 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("next_ = %d"), this->next_
));
626 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
627 #endif /* ACE_HAS_DUMP */
630 template <class EXT_ID
, class INT_ID
, class ACE_LOCK
> void
631 ACE_Map_Const_Iterator_Base
<EXT_ID
, INT_ID
, ACE_LOCK
>::dump_i () const
633 #if defined (ACE_HAS_DUMP)
634 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
635 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("next_ = %d"), this->next_
));
636 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
637 #endif /* ACE_HAS_DUMP */
640 template <class EXT_ID
, class INT_ID
, class ACE_LOCK
> void
641 ACE_Map_Iterator
<EXT_ID
, INT_ID
, ACE_LOCK
>::dump () const
643 #if defined (ACE_HAS_DUMP)
645 #endif /* ACE_HAS_DUMP */
648 template <class EXT_ID
, class INT_ID
, class ACE_LOCK
> void
649 ACE_Map_Const_Iterator
<EXT_ID
, INT_ID
, ACE_LOCK
>::dump () const
651 #if defined (ACE_HAS_DUMP)
653 #endif /* ACE_HAS_DUMP */
656 template <class EXT_ID
, class INT_ID
, class ACE_LOCK
> void
657 ACE_Map_Reverse_Iterator
<EXT_ID
, INT_ID
, ACE_LOCK
>::dump () const
659 #if defined (ACE_HAS_DUMP)
661 #endif /* ACE_HAS_DUMP */
664 ACE_END_VERSIONED_NAMESPACE_DECL
666 #endif /* ACE_MAP_MANAGER_CPP */