Line data Source code
1 : /*
2 : Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
3 :
4 : This file is part of libzmq, the ZeroMQ core engine in C++.
5 :
6 : libzmq is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU Lesser General Public License (LGPL) as published
8 : by the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : As a special exception, the Contributors give you permission to link
12 : this library with independent modules to produce an executable,
13 : regardless of the license terms of these independent modules, and to
14 : copy and distribute the resulting executable under terms of your choice,
15 : provided that you also meet, for each linked independent module, the
16 : terms and conditions of the license of that module. An independent
17 : module is a module which is not derived from or based on this library.
18 : If you modify this library, you must extend this exception to your
19 : version of the library.
20 :
21 : libzmq is distributed in the hope that it will be useful, but WITHOUT
22 : ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24 : License for more details.
25 :
26 : You should have received a copy of the GNU Lesser General Public License
27 : along with this program. If not, see <http://www.gnu.org/licenses/>.
28 : */
29 :
30 : #include "precompiled.hpp"
31 : #include "timers.hpp"
32 : #include "err.hpp"
33 :
34 3 : zmq::timers_t::timers_t () :
35 : tag (0xCAFEDADA),
36 6 : next_timer_id (0)
37 : {
38 :
39 3 : }
40 :
41 12 : zmq::timers_t::~timers_t ()
42 : {
43 : // Mark the timers as dead
44 3 : tag = 0xdeadbeef;
45 3 : }
46 :
47 66 : bool zmq::timers_t::check_tag ()
48 : {
49 66 : return tag == 0xCAFEDADA;
50 : }
51 :
52 3 : int zmq::timers_t::add (size_t interval_, timers_timer_fn handler_, void* arg_)
53 : {
54 3 : uint64_t when = clock.now_ms() + interval_;
55 3 : timer_t timer = {++next_timer_id, interval_, handler_, arg_};
56 9 : timers.insert (timersmap_t::value_type (when, timer));
57 :
58 3 : return timer.timer_id;
59 : }
60 :
61 3 : int zmq::timers_t::cancel (int timer_id_)
62 : {
63 6 : cancelled_timers_t::iterator it = cancelled_timers.find (timer_id_);
64 :
65 6 : if (it != cancelled_timers.end ()) {
66 0 : errno = EINVAL;
67 0 : return -1;
68 : }
69 :
70 3 : cancelled_timers.insert (timer_id_);
71 :
72 3 : return 0;
73 : }
74 :
75 3 : int zmq::timers_t::set_interval (int timer_id_, size_t interval_)
76 : {
77 12 : for (timersmap_t::iterator it = timers.begin (); it != timers.end (); ++it) {
78 3 : if (it->second.timer_id == timer_id_) {
79 3 : timer_t timer = it->second;
80 3 : timer.interval = interval_;
81 3 : uint64_t when = clock.now_ms() + interval_;
82 3 : timers.erase (it);
83 9 : timers.insert (timersmap_t::value_type (when, timer));
84 :
85 : return 0;
86 : }
87 : }
88 :
89 0 : errno = EINVAL;
90 0 : return -1;
91 : }
92 :
93 3 : int zmq::timers_t::reset (int timer_id_) {
94 12 : for (timersmap_t::iterator it = timers.begin (); it != timers.end (); ++it) {
95 3 : if (it->second.timer_id == timer_id_) {
96 3 : timer_t timer = it->second;
97 3 : uint64_t when = clock.now_ms() + timer.interval;
98 3 : timers.erase (it);
99 9 : timers.insert (timersmap_t::value_type (when, timer));
100 :
101 : return 0;
102 : }
103 : }
104 :
105 0 : errno = EINVAL;
106 0 : return -1;
107 : }
108 :
109 27 : long zmq::timers_t::timeout ()
110 : {
111 54 : timersmap_t::iterator it = timers.begin ();
112 :
113 27 : uint64_t now = clock.now_ms();
114 :
115 54 : while (it != timers.end ()) {
116 54 : cancelled_timers_t::iterator cancelled_it = cancelled_timers.find (it->second.timer_id);
117 :
118 : // Live timer, lets return the timeout
119 54 : if (cancelled_it == cancelled_timers.end ()) {
120 27 : if (it->first > now)
121 18 : return (long) (it->first - now);
122 : else
123 : return 0;
124 : }
125 :
126 : // Let's remove it from the begining of the list
127 0 : timersmap_t::iterator old = it;
128 : ++it;
129 0 : timers.erase (old);
130 0 : cancelled_timers.erase (cancelled_it);
131 : }
132 :
133 : // Wait forever as no timers are alive
134 : return -1;
135 : }
136 :
137 24 : int zmq::timers_t::execute ()
138 : {
139 48 : timersmap_t::iterator it = timers.begin ();
140 :
141 24 : uint64_t now = clock.now_ms();
142 :
143 72 : while (it != timers.end ()) {
144 48 : cancelled_timers_t::iterator cancelled_it = cancelled_timers.find (it->second.timer_id);
145 :
146 : // Dead timer, lets remove it and continue
147 48 : if (cancelled_it != cancelled_timers.end ()) {
148 3 : timersmap_t::iterator old = it;
149 : ++it;
150 3 : timers.erase (old);
151 3 : cancelled_timers.erase (cancelled_it);
152 : continue;
153 : }
154 :
155 : // Map is ordered, if we have to wait for current timer we can stop.
156 21 : if (it->first > now)
157 : break;
158 :
159 9 : timer_t timer = it->second;
160 :
161 9 : timer.handler (timer.timer_id, timer.arg);
162 :
163 9 : timersmap_t::iterator old = it;
164 : ++it;
165 9 : timers.erase (old);
166 27 : timers.insert (timersmap_t::value_type (now + timer.interval, timer));
167 : }
168 :
169 24 : return 0;
170 : }
|