PageRenderTime 48ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/dep/acelite/ace/Timer_Wheel_T.cpp

https://github.com/chucho/FaceCore
C++ | 964 lines | 597 code | 128 blank | 239 comment | 105 complexity | 6dd4c0888a51ddecaaffe6df47a32202 MD5 | raw file
  1. // $Id: Timer_Wheel_T.cpp 89254 2010-02-25 22:10:39Z cleeland $
  2. #ifndef ACE_TIMER_WHEEL_T_CPP
  3. #define ACE_TIMER_WHEEL_T_CPP
  4. #if !defined (ACE_LACKS_PRAGMA_ONCE)
  5. # pragma once
  6. #endif /* ACE_LACKS_PRAGMA_ONCE */
  7. #include "ace/OS_NS_sys_time.h"
  8. #include "ace/Guard_T.h"
  9. #include "ace/Timer_Wheel_T.h"
  10. #include "ace/Log_Msg.h"
  11. ACE_BEGIN_VERSIONED_NAMESPACE_DECL
  12. // Design/implementation notes for ACE_Timer_Wheel_T.
  13. //
  14. // Each timer queue entry is represented by a ACE_Timer_Node.
  15. // The timing wheel is divided into a number of "spokes"; there are
  16. // spoke_count_ spokes in the wheel. Each timer is hashed into one of the
  17. // spokes. Entries within each spoke are linked in a double-linked list
  18. // in order of increasing expiration. The first ACE_Timer_Node in each
  19. // spoke is a "dummy node" that marks the end of the list of ACE_Timer_Nodes
  20. // in that spoke.
  21. //
  22. // The timer ID for a scheduled timer is formed by its spoke position in
  23. // the wheel, and the number of timers that have been inserted in that spoke
  24. // since the queue was initialized. N bits of the long timer_id are used
  25. // to determine the spoke, and M bits are used as a counter.
  26. // Each time a Node is inserted into a spoke, it's counter
  27. // is incremented. The count is kept in the timer ID field
  28. // of the dummy root Node. In the event of overflow of the counter, the spoke
  29. // must be searched for each new id to make sure it's not already in use. To
  30. // prevent having to do an exhaustive search each time, we keep extra data
  31. // in the dummy root Node.
  32. /**
  33. * Default Constructor that sets defaults for spoke_count_ and resolution_
  34. * and doesn't do any preallocation.
  35. *
  36. * @param upcall_functor A pointer to a functor to use instead of the default
  37. * @param freelist A pointer to a freelist to use instead of the default
  38. */
  39. template <class TYPE, class FUNCTOR, class ACE_LOCK>
  40. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Wheel_T
  41. (FUNCTOR* upcall_functor
  42. , FreeList* freelist
  43. )
  44. : Base (upcall_functor, freelist)
  45. , spokes_(0)
  46. , spoke_count_(0) // calculated in open_i
  47. , spoke_bits_(0)
  48. , res_bits_ (0)
  49. , earliest_spoke_ (0)
  50. , iterator_(0)
  51. , timer_count_(0)
  52. {
  53. ACE_TRACE ("ACE_Timer_Wheel_T::ACE_Timer_Wheel_T");
  54. this->open_i (0,
  55. ACE_DEFAULT_TIMER_WHEEL_SIZE,
  56. ACE_DEFAULT_TIMER_WHEEL_RESOLUTION);
  57. }
  58. /**
  59. * Constructor that sets up the timing wheel and also may preallocate
  60. * some nodes on the free list
  61. *
  62. * @param spoke_count The number of lists in the timer wheel
  63. * @param resolution The time resolution in milliseconds used by the hashing function
  64. * @param prealloc The number of entries to prealloc in the free_list
  65. * @param upcall_functor A pointer to a functor to use instead of the default
  66. * @param freelist A pointer to a freelist to use instead of the default
  67. */
  68. template <class TYPE, class FUNCTOR, class ACE_LOCK>
  69. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Wheel_T
  70. (u_int spoke_count,
  71. u_int resolution,
  72. size_t prealloc,
  73. FUNCTOR* upcall_functor,
  74. FreeList* freelist)
  75. : Base (upcall_functor, freelist)
  76. , spokes_ (0)
  77. , spoke_count_ (0) // calculated in open_i
  78. , spoke_bits_ (0)
  79. , res_bits_ (0)
  80. , earliest_spoke_ (0)
  81. , iterator_ (0)
  82. , timer_count_ (0)
  83. {
  84. ACE_TRACE ("ACE_Timer_Wheel_T::ACE_Timer_Wheel_T");
  85. this->open_i (prealloc, spoke_count, resolution);
  86. }
  87. template <class TYPE, class FUNCTOR, class ACE_LOCK> int
  88. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::power2bits (int n,
  89. int min_bits,
  90. int max_bits)
  91. {
  92. int max = (1 << max_bits) - 1;
  93. if (n > max)
  94. return max_bits;
  95. // count the bits in n.
  96. int i = 0;
  97. int tmp = n;
  98. do
  99. {
  100. tmp >>= 1;
  101. ++i;
  102. }
  103. while (tmp != 0);
  104. if (i <= min_bits)
  105. return min_bits;
  106. // Which is nearest?
  107. int a = (1 << i) - n;
  108. int b = (1 << (i - 1)) - n;
  109. if (b < 0)
  110. b = -b;
  111. if (b < a)
  112. return i - 1;
  113. return i;
  114. }
  115. /**
  116. * Initialize the queue. Uses the established members for all needed
  117. * information.
  118. */
  119. template <class TYPE, class FUNCTOR, class ACE_LOCK> void
  120. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::open_i
  121. (size_t prealloc, u_int spokes, u_int res)
  122. {
  123. ACE_TRACE ("ACE_Timer_Wheel_T::open_i");
  124. this->gettimeofday (ACE_OS::gettimeofday);
  125. // Rather than waste bits in our timer id, we might as well round up
  126. // the spoke count to the next power of two - 1 . (i.e 1,3,7,15,...127,etc.)
  127. const int MIN_SPOKE_BITS = 3; // Allow between 8 and 4096 spokes
  128. const int MAX_SPOKE_BITS = 12;
  129. const int MAX_RES_BITS = 20; // 20 is plenty, even on 64 bit platforms.
  130. this->spoke_bits_ = power2bits (spokes, MIN_SPOKE_BITS, MAX_SPOKE_BITS);
  131. this->res_bits_ = power2bits (res, 1, MAX_RES_BITS);
  132. this->spoke_count_ = 1 << this->spoke_bits_;
  133. this->free_list_->resize (prealloc + this->spoke_count_);
  134. this->wheel_time_.msec (1 << (this->res_bits_));
  135. ACE_NEW (this->spokes_, ACE_Timer_Node_T<TYPE>* [this->spoke_count_]);
  136. // Create the root nodes. These will be treated specially
  137. for (u_int i = 0; i < this->spoke_count_; ++i)
  138. {
  139. ACE_Timer_Node_T<TYPE>* root = this->alloc_node ();
  140. root->set (0, 0, ACE_Time_Value::zero, ACE_Time_Value::zero, root, root, 0);
  141. this->spokes_[i] = root;
  142. }
  143. ACE_NEW (iterator_, Iterator (*this));
  144. }
  145. /// Destructor just cleans up its memory
  146. template <class TYPE, class FUNCTOR, class ACE_LOCK>
  147. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::~ACE_Timer_Wheel_T (void)
  148. {
  149. ACE_TRACE ("ACE_Timer_Wheel_T::~ACE_Timer_Wheel_T");
  150. delete iterator_;
  151. for (u_int i = 0; i < this->spoke_count_; ++i)
  152. {
  153. // Free all the nodes starting at the root
  154. ACE_Timer_Node_T<TYPE>* root = this->spokes_[i];
  155. for (ACE_Timer_Node_T<TYPE>* n = root->get_next (); n != root;)
  156. {
  157. ACE_Timer_Node_T<TYPE>* next = n->get_next ();
  158. this->upcall_functor ().deletion (*this,
  159. n->get_type (),
  160. n->get_act ());
  161. this->free_node (n);
  162. n = next;
  163. }
  164. delete root;
  165. }
  166. delete[] this->spokes_;
  167. }
  168. /// Searches for a node by timer_id within one spoke.
  169. template <class TYPE, class FUNCTOR, class ACE_LOCK>
  170. ACE_Timer_Node_T<TYPE>*
  171. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::find_spoke_node
  172. (u_int spoke, long timer_id) const
  173. {
  174. ACE_Timer_Node_T<TYPE>* root = this->spokes_[spoke];
  175. for (ACE_Timer_Node_T<TYPE>* n = root->get_next ();
  176. n != root;
  177. n = n->get_next ())
  178. {
  179. if (n->get_timer_id () == timer_id)
  180. return n;
  181. }
  182. return 0;
  183. }
  184. /// Searches all spokes for a node matching the specified timer_id
  185. /// Uses the spoke encoded in the timer_id as a starting place.
  186. template <class TYPE, class FUNCTOR, class ACE_LOCK>
  187. ACE_Timer_Node_T<TYPE>*
  188. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::find_node (long timer_id) const
  189. {
  190. if (timer_id == -1)
  191. return 0;
  192. // Search the spoke where timer_id was originally scheduled
  193. u_int spoke_mask = this->spoke_count_ - 1;
  194. u_int start = timer_id & spoke_mask;
  195. ACE_Timer_Node_T<TYPE>* n = this->find_spoke_node (start, timer_id);
  196. if (n != 0)
  197. return n;
  198. //ACE_ERROR((LM_ERROR, "Node not found in original spoke.\n"));
  199. // Search the rest of the spokes
  200. for (u_int i = 0; i < this->spoke_count_; ++i)
  201. {
  202. if (i != start)
  203. { // already searched this one
  204. n = this->find_spoke_node (i, timer_id);
  205. if (n != 0)
  206. return n;
  207. }
  208. }
  209. //ACE_ERROR((LM_ERROR, "Node not found.\n"));
  210. return 0;
  211. }
  212. /**
  213. * Check to see if the wheel is empty
  214. *
  215. * @return True if empty
  216. */
  217. template <class TYPE, class FUNCTOR, class ACE_LOCK> bool
  218. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::is_empty (void) const
  219. {
  220. ACE_TRACE ("ACE_Timer_Wheel_T::is_empty");
  221. return timer_count_ == 0;
  222. }
  223. /**
  224. * @return First (earliest) node in the wheel_'s earliest_spoke_ list
  225. */
  226. template <class TYPE, class FUNCTOR, class ACE_LOCK> const ACE_Time_Value &
  227. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::earliest_time (void) const
  228. {
  229. ACE_TRACE ("ACE_Timer_Wheel_T::earliest_time");
  230. ACE_Timer_Node_T<TYPE>* n = this->get_first_i ();
  231. if (n != 0)
  232. return n->get_timer_value ();
  233. return ACE_Time_Value::zero;
  234. }
  235. /// Uses a simple hash to find which spoke to use based on when the
  236. /// timer is due to expire. Hopefully the 64bit int operations avoid
  237. /// any overflow problems.
  238. template <class TYPE, class FUNCTOR, class ACE_LOCK> u_int
  239. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::calculate_spoke
  240. (const ACE_Time_Value& t) const
  241. {
  242. return static_cast<u_int> ((t.msec () >> this->res_bits_) & (this->spoke_count_ - 1));
  243. }
  244. /// Generates a unique timer_id for the given spoke. It should be pretty
  245. /// fast until the point where the counter overflows. At that time you
  246. /// have to do exhaustive searches within the spoke to ensure that a particular
  247. /// timer id is not already in use. Some optimizations are in place so
  248. /// that this hopefully doesn't have to happen often.
  249. template <class TYPE, class FUNCTOR, class ACE_LOCK> long
  250. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::generate_timer_id (u_int spoke)
  251. {
  252. int cnt_bits = sizeof (long) * 8 - this->spoke_bits_;
  253. long max_cnt = ((long)1 << cnt_bits) - 1;
  254. if (spoke == this->spoke_count_)
  255. --max_cnt; // Because -1 is used as a special invalid timer_id.
  256. ACE_Timer_Node_T<TYPE>* root = this->spokes_[spoke];
  257. if (root == root->get_next ())
  258. root->set_act(0);
  259. // We use this field to keep track of the next counter value that
  260. // may be in use. Of course it may have expired, so we just use
  261. // this field so that we know when we don't have to check for duplicates
  262. #if defined (ACE_WIN64)
  263. // The cast below is legit... we know that long is shorter than a
  264. // pointer, but are only using it as a 'long' storage area.
  265. # pragma warning(push)
  266. # pragma warning(disable : 4311)
  267. #endif /* ACE_WIN64 */
  268. long next_cnt = reinterpret_cast<long> (root->get_act ());
  269. #if defined (ACE_WIN64)
  270. # pragma warning(pop)
  271. #endif /* ACE_WIN64 */
  272. // This field is used as a counter instead of a timer_id.
  273. long cnt = root->get_timer_id ();
  274. if (cnt >= max_cnt && root == root->get_next ())
  275. {
  276. // Special case when we overflow on an empty spoke. We can just
  277. // wrap the count around without searching for duplicates. We only
  278. // want to do this when the counter overflows, so that we return
  279. // unique timer_id values as often as possible.
  280. root->set_timer_id (1);
  281. return spoke;
  282. }
  283. else if (cnt >= max_cnt)
  284. { // overflow
  285. cnt = 0; // try again starting at zero
  286. }
  287. else if (next_cnt == 0 || cnt < next_cnt)
  288. {
  289. root->set_timer_id (cnt + 1);
  290. return (cnt << this->spoke_bits_) | spoke;
  291. }
  292. //ACE_ERROR((LM_ERROR, "Timer id overflow. We have to search now.\n"));
  293. // We've run out of consecutive id numbers so now we have to search
  294. // for a unique id.
  295. // We'll try increasing numbers until we find one that is not in use,
  296. // and we'll record the next highest number so that we can avoid this
  297. // search as often as possible.
  298. for (; cnt < max_cnt - 1; ++cnt)
  299. {
  300. long id = (cnt << this->spoke_bits_) | spoke;
  301. ACE_Timer_Node_T<TYPE>* n = this->find_spoke_node (spoke, id);
  302. if (n == 0)
  303. {
  304. root->set_timer_id (cnt + 1);
  305. // Now we need to find the next highest cnt in use
  306. next_cnt = 0;
  307. for (; n != root; n = n->get_next ())
  308. {
  309. long tmp = n->get_timer_id () >> this->spoke_bits_;
  310. if (tmp > cnt && (tmp < next_cnt || next_cnt == 0))
  311. next_cnt = tmp;
  312. }
  313. #if defined (ACE_WIN64)
  314. // The cast below is legit... we know we're storing a long in
  315. // a pointer, but are only using it as a 'long' storage area.
  316. # pragma warning(push)
  317. # pragma warning(disable : 4312)
  318. #endif /* ACE_WIN64 */
  319. root->set_act (reinterpret_cast<void*> (next_cnt));
  320. #if defined (ACE_WIN64)
  321. # pragma warning(pop)
  322. #endif /* ACE_WIN64 */
  323. return id;
  324. }
  325. }
  326. return -1; // We did our best, but the spoke is full.
  327. }
  328. /**
  329. * Creates a ACE_Timer_Node_T based on the input parameters. Then inserts
  330. * the node into the wheel using reschedule (). Then returns a timer_id.
  331. *
  332. * @param type The data of the timer node
  333. * @param act Asynchronous Completion Token (AKA magic cookie)
  334. * @param future_time The time the timer is scheduled for (absolute time)
  335. * @param interval If not ACE_Time_Value::zero, then this is a periodic
  336. * timer and interval is the time period
  337. *
  338. * @return Unique identifier (can be used to cancel the timer).
  339. * -1 on failure.
  340. */
  341. template <class TYPE, class FUNCTOR, class ACE_LOCK> long
  342. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::schedule_i (const TYPE& type,
  343. const void* act,
  344. const ACE_Time_Value& future_time,
  345. const ACE_Time_Value& interval)
  346. {
  347. ACE_TRACE ("ACE_Timer_Wheel_T::schedule_i");
  348. ACE_Timer_Node_T<TYPE>* n = this->alloc_node ();
  349. if (n != 0)
  350. {
  351. u_int spoke = calculate_spoke (future_time);
  352. long id = generate_timer_id (spoke);
  353. //ACE_ERROR((LM_ERROR, "Scheduling %x spoke:%d id:%d\n", (long) n, spoke, id));
  354. if (id != -1)
  355. {
  356. n->set (type, act, future_time, interval, 0, 0, id);
  357. this->schedule_i (n, spoke, future_time);
  358. }
  359. return id;
  360. }
  361. // Failure return
  362. errno = ENOMEM;
  363. return -1;
  364. }
  365. /**
  366. * Takes an ACE_Timer_Node and inserts it into the correct position in
  367. * the correct list. Also makes sure to update the earliest time.
  368. *
  369. * @param n The timer node to reschedule
  370. */
  371. template <class TYPE, class FUNCTOR, class ACE_LOCK> void
  372. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::reschedule (ACE_Timer_Node_T<TYPE>* n)
  373. {
  374. ACE_TRACE ("ACE_Timer_Wheel_T::reschedule");
  375. const ACE_Time_Value& expire = n->get_timer_value ();
  376. u_int spoke = calculate_spoke (expire);
  377. this->schedule_i (n, spoke, expire);
  378. }
  379. /// The shared scheduling functionality between schedule() and reschedule()
  380. template <class TYPE, class FUNCTOR, class ACE_LOCK> void
  381. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::schedule_i
  382. (ACE_Timer_Node_T<TYPE>* n,
  383. u_int spoke,
  384. const ACE_Time_Value& expire)
  385. {
  386. // See if we need to update the earliest time
  387. if (this->is_empty() || expire < this->earliest_time ())
  388. this->earliest_spoke_ = spoke;
  389. ACE_Timer_Node_T<TYPE>* root = this->spokes_[spoke];
  390. ACE_Timer_Node_T<TYPE>* last = root->get_prev ();
  391. ++timer_count_;
  392. // If the spoke is empty
  393. if (last == root) {
  394. n->set_prev (root);
  395. n->set_next (root);
  396. root->set_prev (n);
  397. root->set_next (n);
  398. return;
  399. }
  400. // We always want to search backwards from the tail of the list, because
  401. // this minimizes the search in the extreme case when lots of timers are
  402. // scheduled for exactly the same time
  403. ACE_Timer_Node_T<TYPE>* p = root->get_prev ();
  404. while (p != root && p->get_timer_value () > expire)
  405. p = p->get_prev ();
  406. // insert after
  407. n->set_prev (p);
  408. n->set_next (p->get_next ());
  409. p->get_next ()->set_prev (n);
  410. p->set_next (n);
  411. }
  412. /**
  413. * Find the timer node by using the id as a pointer. Then use set_interval()
  414. * on the node to update the interval.
  415. *
  416. * @param timer_id The timer identifier
  417. * @param interval The new interval
  418. *
  419. * @return 0 if successful, -1 if no.
  420. */
  421. template <class TYPE, class FUNCTOR, class ACE_LOCK> int
  422. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::reset_interval (long timer_id,
  423. const ACE_Time_Value &interval
  424. )
  425. {
  426. ACE_TRACE ("ACE_Timer_Wheel_T::reset_interval");
  427. ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
  428. ACE_Timer_Node_T<TYPE>* n = this->find_node (timer_id);
  429. if (n != 0)
  430. {
  431. // The interval will take effect the next time this node is expired.
  432. n->set_interval (interval);
  433. return 0;
  434. }
  435. return -1;
  436. }
  437. /**
  438. * Goes through every list in the wheel and whenever we find one with the
  439. * correct type value, we remove it and continue. At the end make sure
  440. * we reset the earliest time value in case the earliest timers were
  441. * removed.
  442. *
  443. * @param type The value to search for.
  444. * @param skip_close If this non-zero, the cancellation method of the
  445. * functor will not be called for each cancelled timer.
  446. *
  447. * @return Number of timers cancelled
  448. */
  449. template <class TYPE, class FUNCTOR, class ACE_LOCK> int
  450. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (const TYPE& type, int skip_close)
  451. {
  452. ACE_TRACE ("ACE_Timer_Wheel_T::cancel");
  453. int num_canceled = 0; // Note : Technically this can overflow.
  454. int cookie = 0;
  455. ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
  456. if (!this->is_empty ())
  457. {
  458. ACE_Timer_Node_T<TYPE>* first = this->get_first ();
  459. ACE_Time_Value last = first->get_timer_value ();
  460. int recalc = 0;
  461. for (u_int i = 0; i < this->spoke_count_; ++i)
  462. {
  463. ACE_Timer_Node_T<TYPE>* root = this->spokes_[i];
  464. for (ACE_Timer_Node_T<TYPE>* n = root->get_next (); n != root; )
  465. {
  466. if (n->get_type () == type)
  467. {
  468. ++num_canceled;
  469. if (n == first)
  470. recalc = 1;
  471. ACE_Timer_Node_T<TYPE>* tmp = n;
  472. n = n->get_next ();
  473. this->cancel_i (tmp);
  474. }
  475. else
  476. {
  477. n = n->get_next ();
  478. }
  479. }
  480. }
  481. if (recalc)
  482. this->recalc_earliest (last);
  483. }
  484. // Call the close hooks.
  485. // cancel_type() called once per <type>.
  486. this->upcall_functor ().cancel_type (*this,
  487. type,
  488. skip_close,
  489. cookie);
  490. for (int i = 0;
  491. i < num_canceled;
  492. ++i)
  493. {
  494. // cancel_timer() called once per <timer>.
  495. this->upcall_functor ().cancel_timer (*this,
  496. type,
  497. skip_close,
  498. cookie);
  499. }
  500. return num_canceled;
  501. }
  502. /**
  503. * Cancels the single timer that is specified by the timer_id. In this
  504. * case the timer_id is actually a pointer to the node, so we cast it
  505. * to the node. This can be dangerous if the timer_id is made up
  506. * (or deleted twice) so we do a little sanity check. Finally we update
  507. * the earliest time in case the earliest timer was removed.
  508. *
  509. * @param timer_id Timer Identifier
  510. * @param act Asychronous Completion Token (AKA magic cookie):
  511. * If this is non-zero, stores the magic cookie of
  512. * the cancelled timer here.
  513. * @param skip_close If this non-zero, the cancellation method of the
  514. * functor will not be called.
  515. *
  516. * @return 1 for sucess and 0 if the timer_id wasn't found (or was
  517. * found to be invalid)
  518. */
  519. template <class TYPE, class FUNCTOR, class ACE_LOCK> int
  520. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (long timer_id,
  521. const void **act,
  522. int skip_close)
  523. {
  524. ACE_TRACE ("ACE_Timer_Wheel_T::cancel");
  525. ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
  526. ACE_Timer_Node_T<TYPE>* n = this->find_node (timer_id);
  527. if (n != 0)
  528. {
  529. ACE_Time_Value last = n->get_timer_value ();
  530. int recalc = (this->get_first_i () == n);
  531. // Call the close hooks.
  532. int cookie = 0;
  533. // cancel_type() called once per <type>.
  534. this->upcall_functor ().cancel_type (*this,
  535. n->get_type (),
  536. skip_close,
  537. cookie);
  538. // cancel_timer() called once per <timer>.
  539. this->upcall_functor ().cancel_timer (*this,
  540. n->get_type (),
  541. skip_close,
  542. cookie);
  543. if (act != 0)
  544. *act = n->get_act ();
  545. this->cancel_i (n);
  546. if (recalc)
  547. this->recalc_earliest (last);
  548. return 1;
  549. }
  550. return 0;
  551. }
  552. /// Shared subset of the two cancel() methods.
  553. template <class TYPE, class FUNCTOR, class ACE_LOCK> void
  554. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::cancel_i (ACE_Timer_Node_T<TYPE>* n)
  555. {
  556. this->unlink (n);
  557. this->free_node (n);
  558. }
  559. /// There are a few places where we have to figure out which timer
  560. /// will expire next. This method makes the assumption that spokes
  561. /// are always sorted, and that timers are always in the correct spoke
  562. /// determined from their expiration time.
  563. /// The last time is always passed in, even though you can often calculate
  564. /// it as get_first()->get_timer_value().
  565. template <class TYPE, class FUNCTOR, class ACE_LOCK> void
  566. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::recalc_earliest
  567. (const ACE_Time_Value& last)
  568. {
  569. // This is possible because we use a count for is_empty()
  570. if (this->is_empty ())
  571. return;
  572. ACE_Time_Value et = ACE_Time_Value::zero;
  573. u_int es = 0;
  574. u_int spoke = this->earliest_spoke_;
  575. // We will have to go around the wheel at most one time.
  576. for (u_int i = 0; i < this->spoke_count_; ++i)
  577. {
  578. ACE_Timer_Node_T<TYPE>* root = this->spokes_[spoke];
  579. ACE_Timer_Node_T<TYPE>* n = root->get_next ();
  580. if (n != root)
  581. {
  582. ACE_Time_Value t = n->get_timer_value ();
  583. if (t < last + this->wheel_time_)
  584. {
  585. this->earliest_spoke_ = spoke;
  586. return;
  587. }
  588. else if (et == ACE_Time_Value::zero || t < et)
  589. {
  590. et = t;
  591. es = spoke;
  592. }
  593. }
  594. if (++spoke >= this->spoke_count_)
  595. spoke = 0;
  596. }
  597. this->earliest_spoke_ = es;
  598. //ACE_ERROR((LM_ERROR, "We had to search the whole wheel.\n"));
  599. }
  600. /**
  601. * Dumps out the size of the wheel, the resolution, and the contents
  602. * of the wheel.
  603. */
  604. template <class TYPE, class FUNCTOR, class ACE_LOCK> void
  605. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::dump (void) const
  606. {
  607. #if defined (ACE_HAS_DUMP)
  608. ACE_TRACE ("ACE_Timer_Wheel_T::dump");
  609. ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
  610. ACE_DEBUG ((LM_DEBUG,
  611. ACE_TEXT ("\nspoke_count_ = %d"), this->spoke_count_));
  612. ACE_DEBUG ((LM_DEBUG,
  613. ACE_TEXT ("\nresolution_ = %d"), 1 << this->res_bits_));
  614. ACE_DEBUG ((LM_DEBUG,
  615. ACE_TEXT ("\nwheel_ =\n")));
  616. for (u_int i = 0; i < this->spoke_count_; ++i)
  617. {
  618. ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("%d\n"), i));
  619. ACE_Timer_Node_T<TYPE>* root = this->spokes_[i];
  620. for (ACE_Timer_Node_T<TYPE>* n = root->get_next ();
  621. n != root;
  622. n = n->get_next ())
  623. {
  624. n->dump ();
  625. }
  626. }
  627. ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
  628. #endif /* ACE_HAS_DUMP */
  629. }
  630. /**
  631. * Removes the earliest node and then find the new <earliest_spoke_>
  632. *
  633. * @return The earliest timer node.
  634. */
  635. template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
  636. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::remove_first (void)
  637. {
  638. ACE_TRACE ("ACE_Timer_Wheel_T::remove_first");
  639. return remove_first_expired (ACE_Time_Value::max_time);
  640. }
  641. template <class TYPE, class FUNCTOR, class ACE_LOCK> void
  642. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::unlink (ACE_Timer_Node_T<TYPE>* n)
  643. {
  644. ACE_TRACE ("ACE_Timer_Wheel_T::unlink");
  645. --timer_count_;
  646. n->get_prev ()->set_next (n->get_next ());
  647. n->get_next ()->set_prev (n->get_prev ());
  648. n->set_prev (0);
  649. n->set_next (0);
  650. }
  651. template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
  652. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::remove_first_expired (const ACE_Time_Value& now)
  653. {
  654. ACE_Timer_Node_T<TYPE>* n = this->get_first ();
  655. if (n != 0 && n->get_timer_value() <= now)
  656. {
  657. this->unlink (n);
  658. this->recalc_earliest (n->get_timer_value ());
  659. return n;
  660. }
  661. return 0;
  662. }
  663. /**
  664. * Returns the earliest node without removing it
  665. *
  666. * @return The earliest timer node.
  667. */
  668. template <class TYPE, class FUNCTOR, class ACE_LOCK>
  669. ACE_Timer_Node_T<TYPE>*
  670. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::get_first (void)
  671. {
  672. ACE_TRACE ("ACE_Timer_Wheel_T::get_first");
  673. return this->get_first_i ();
  674. }
  675. template <class TYPE, class FUNCTOR, class ACE_LOCK>
  676. ACE_Timer_Node_T<TYPE>*
  677. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::get_first_i (void) const
  678. {
  679. ACE_Timer_Node_T<TYPE>* root = this->spokes_[this->earliest_spoke_];
  680. ACE_Timer_Node_T<TYPE>* first = root->get_next ();
  681. if (first != root)
  682. return first;
  683. return 0;
  684. }
  685. /**
  686. * @return The iterator
  687. */
  688. template <class TYPE, class FUNCTOR, class ACE_LOCK>
  689. ACE_Timer_Queue_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>&
  690. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::iter (void)
  691. {
  692. this->iterator_->first ();
  693. return *this->iterator_;
  694. }
  695. /**
  696. * Dummy version of expire to get rid of warnings in Sun CC 4.2
  697. * Just call the expire of the base class.
  698. */
  699. template <class TYPE, class FUNCTOR, class ACE_LOCK> int
  700. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::expire ()
  701. {
  702. return ACE_Timer_Queue_T<TYPE,FUNCTOR,ACE_LOCK>::expire ();
  703. }
  704. /**
  705. * This is a specialized version of expire that is more suited for the
  706. * internal data representation.
  707. *
  708. * @param cur_time The time to expire timers up to.
  709. *
  710. * @return Number of timers expired
  711. */
  712. template <class TYPE, class FUNCTOR, class ACE_LOCK> int
  713. ACE_Timer_Wheel_T<TYPE, FUNCTOR, ACE_LOCK>::expire (const ACE_Time_Value& cur_time)
  714. {
  715. ACE_TRACE ("ACE_Timer_Wheel_T::expire");
  716. int expcount = 0;
  717. ACE_MT (ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->mutex_, -1));
  718. ACE_Timer_Node_T<TYPE>* n = this->remove_first_expired (cur_time);
  719. while (n != 0)
  720. {
  721. ++expcount;
  722. //ACE_ERROR((LM_ERROR, "Expiring %x\n", (long) n));
  723. ACE_Timer_Node_Dispatch_Info_T<TYPE> info;
  724. // Get the dispatch info
  725. n->get_dispatch_info (info);
  726. if (n->get_interval () > ACE_Time_Value::zero)
  727. {
  728. // Make sure that we skip past values that have already
  729. // "expired".
  730. this->recompute_next_abs_interval_time (n, cur_time);
  731. this->reschedule (n);
  732. }
  733. else
  734. {
  735. this->free_node (n);
  736. }
  737. const void *upcall_act = 0;
  738. this->preinvoke (info, cur_time, upcall_act);
  739. this->upcall (info, cur_time);
  740. this->postinvoke (info, cur_time, upcall_act);
  741. n = this->remove_first_expired (cur_time);
  742. }
  743. return expcount;
  744. }
  745. ///////////////////////////////////////////////////////////////////////////
  746. // ACE_Timer_Wheel_Iterator_T
  747. /**
  748. * Just initializes the iterator with a ACE_Timer_Wheel_T and then calls
  749. * first() to initialize the rest of itself.
  750. *
  751. * @param wheel A reference for a timer queue to iterate over
  752. */
  753. template <class TYPE, class FUNCTOR, class ACE_LOCK>
  754. ACE_Timer_Wheel_Iterator_T<TYPE,FUNCTOR,ACE_LOCK>::ACE_Timer_Wheel_Iterator_T
  755. (Wheel& wheel)
  756. : timer_wheel_ (wheel)
  757. {
  758. this->first();
  759. }
  760. /**
  761. * Destructor, at this level does nothing.
  762. */
  763. template <class TYPE, class FUNCTOR, class ACE_LOCK>
  764. ACE_Timer_Wheel_Iterator_T<TYPE,
  765. FUNCTOR,
  766. ACE_LOCK>::~ACE_Timer_Wheel_Iterator_T (void)
  767. {
  768. }
  769. /**
  770. * Positions the iterator at the first position in the timing wheel
  771. * that contains something. spoke_ will be set to the spoke position of
  772. * this entry and current_node_ will point to the first entry in that spoke.
  773. *
  774. * If the wheel is empty, spoke_ will be equal timer_wheel_.spoke_count_ and
  775. * current_node_ would be 0.
  776. */
  777. template <class TYPE, class FUNCTOR, class ACE_LOCK> void
  778. ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::first (void)
  779. {
  780. this->goto_next(0);
  781. }
  782. /**
  783. * Positions the iterator at the next node.
  784. */
  785. template <class TYPE, class FUNCTOR, class ACE_LOCK> void
  786. ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::next (void)
  787. {
  788. if (this->isdone())
  789. return;
  790. ACE_Timer_Node_T<TYPE>* n = this->current_node_->get_next ();
  791. ACE_Timer_Node_T<TYPE>* root = this->timer_wheel_.spokes_[this->spoke_];
  792. if (n == root)
  793. this->goto_next (this->spoke_ + 1);
  794. else
  795. this->current_node_ = n;
  796. }
  797. /// Helper class for common functionality of next() and first()
  798. template <class TYPE, class FUNCTOR, class ACE_LOCK> void
  799. ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::goto_next (u_int start_spoke)
  800. {
  801. // Find the first non-empty entry.
  802. u_int sc = this->timer_wheel_.spoke_count_;
  803. for (u_int i = start_spoke; i < sc; ++i)
  804. {
  805. ACE_Timer_Node_T<TYPE>* root = this->timer_wheel_.spokes_[i];
  806. ACE_Timer_Node_T<TYPE>* n = root->get_next ();
  807. if (n != root)
  808. {
  809. this->spoke_ = i;
  810. this->current_node_ = n;
  811. return;
  812. }
  813. }
  814. // empty
  815. this->spoke_ = sc;
  816. this->current_node_ = 0;
  817. }
  818. /**
  819. * @return True when we there aren't any more items (when current_node_ == 0)
  820. */
  821. template <class TYPE, class FUNCTOR, class ACE_LOCK> bool
  822. ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::isdone (void) const
  823. {
  824. return this->current_node_ == 0;
  825. }
  826. /**
  827. * @return The node at the current spokeition in the sequence or 0 if the wheel
  828. * is empty
  829. */
  830. template <class TYPE, class FUNCTOR, class ACE_LOCK> ACE_Timer_Node_T<TYPE> *
  831. ACE_Timer_Wheel_Iterator_T<TYPE, FUNCTOR, ACE_LOCK>::item (void)
  832. {
  833. return this->current_node_;
  834. }
  835. ACE_END_VERSIONED_NAMESPACE_DECL
  836. #endif /* ACE_TIMER_WHEEL_T_CPP */