@@ -90,7 +90,8 @@ TimerQueue::TimerQueue(EventLoop* loop)
90
90
: loop_(loop),
91
91
timerfd_(createTimerfd()),
92
92
timerfdChannel_(loop, timerfd_),
93
- timers_()
93
+ timers_(),
94
+ callingExpiredTimers_(false )
94
95
{
95
96
timerfdChannel_.setReadCallback (
96
97
boost::bind (&TimerQueue::handleRead, this ));
@@ -119,6 +120,12 @@ TimerId TimerQueue::addTimer(const TimerCallback& cb,
119
120
return TimerId (timer, timer->sequence ());
120
121
}
121
122
123
+ void TimerQueue::cancel (TimerId timerId)
124
+ {
125
+ loop_->runInLoop (
126
+ boost::bind (&TimerQueue::cancelInLoop, this , timerId));
127
+ }
128
+
122
129
void TimerQueue::scheduleInLoop (Timer* timer)
123
130
{
124
131
loop_->assertInLoopThread ();
@@ -130,6 +137,26 @@ void TimerQueue::scheduleInLoop(Timer* timer)
130
137
}
131
138
}
132
139
140
+ void TimerQueue::cancelInLoop (TimerId timerId)
141
+ {
142
+ loop_->assertInLoopThread ();
143
+ assert (timers_.size () == activeTimers_.size ());
144
+ ActiveTimer timer (timerId.timer_ , timerId.seq_ );
145
+ ActiveTimerSet::iterator it = activeTimers_.find (timer);
146
+ if (it != activeTimers_.end ())
147
+ {
148
+ size_t n = timers_.erase (Entry (it->first ->expiration (), it->first ));
149
+ assert (n == 1 ); (void )n;
150
+ delete it->first ; // FIXME: no delete please
151
+ activeTimers_.erase (it);
152
+ }
153
+ else if (callingExpiredTimers_)
154
+ {
155
+ cancelingTimers_.insert (timer);
156
+ }
157
+ assert (timers_.size () == activeTimers_.size ());
158
+ }
159
+
133
160
void TimerQueue::handleRead ()
134
161
{
135
162
loop_->assertInLoopThread ();
@@ -138,25 +165,38 @@ void TimerQueue::handleRead()
138
165
139
166
std::vector<Entry> expired = getExpired (now);
140
167
168
+ callingExpiredTimers_ = true ;
169
+ cancelingTimers_.clear ();
141
170
// safe to callback outside critical section
142
171
for (std::vector<Entry>::iterator it = expired.begin ();
143
172
it != expired.end (); ++it)
144
173
{
145
174
it->second ->run ();
146
175
}
176
+ callingExpiredTimers_ = false ;
147
177
148
178
reset (expired, now);
149
179
}
150
180
151
181
std::vector<TimerQueue::Entry> TimerQueue::getExpired (Timestamp now)
152
182
{
183
+ assert (timers_.size () == activeTimers_.size ());
153
184
std::vector<Entry> expired;
154
- Entry sentry = std::make_pair (now, reinterpret_cast <Timer*>(UINTPTR_MAX));
155
- TimerList::iterator it = timers_.lower_bound (sentry);
156
- assert (it == timers_.end () || now < it ->first );
157
- std::copy (timers_.begin (), it , back_inserter (expired));
158
- timers_.erase (timers_.begin (), it );
185
+ Entry sentry (now, reinterpret_cast <Timer*>(UINTPTR_MAX));
186
+ TimerList::iterator end = timers_.lower_bound (sentry);
187
+ assert (end == timers_.end () || now < end ->first );
188
+ std::copy (timers_.begin (), end , back_inserter (expired));
189
+ timers_.erase (timers_.begin (), end );
159
190
191
+ for (std::vector<Entry>::iterator it = expired.begin ();
192
+ it != expired.end (); ++it)
193
+ {
194
+ ActiveTimer timer (it->second , it->second ->sequence ());
195
+ size_t n = activeTimers_.erase (timer);
196
+ assert (n == 1 ); (void )n;
197
+ }
198
+
199
+ assert (timers_.size () == activeTimers_.size ());
160
200
return expired;
161
201
}
162
202
@@ -167,15 +207,17 @@ void TimerQueue::reset(const std::vector<Entry>& expired, Timestamp now)
167
207
for (std::vector<Entry>::const_iterator it = expired.begin ();
168
208
it != expired.end (); ++it)
169
209
{
170
- if (it->second ->repeat ())
210
+ ActiveTimer timer (it->second , it->second ->sequence ());
211
+ if (it->second ->repeat ()
212
+ && cancelingTimers_.find (timer) == cancelingTimers_.end ())
171
213
{
172
214
it->second ->restart (now);
173
215
insert (it->second );
174
216
}
175
217
else
176
218
{
177
219
// FIXME move to a free list
178
- delete it->second ;
220
+ delete it->second ; // FIXME: no delete please
179
221
}
180
222
}
181
223
@@ -192,15 +234,27 @@ void TimerQueue::reset(const std::vector<Entry>& expired, Timestamp now)
192
234
193
235
bool TimerQueue::insert (Timer* timer)
194
236
{
237
+ loop_->assertInLoopThread ();
238
+ assert (timers_.size () == activeTimers_.size ());
195
239
bool earliestChanged = false ;
196
240
Timestamp when = timer->expiration ();
197
241
TimerList::iterator it = timers_.begin ();
198
242
if (it == timers_.end () || when < it->first )
199
243
{
200
244
earliestChanged = true ;
201
245
}
202
- std::pair<TimerList::iterator, bool > result = timers_.insert (std::make_pair (when, timer));
203
- assert (result.second ); (void )result;
246
+ {
247
+ std::pair<TimerList::iterator, bool > result
248
+ = timers_.insert (Entry (when, timer));
249
+ assert (result.second ); (void )result;
250
+ }
251
+ {
252
+ std::pair<ActiveTimerSet::iterator, bool > result
253
+ = activeTimers_.insert (ActiveTimer (timer, timer->sequence ()));
254
+ assert (result.second ); (void )result;
255
+ }
256
+
257
+ assert (timers_.size () == activeTimers_.size ());
204
258
return earliestChanged;
205
259
}
206
260
0 commit comments