00001
00002
00003 #ifndef ACE_TIMER_HASH_T_C
00004 #define ACE_TIMER_HASH_T_C
00005
00006 #include "ace/Timer_Hash_T.h"
00007
00008 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00009 # pragma once
00010 #endif
00011
00012 #include "ace/High_Res_Timer.h"
00013 #include "ace/Log_Msg.h"
00014
00015 ACE_RCSID(ace,
00016 Timer_Hash_T,
00017 "$Id: Timer_Hash_T.cpp,v 1.1.1.4 2003/02/21 18:36:32 chad Exp $")
00018
00019 struct Hash_Token
00020 {
00021 Hash_Token (const void *act,
00022 size_t pos,
00023 long orig_id)
00024 : act_ (act),
00025 pos_ (pos),
00026 orig_id_ (orig_id)
00027 {}
00028
00029 const void *act_;
00030 size_t pos_;
00031 long orig_id_;
00032 };
00033
00034
00035
00036 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00037 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Hash_Upcall (void)
00038 : timer_hash_ (0)
00039 {
00040
00041 }
00042
00043
00044
00045 template <class TYPE, class FUNCTOR, class ACE_LOCK>
00046 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Hash_Upcall (ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> *timer_hash)
00047 : timer_hash_ (timer_hash)
00048 {
00049
00050 }
00051
00052
00053
00054 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00055 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::timeout (TIMER_QUEUE &timer_queue,
00056 ACE_Event_Handler *handler,
00057 const void *arg,
00058 const ACE_Time_Value &cur_time)
00059 {
00060 ACE_UNUSED_ARG (timer_queue);
00061
00062 Hash_Token *h = ACE_reinterpret_cast (Hash_Token *,
00063 ACE_const_cast (void *,
00064 arg));
00065 int result =
00066 this->timer_hash_->upcall_functor ().timeout (*this->timer_hash_,
00067 handler,
00068 h->act_,
00069 cur_time);
00070 delete h;
00071 return result;
00072 }
00073
00074
00075
00076
00077 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00078 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::cancellation (TIMER_QUEUE &timer_queue,
00079 ACE_Event_Handler *handler)
00080 {
00081 ACE_UNUSED_ARG (timer_queue);
00082 return this->timer_hash_->upcall_functor ().cancellation (*this->timer_hash_,
00083 handler);
00084 }
00085
00086
00087
00088
00089 template <class TYPE, class FUNCTOR, class ACE_LOCK> int
00090 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>::deletion (TIMER_QUEUE &timer_queue,
00091 ACE_Event_Handler *handler,
00092 const void *arg)
00093 {
00094 ACE_UNUSED_ARG (timer_queue);
00095
00096 Hash_Token *h = ACE_reinterpret_cast (Hash_Token *,
00097 ACE_const_cast (void *,
00098 arg));
00099 int result =
00100 this->timer_hash_->upcall_functor ().deletion (*this->timer_hash_,
00101 handler,
00102 h->act_);
00103 delete h;
00104 return result;
00105 }
00106
00107
00108
00109 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
00110 ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::ACE_Timer_Hash_Iterator_T (ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET> &hash)
00111 : timer_hash_ (hash)
00112 {
00113 this->first ();
00114
00115 }
00116
00117
00118
00119 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> void
00120 ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::first (void)
00121 {
00122 for (this->position_ = 0;
00123 this->position_ < this->timer_hash_.table_size_;
00124 this->position_++)
00125 {
00126
00127 if (!this->timer_hash_.table_[this->position_]->is_empty ())
00128 {
00129 this->iter_ = &this->timer_hash_.table_[this->position_]->iter ();
00130 this->iter_->first ();
00131 return;
00132 }
00133 }
00134
00135
00136 this->iter_ = 0;
00137 }
00138
00139
00140
00141
00142 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> void
00143 ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::next (void)
00144 {
00145 if (this->isdone ())
00146 return;
00147
00148
00149 if (this->iter_->isdone ())
00150 {
00151 for (this->position_++;
00152 this->position_ < this->timer_hash_.table_size_;
00153 this->position_++)
00154 {
00155
00156 if (!this->timer_hash_.table_[this->position_]->is_empty ())
00157 {
00158 this->iter_ = &this->timer_hash_.table_[this->position_]->iter ();
00159 this->iter_->first ();
00160 return;
00161 }
00162 }
00163
00164
00165 this->iter_ = 0;
00166 }
00167 else
00168 this->iter_->next ();
00169 }
00170
00171
00172
00173 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
00174 ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::isdone (void) const
00175 {
00176 return this->iter_ == 0;
00177 }
00178
00179
00180
00181 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> ACE_Timer_Node_T<TYPE> *
00182 ACE_Timer_Hash_Iterator_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::item (void)
00183 {
00184 if (this->isdone ())
00185 return 0;
00186
00187 return this->iter_->item ();
00188 }
00189
00190 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK> &
00191 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::iter (void)
00192 {
00193 this->iterator_->first ();
00194 return *this->iterator_;
00195 }
00196
00197
00198
00199 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
00200 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::ACE_Timer_Hash_T (size_t table_size,
00201 FUNCTOR *upcall_functor,
00202 ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
00203 : ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> (upcall_functor, freelist),
00204 size_ (0),
00205 table_size_ (table_size),
00206 table_functor_ (this),
00207 earliest_position_ (0)
00208 #if defined (ACE_WIN64)
00209 , pointer_base_ (0)
00210 #endif
00211 {
00212 ACE_TRACE ("ACE_Timer_Hash_T::ACE_Timer_Hash_T");
00213
00214 ACE_NEW (table_,
00215 BUCKET *[table_size]);
00216
00217 this->gettimeofday (ACE_OS::gettimeofday);
00218
00219 for (size_t i = 0;
00220 i < table_size;
00221 i++)
00222 {
00223 ACE_NEW (this->table_[i],
00224 BUCKET (&this->table_functor_,
00225 this->free_list_));
00226 this->table_[i]->gettimeofday (ACE_OS::gettimeofday);
00227 }
00228
00229 ACE_NEW (iterator_,
00230 HASH_ITERATOR (*this));
00231 }
00232
00233
00234 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
00235 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::ACE_Timer_Hash_T (FUNCTOR *upcall_functor,
00236 ACE_Free_List<ACE_Timer_Node_T <TYPE> > *freelist)
00237 : ACE_Timer_Queue_T<TYPE, FUNCTOR, ACE_LOCK> (upcall_functor, freelist),
00238 size_ (0),
00239 table_size_ (ACE_DEFAULT_TIMER_HASH_TABLE_SIZE),
00240 table_functor_ (this),
00241 earliest_position_ (0)
00242 #if defined (ACE_WIN64)
00243 , pointer_base_ (0)
00244 #endif
00245 {
00246 ACE_TRACE ("ACE_Timer_Hash_T::ACE_Timer_Hash_T");
00247
00248 ACE_NEW (table_,
00249 BUCKET *[ACE_DEFAULT_TIMER_HASH_TABLE_SIZE]);
00250
00251
00252 this->gettimeofday (ACE_OS::gettimeofday);
00253
00254 for (size_t i = 0;
00255 i < this->table_size_;
00256 i++)
00257 {
00258 ACE_NEW (this->table_[i],
00259 BUCKET (&this->table_functor_,
00260 this->free_list_));
00261 this->table_[i]->gettimeofday (ACE_OS::gettimeofday);
00262 }
00263
00264 ACE_NEW (iterator_,
00265 HASH_ITERATOR (*this));
00266 }
00267
00268
00269
00270 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET>
00271 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::~ACE_Timer_Hash_T (void)
00272 {
00273 ACE_TRACE ("ACE_Timer_Hash_T::~ACE_Timer_Hash_T");
00274 ACE_MT (ACE_GUARD (ACE_LOCK, ace_mon, this->mutex_));
00275
00276 delete iterator_;
00277
00278 for (size_t i = 0;
00279 i < this->table_size_;
00280 i++)
00281 delete this->table_[i];
00282
00283 delete [] this->table_;
00284 }
00285
00286
00287
00288 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
00289 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::is_empty (void) const
00290 {
00291 ACE_TRACE ("ACE_Timer_Hash_T::is_empty");
00292 return this->table_[this->earliest_position_]->is_empty ();
00293 }
00294
00295
00296
00297 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> const ACE_Time_Value &
00298 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::earliest_time (void) const
00299 {
00300 ACE_TRACE ("ACE_Timer_Hash_T::earliest_time");
00301 return this->table_[this->earliest_position_]->earliest_time ();
00302 }
00303
00304 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> void
00305 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::dump (void) const
00306 {
00307 ACE_TRACE ("ACE_Timer_Hash_T::dump");
00308 ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00309 ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ntable_size_ = %d"), this->table_size_));
00310 ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nearliest_position_ = %d"), this->earliest_position_));
00311
00312 for (size_t i = 0; i < this->table_size_; i++)
00313 if (!this->table_[i]->is_empty ())
00314 ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nBucket %d contains nodes"), i));
00315
00316 ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\n")));
00317 ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00318 }
00319
00320
00321
00322
00323 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> void
00324 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::reschedule (ACE_Timer_Node_T<TYPE> *expired)
00325 {
00326 ACE_TRACE ("ACE_Timer_Hash_T::reschedule");
00327
00328 size_t position =
00329 expired->get_timer_value ().sec () % this->table_size_;
00330
00331 Hash_Token *h = ACE_reinterpret_cast (Hash_Token *,
00332 ACE_const_cast (void *,
00333 expired->get_act ()));
00334
00335 h->orig_id_ = this->table_[position]->schedule (expired->get_type (),
00336 h,
00337 expired->get_timer_value (),
00338 expired->get_interval ());
00339
00340 if (this->table_[this->earliest_position_]->is_empty ()
00341 || this->table_[position]->earliest_time ()
00342 < this->table_[this->earliest_position_]->earliest_time ())
00343 this->earliest_position_ = position;
00344 }
00345
00346
00347
00348
00349 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> long
00350 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::schedule (const TYPE &type,
00351 const void *act,
00352 const ACE_Time_Value &future_time,
00353 const ACE_Time_Value &interval)
00354 {
00355 ACE_TRACE ("ACE_Timer_Hash_T::schedule");
00356 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00357
00358 size_t position =
00359 future_time.sec () % this->table_size_;
00360
00361 Hash_Token *h;
00362
00363 ACE_NEW_RETURN (h,
00364 Hash_Token (act,
00365 position,
00366 0),
00367 -1);
00368
00369 h->orig_id_ = this->table_[position]->schedule (type,
00370 h,
00371 future_time,
00372 interval);
00373
00374 if (this->table_[this->earliest_position_]->is_empty ()
00375 || this->table_[position]->earliest_time ()
00376 < this->table_[this->earliest_position_]->earliest_time ())
00377 this->earliest_position_ = position;
00378
00379 ++this->size_;
00380
00381 #if defined (ACE_WIN64)
00382
00383
00384
00385
00386
00387
00388
00389
00390 ptrdiff_t hi = ACE_reinterpret_cast (ptrdiff_t, h);
00391 if (this->pointer_base_ == 0)
00392 this->pointer_base_ = hi & 0xffffffff00000000;
00393 return ACE_reinterpret_cast (long, hi & 0xffffffff);
00394 #else
00395 return ACE_reinterpret_cast (long, h);
00396 #endif
00397 }
00398
00399
00400
00401 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
00402 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::reset_interval (long timer_id,
00403 const ACE_Time_Value &interval)
00404 {
00405 ACE_TRACE ("ACE_Timer_Hash_T::reset_interval");
00406 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00407
00408
00409
00410 if (timer_id == -1)
00411 return -1;
00412
00413
00414 #if defined (ACE_WIN64)
00415 unsigned long timer_offset = ACE_static_cast (unsigned long, timer_id);
00416 Hash_Token *h = ACE_reinterpret_cast (Hash_Token *,
00417 (this->pointer_base_ + timer_offset));
00418 #else
00419 Hash_Token *h = ACE_reinterpret_cast (Hash_Token *,
00420 timer_id);
00421 #endif
00422
00423 return this->table_[h->pos_]->reset_interval (h->orig_id_,
00424 interval);
00425 }
00426
00427
00428
00429
00430 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
00431 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::cancel (long timer_id,
00432 const void **act,
00433 int dont_call)
00434 {
00435 ACE_TRACE ("ACE_Timer_Hash_T::cancel");
00436 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00437
00438
00439
00440 if (timer_id == -1)
00441 return 0;
00442
00443 #if defined (ACE_WIN64)
00444 unsigned long timer_offset = ACE_static_cast (unsigned long, timer_id);
00445 Hash_Token *h = ACE_reinterpret_cast (Hash_Token *,
00446 (this->pointer_base_ + timer_offset));
00447 #else
00448 Hash_Token *h = ACE_reinterpret_cast (Hash_Token *,
00449 timer_id);
00450 #endif
00451
00452 int result = this->table_[h->pos_]->cancel (h->orig_id_,
00453 act,
00454 dont_call);
00455
00456 if (h->pos_ == this->earliest_position_)
00457 this->find_new_earliest ();
00458
00459 if (act != 0)
00460 *act = h->act_;
00461
00462 delete h;
00463
00464 --this->size_;
00465
00466 return result;
00467 }
00468
00469
00470
00471 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
00472 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::cancel (const TYPE &type,
00473 int dont_call)
00474 {
00475 ACE_TRACE ("ACE_Timer_Hash_T::cancel");
00476
00477 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00478
00479 size_t i;
00480
00481 Hash_Token **timer_ids;
00482
00483 ACE_NEW_RETURN (timer_ids,
00484 Hash_Token *[this->size_],
00485 -1);
00486 size_t pos = 0;
00487
00488 for (i = 0;
00489 i < this->table_size_;
00490 i++)
00491 {
00492 ACE_Timer_Queue_Iterator_T<TYPE,
00493 ACE_Timer_Hash_Upcall<TYPE, FUNCTOR, ACE_LOCK>,
00494 ACE_Null_Mutex> &iter =
00495 this->table_[i]->iter ();
00496
00497 for (iter.first ();
00498 !iter.isdone ();
00499 iter.next ())
00500 if (iter.item ()->get_type () == type)
00501 timer_ids[pos++] =
00502 ACE_reinterpret_cast (Hash_Token *,
00503 ACE_const_cast (void *,
00504 iter.item ()->get_act ()));
00505 }
00506
00507 if (pos > this->size_)
00508 return -1;
00509
00510 for (i = 0; i < pos; i++)
00511 {
00512 this->table_[timer_ids[i]->pos_]->cancel (timer_ids[i]->orig_id_,
00513 0,
00514 1);
00515 delete timer_ids[i];
00516 --this->size_;
00517 }
00518
00519 delete [] timer_ids;
00520
00521 if (dont_call == 0)
00522 this->upcall_functor ().cancellation (*this,
00523 type);
00524 this->find_new_earliest ();
00525
00526 return ACE_static_cast (int, pos);
00527 }
00528
00529
00530
00531 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> ACE_Timer_Node_T<TYPE> *
00532 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::remove_first (void)
00533 {
00534 if (this->is_empty ())
00535 return 0;
00536
00537 ACE_Timer_Node_T<TYPE> *temp =
00538 this->table_[this->earliest_position_]->remove_first ();
00539
00540 this->find_new_earliest ();
00541
00542 --this->size_;
00543
00544 return temp;
00545 }
00546
00547
00548
00549 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> void
00550 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::find_new_earliest (void)
00551 {
00552 for (size_t i = 0; i < this->table_size_; i++)
00553 if (!this->table_[i]->is_empty ())
00554 if (this->table_[this->earliest_position_]->is_empty ()
00555 || this->earliest_time () == ACE_Time_Value::zero
00556 || this->table_[i]->earliest_time () <= this->earliest_time ())
00557 this->earliest_position_ = i;
00558 }
00559
00560
00561
00562 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> ACE_Timer_Node_T<TYPE> *
00563 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::get_first (void)
00564 {
00565 ACE_TRACE ("ACE_Timer_Hash_T::get_first");
00566
00567 if (this->is_empty ())
00568 return 0;
00569
00570 return this->table_[this->earliest_position_]->get_first ();
00571 }
00572
00573
00574
00575 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
00576 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::expire ()
00577 {
00578 return ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK>::expire();
00579 }
00580
00581
00582
00583 template <class TYPE, class FUNCTOR, class ACE_LOCK, class BUCKET> int
00584 ACE_Timer_Hash_T<TYPE, FUNCTOR, ACE_LOCK, BUCKET>::expire (const ACE_Time_Value &cur_time)
00585 {
00586 ACE_TRACE ("ACE_Timer_Hash_T::expire");
00587 ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
00588
00589 int number_of_timers_expired = 0;
00590
00591 ACE_Timer_Node_T<TYPE> *expired;
00592
00593
00594
00595 for (size_t i = 0;
00596 i < this->table_size_;
00597 i++)
00598 {
00599 while (!this->table_[i]->is_empty ()
00600 && this->table_[i]->earliest_time () <= cur_time)
00601 {
00602 expired = this->table_[i]->get_first ();
00603 TYPE type = expired->get_type ();
00604 const void *act = expired->get_act ();
00605 int reclaim = 1;
00606
00607
00608 if (expired->get_interval () > ACE_Time_Value::zero)
00609 {
00610
00611
00612 do
00613 expired->set_timer_value (expired->get_timer_value ()
00614 + expired->get_interval ());
00615 while (expired->get_timer_value () <= cur_time);
00616
00617
00618
00619 this->reschedule (expired);
00620 reclaim = 0;
00621 }
00622
00623
00624
00625
00626
00627
00628 this->table_[i]->cancel (expired->get_timer_id ());
00629
00630 Hash_Token *h = ACE_reinterpret_cast (Hash_Token *,
00631 ACE_const_cast (void *,
00632 act));
00633
00634 this->upcall (type,
00635 h->act_,
00636 cur_time);
00637 if (reclaim)
00638 {
00639 --this->size_;
00640 delete h;
00641 }
00642 number_of_timers_expired++;
00643 }
00644 }
00645
00646 return number_of_timers_expired;
00647 }
00648
00649 #endif