2 //=============================================================================
4 * @file Hash_Map_Manager_T.cpp
6 * @author Douglas C. Schmidt <schmidt@cse.wustl.edu>
8 //=============================================================================
11 #ifndef ACE_HASH_MAP_MANAGER_T_CPP
12 #define ACE_HASH_MAP_MANAGER_T_CPP
14 #include "ace/Hash_Map_Manager_T.h"
16 #if !defined (ACE_LACKS_PRAGMA_ONCE)
18 #endif /* ACE_LACKS_PRAGMA_ONCE */
20 #if !defined (__ACE_INLINE__)
21 # include "ace/Hash_Map_Manager_T.inl"
22 #endif /* __ACE_INLINE__ */
24 #include "ace/Malloc_Base.h"
26 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
28 ACE_ALLOC_HOOK_DEFINE_Tc5(ACE_Hash_Map_Manager_Ex
)
29 ACE_ALLOC_HOOK_DEFINE_Tc5(ACE_Hash_Map_Iterator_Base_Ex
)
30 ACE_ALLOC_HOOK_DEFINE_Tc5(ACE_Hash_Map_Iterator_Ex
)
31 ACE_ALLOC_HOOK_DEFINE_Tc5(ACE_Hash_Map_Const_Iterator_Base_Ex
)
32 ACE_ALLOC_HOOK_DEFINE_Tc5(ACE_Hash_Map_Const_Iterator_Ex
)
33 ACE_ALLOC_HOOK_DEFINE_Tc5(ACE_Hash_Map_Reverse_Iterator_Ex
)
34 ACE_ALLOC_HOOK_DEFINE_Tc5(ACE_Hash_Map_Const_Reverse_Iterator_Ex
)
36 template <class EXT_ID
, class INT_ID
>
37 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
>::ACE_Hash_Map_Entry (ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> *next
,
38 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> *prev
)
44 template <class EXT_ID
, class INT_ID
>
45 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
>::ACE_Hash_Map_Entry (const EXT_ID
&ext_id
,
47 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> *next
,
48 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> *prev
)
56 template <class EXT_ID
, class INT_ID
>
57 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
>::~ACE_Hash_Map_Entry ()
61 template <class EXT_ID
, class INT_ID
> EXT_ID
&
62 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
>::key ()
67 template <class EXT_ID
, class INT_ID
> const EXT_ID
&
68 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
>::key () const
73 template <class EXT_ID
, class INT_ID
> INT_ID
&
74 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
>::item ()
79 template <class EXT_ID
, class INT_ID
> const INT_ID
&
80 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
>::item () const
85 template <class EXT_ID
, class INT_ID
> void
86 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
>::dump () const
88 #if defined (ACE_HAS_DUMP)
89 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
90 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("next_ = %d"), this->next_
));
91 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("prev_ = %d"), this->prev_
));
92 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
93 #endif /* ACE_HAS_DUMP */
96 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> void
97 ACE_Hash_Map_Manager_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::dump () const
99 #if defined (ACE_HAS_DUMP)
100 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
101 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("total_size_ = %d\n"), this->total_size_
));
102 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("cur_size_ = %d\n"), this->cur_size_
));
103 this->table_allocator_
->dump ();
104 this->entry_allocator_
->dump ();
106 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
107 #endif /* ACE_HAS_DUMP */
110 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> int
111 ACE_Hash_Map_Manager_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::create_buckets (size_t size
)
113 size_t bytes
= size
* sizeof (ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
>);
116 ACE_ALLOCATOR_RETURN (ptr
,
117 this->table_allocator_
->malloc (bytes
),
120 this->table_
= (ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> *) ptr
;
122 this->total_size_
= size
;
124 // Initialize each entry in the hash table to be a circular linked
125 // list with the dummy node in the front serving as the anchor of
127 for (size_t i
= 0; i
< size
; i
++)
128 new (&this->table_
[i
]) ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> (&this->table_
[i
],
133 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> int
134 ACE_Hash_Map_Manager_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::open (size_t size
,
135 ACE_Allocator
*table_alloc
,
136 ACE_Allocator
*entry_alloc
)
138 ACE_WRITE_GUARD_RETURN (ACE_LOCK
, ace_mon
, this->lock_
, -1);
140 // Calling this->close_i () to ensure we release previous allocated
141 // memory before allocating new one.
144 if (table_alloc
== 0)
145 table_alloc
= ACE_Allocator::instance ();
147 this->table_allocator_
= table_alloc
;
149 if (entry_alloc
== 0)
150 entry_alloc
= table_alloc
;
152 this->entry_allocator_
= entry_alloc
;
154 // This assertion is here to help track a situation that shouldn't
155 // happen, but did with Sun C++ 4.1 (before a change to this class
156 // was made: it used to have an enum that was supposed to be defined
157 // to be ACE_DEFAULT_MAP_SIZE, but instead was defined to be 0).
161 return this->create_buckets (size
);
164 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> int
165 ACE_Hash_Map_Manager_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::close_i ()
167 // Protect against "double-deletion" in case the destructor also
169 if (this->table_
!= 0)
171 // Remove all the entries.
172 this->unbind_all_i ();
174 // Iterate through the buckets cleaning up the sentinels.
175 for (size_t i
= 0; i
< this->total_size_
; i
++)
177 // Destroy the dummy entry.
178 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> *entry
= &this->table_
[i
];
180 // The second argument results in a no-op instead of
182 ACE_DES_FREE_TEMPLATE2 (entry
, ACE_NOOP
,
183 ACE_Hash_Map_Entry
, EXT_ID
, INT_ID
);
187 this->total_size_
= 0;
189 // Free table memory.
190 this->table_allocator_
->free (this->table_
);
192 // Should be done last...
199 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> int
200 ACE_Hash_Map_Manager_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::unbind_all_i ()
202 // Iterate through the entire map calling the destuctor of each
203 // <ACE_Hash_Map_Entry>.
204 for (size_t i
= 0; i
< this->total_size_
; i
++)
206 for (ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> *temp_ptr
= this->table_
[i
].next_
;
207 temp_ptr
!= &this->table_
[i
];
210 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> *hold_ptr
= temp_ptr
;
211 temp_ptr
= temp_ptr
->next_
;
213 // Explicitly call the destructor.
214 ACE_DES_FREE_TEMPLATE2 (hold_ptr
, this->entry_allocator_
->free
,
215 ACE_Hash_Map_Entry
, EXT_ID
, INT_ID
);
218 // Restore the sentinel.
219 this->table_
[i
].next_
= &this->table_
[i
];
220 this->table_
[i
].prev_
= &this->table_
[i
];
228 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> int
229 ACE_Hash_Map_Manager_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::bind_i (const EXT_ID
&ext_id
,
230 const INT_ID
&int_id
,
231 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> *&entry
)
234 if (this->shared_find (ext_id
, entry
, loc
) == -1)
238 ACE_ALLOCATOR_RETURN (ptr
,
239 this->entry_allocator_
->malloc (sizeof (ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
>)),
242 entry
= new (ptr
) ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> (ext_id
,
244 this->table_
[loc
].next_
,
246 this->table_
[loc
].next_
= entry
;
247 entry
->next_
->prev_
= entry
;
255 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> int
256 ACE_Hash_Map_Manager_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::trybind_i (const EXT_ID
&ext_id
,
258 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> *&entry
)
261 if (this->shared_find (ext_id
, entry
, loc
) == -1)
265 ACE_ALLOCATOR_RETURN (ptr
,
266 this->entry_allocator_
->malloc (sizeof (ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
>)),
269 entry
= new (ptr
) ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> (ext_id
,
271 this->table_
[loc
].next_
,
273 this->table_
[loc
].next_
= entry
;
274 entry
->next_
->prev_
= entry
;
282 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> int
283 ACE_Hash_Map_Manager_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::unbind_i (const EXT_ID
&ext_id
,
286 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> *temp
= 0;
289 if (this->shared_find (ext_id
, temp
, loc
) == -1)
295 int_id
= temp
->int_id_
;
297 return this->unbind_i (temp
);
300 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> int
301 ACE_Hash_Map_Manager_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::unbind_i (ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> *entry
)
303 entry
->next_
->prev_
= entry
->prev_
;
304 entry
->prev_
->next_
= entry
->next_
;
306 // Explicitly call the destructor.
307 ACE_DES_FREE_TEMPLATE2 (entry
, this->entry_allocator_
->free
,
308 ACE_Hash_Map_Entry
, EXT_ID
, INT_ID
);
314 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> int
315 ACE_Hash_Map_Manager_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::shared_find (const EXT_ID
&ext_id
,
316 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> *&entry
,
319 if (this->total_size_
== 0)
325 loc
= this->hash (ext_id
) % this->total_size_
;
327 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> *temp
= this->table_
[loc
].next_
;
329 while (temp
!= &this->table_
[loc
] && this->equal (temp
->ext_id_
, ext_id
) == 0)
332 if (temp
== &this->table_
[loc
])
344 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> int
345 ACE_Hash_Map_Manager_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::rebind_i (const EXT_ID
&ext_id
,
346 const INT_ID
&int_id
,
347 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> *&entry
)
350 if (this->shared_find (ext_id
, entry
, dummy
) == -1)
351 return this->bind_i (ext_id
, int_id
);
354 entry
->ext_id_
= ext_id
;
355 entry
->int_id_
= int_id
;
360 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> int
361 ACE_Hash_Map_Manager_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::rebind_i (const EXT_ID
&ext_id
,
362 const INT_ID
&int_id
,
364 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> *&entry
)
367 if (this->shared_find (ext_id
, entry
, dummy
) == -1)
368 return this->bind_i (ext_id
, int_id
);
371 old_int_id
= entry
->int_id_
;
372 entry
->ext_id_
= ext_id
;
373 entry
->int_id_
= int_id
;
378 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> int
379 ACE_Hash_Map_Manager_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::rebind_i (const EXT_ID
&ext_id
,
380 const INT_ID
&int_id
,
383 ACE_Hash_Map_Entry
<EXT_ID
, INT_ID
> *&entry
)
386 if (this->shared_find (ext_id
, entry
, dummy
) == -1)
387 return this->bind_i (ext_id
, int_id
);
390 old_ext_id
= entry
->ext_id_
;
391 old_int_id
= entry
->int_id_
;
392 entry
->ext_id_
= ext_id
;
393 entry
->int_id_
= int_id
;
398 // ------------------------------------------------------------
400 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> void
401 ACE_Hash_Map_Iterator_Base_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::dump_i () const
403 ACE_TRACE ("ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump_i");
405 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
406 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("index_ = %d "), this->index_
));
407 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("next_ = %x"), this->next_
));
408 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
411 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> int
412 ACE_Hash_Map_Iterator_Base_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::forward_i ()
414 ACE_TRACE ("ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::forward_i");
416 if (this->map_man_
->table_
== 0)
418 // Handle initial case specially.
419 else if (this->index_
== -1)
422 return this->forward_i ();
424 else if (this->index_
>= static_cast<ssize_t
> (this->map_man_
->total_size_
))
427 this->next_
= this->next_
->next_
;
428 if (this->next_
== &this->map_man_
->table_
[this->index_
])
430 while (++this->index_
< static_cast<ssize_t
> (this->map_man_
->total_size_
))
432 this->next_
= this->map_man_
->table_
[this->index_
].next_
;
433 if (this->next_
!= &this->map_man_
->table_
[this->index_
])
438 return this->index_
< static_cast<ssize_t
> (this->map_man_
->total_size_
);
441 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> int
442 ACE_Hash_Map_Iterator_Base_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::reverse_i ()
444 ACE_TRACE ("ACE_Hash_Map_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::reverse_i");
446 if (this->map_man_
->table_
== 0)
448 else if (this->index_
== static_cast<ssize_t
> (this->map_man_
->total_size_
))
451 return this->reverse_i ();
453 else if (this->index_
< 0)
456 this->next_
= this->next_
->prev_
;
457 if (this->next_
== &this->map_man_
->table_
[this->index_
])
459 while (--this->index_
>= 0)
461 this->next_
= this->map_man_
->table_
[this->index_
].prev_
;
462 if (this->next_
!= &this->map_man_
->table_
[this->index_
])
467 return this->index_
>= 0;
470 // ------------------------------------------------------------
472 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> void
473 ACE_Hash_Map_Const_Iterator_Base_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::dump_i () const
475 ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::dump_i");
477 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
478 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("index_ = %d "), this->index_
));
479 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("next_ = %x"), this->next_
));
480 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
483 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> int
484 ACE_Hash_Map_Const_Iterator_Base_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::forward_i ()
486 ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::forward_i");
488 if (this->map_man_
->table_
== 0)
490 // Handle initial case specially.
491 else if (this->index_
== -1)
494 return this->forward_i ();
496 else if (this->index_
>= (ssize_t
) this->map_man_
->total_size_
)
499 this->next_
= this->next_
->next_
;
500 if (this->next_
== &this->map_man_
->table_
[this->index_
])
502 while (++this->index_
< (ssize_t
) this->map_man_
->total_size_
)
504 this->next_
= this->map_man_
->table_
[this->index_
].next_
;
505 if (this->next_
!= &this->map_man_
->table_
[this->index_
])
510 return this->index_
< (ssize_t
) this->map_man_
->total_size_
;
513 template <class EXT_ID
, class INT_ID
, class HASH_KEY
, class COMPARE_KEYS
, class ACE_LOCK
> int
514 ACE_Hash_Map_Const_Iterator_Base_Ex
<EXT_ID
, INT_ID
, HASH_KEY
, COMPARE_KEYS
, ACE_LOCK
>::reverse_i ()
516 ACE_TRACE ("ACE_Hash_Map_Const_Iterator_Base_Ex<EXT_ID, INT_ID, HASH_KEY, COMPARE_KEYS, ACE_LOCK>::reverse_i");
518 if (this->map_man_
->table_
== 0)
520 else if (this->index_
== (ssize_t
) this->map_man_
->total_size_
)
523 return this->reverse_i ();
525 else if (this->index_
< 0)
528 this->next_
= this->next_
->prev_
;
529 if (this->next_
== &this->map_man_
->table_
[this->index_
])
531 while (--this->index_
>= 0)
533 this->next_
= this->map_man_
->table_
[this->index_
].prev_
;
534 if (this->next_
!= &this->map_man_
->table_
[this->index_
])
539 return this->index_
>= 0;
542 ACE_END_VERSIONED_NAMESPACE_DECL
544 #endif /* ACE_HASH_MAP_MANAGER_T_CPP */