Skip to content

Commit 374acaa

Browse files
authored
Use the std::chrono::steady_clock for timers (#60)
1 parent 5c06e06 commit 374acaa

File tree

6 files changed

+83
-54
lines changed

6 files changed

+83
-54
lines changed

trantor/net/EventLoop.cc

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,11 +219,23 @@ void EventLoop::queueInLoop(Func &&cb)
219219

220220
TimerId EventLoop::runAt(const Date &time, const Func &cb)
221221
{
222-
return timerQueue_->addTimer(cb, time, 0);
222+
auto microSeconds =
223+
time.microSecondsSinceEpoch() - Date::now().microSecondsSinceEpoch();
224+
std::chrono::steady_clock::time_point tp =
225+
std::chrono::steady_clock::now() +
226+
std::chrono::microseconds(microSeconds);
227+
return timerQueue_->addTimer(cb, tp, std::chrono::microseconds(0));
223228
}
224229
TimerId EventLoop::runAt(const Date &time, Func &&cb)
225230
{
226-
return timerQueue_->addTimer(std::move(cb), time, 0);
231+
auto microSeconds =
232+
time.microSecondsSinceEpoch() - Date::now().microSecondsSinceEpoch();
233+
std::chrono::steady_clock::time_point tp =
234+
std::chrono::steady_clock::now() +
235+
std::chrono::microseconds(microSeconds);
236+
return timerQueue_->addTimer(std::move(cb),
237+
tp,
238+
std::chrono::microseconds(0));
227239
}
228240
TimerId EventLoop::runAfter(double delay, const Func &cb)
229241
{
@@ -235,13 +247,17 @@ TimerId EventLoop::runAfter(double delay, Func &&cb)
235247
}
236248
TimerId EventLoop::runEvery(double interval, const Func &cb)
237249
{
238-
return timerQueue_->addTimer(cb, Date::date().after(interval), interval);
250+
std::chrono::microseconds dur(
251+
static_cast<std::chrono::microseconds::rep>(interval * 1000000));
252+
auto tp = std::chrono::steady_clock::now() + dur;
253+
return timerQueue_->addTimer(cb, tp, dur);
239254
}
240255
TimerId EventLoop::runEvery(double interval, Func &&cb)
241256
{
242-
return timerQueue_->addTimer(std::move(cb),
243-
Date::date().after(interval),
244-
interval);
257+
std::chrono::microseconds dur(
258+
static_cast<std::chrono::microseconds::rep>(interval * 1000000));
259+
auto tp = std::chrono::steady_clock::now() + dur;
260+
return timerQueue_->addTimer(std::move(cb), tp, dur);
245261
}
246262
void EventLoop::invalidateTimer(TimerId id)
247263
{

trantor/net/inner/Timer.cc

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,23 @@
1919
namespace trantor
2020
{
2121
std::atomic<TimerId> Timer::timersCreated_ = ATOMIC_VAR_INIT(InvalidTimerId);
22-
Timer::Timer(const TimerCallback &cb, const Date &when, double interval)
22+
Timer::Timer(const TimerCallback &cb,
23+
const TimePoint &when,
24+
const TimeInterval &interval)
2325
: callback_(cb),
2426
when_(when),
2527
interval_(interval),
26-
repeat_(interval > 0.0),
28+
repeat_(interval.count() > 0),
2729
id_(++timersCreated_)
2830
{
2931
}
30-
Timer::Timer(TimerCallback &&cb, const Date &when, double interval)
32+
Timer::Timer(TimerCallback &&cb,
33+
const TimePoint &when,
34+
const TimeInterval &interval)
3135
: callback_(std::move(cb)),
3236
when_(when),
3337
interval_(interval),
34-
repeat_(interval > 0.0),
38+
repeat_(interval.count() > 0),
3539
id_(++timersCreated_)
3640
{
3741
// LOG_TRACE<<"Timer move contrustor";
@@ -40,14 +44,14 @@ void Timer::run() const
4044
{
4145
callback_();
4246
}
43-
void Timer::restart(const Date &now)
47+
void Timer::restart(const TimePoint &now)
4448
{
4549
if (repeat_)
4650
{
47-
when_ = now.after(interval_);
51+
when_ = now + interval_;
4852
}
4953
else
50-
when_ = Date();
54+
when_ = std::chrono::steady_clock::now();
5155
}
5256
bool Timer::operator<(const Timer &t) const
5357
{

trantor/net/inner/Timer.h

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,31 +14,36 @@
1414

1515
#pragma once
1616

17-
#include <trantor/utils/Date.h>
1817
#include <trantor/utils/NonCopyable.h>
1918
#include <trantor/net/callbacks.h>
2019
#include <functional>
2120
#include <atomic>
2221
#include <iostream>
22+
#include <chrono>
2323

2424
namespace trantor
2525
{
2626
using TimerId = uint64_t;
27-
27+
using TimePoint = std::chrono::steady_clock::time_point;
28+
using TimeInterval = std::chrono::microseconds;
2829
class Timer : public NonCopyable
2930
{
3031
public:
31-
Timer(const TimerCallback &cb, const Date &when, double interval);
32-
Timer(TimerCallback &&cb, const Date &when, double interval);
32+
Timer(const TimerCallback &cb,
33+
const TimePoint &when,
34+
const TimeInterval &interval);
35+
Timer(TimerCallback &&cb,
36+
const TimePoint &when,
37+
const TimeInterval &interval);
3338
~Timer()
3439
{
3540
// std::cout<<"Timer unconstract!"<<std::endl;
3641
}
3742
void run() const;
38-
void restart(const Date &now);
43+
void restart(const TimePoint &now);
3944
bool operator<(const Timer &t) const;
4045
bool operator>(const Timer &t) const;
41-
const Date &when() const
46+
const TimePoint &when() const
4247
{
4348
return when_;
4449
}
@@ -53,8 +58,8 @@ class Timer : public NonCopyable
5358

5459
private:
5560
TimerCallback callback_;
56-
Date when_;
57-
const double interval_;
61+
TimePoint when_;
62+
const TimeInterval interval_;
5863
const bool repeat_;
5964
const TimerId id_;
6065
static std::atomic<TimerId> timersCreated_;

trantor/net/inner/TimerQueue.cc

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,21 @@ int createTimerfd()
3535
return timerfd;
3636
}
3737

38-
struct timespec howMuchTimeFromNow(const Date &when)
38+
struct timespec howMuchTimeFromNow(const TimePoint &when)
3939
{
40-
int64_t microseconds =
41-
when.microSecondsSinceEpoch() - Date::date().microSecondsSinceEpoch();
42-
if (microseconds < 100)
40+
auto microSeconds = std::chrono::duration_cast<std::chrono::microseconds>(
41+
when - std::chrono::steady_clock::now())
42+
.count();
43+
if (microSeconds < 100)
4344
{
44-
microseconds = 100;
45+
microSeconds = 100;
4546
}
4647
struct timespec ts;
47-
ts.tv_sec = static_cast<time_t>(microseconds / 1000000);
48-
ts.tv_nsec = static_cast<long>((microseconds % 1000000) * 1000);
48+
ts.tv_sec = static_cast<time_t>(microSeconds / 1000000);
49+
ts.tv_nsec = static_cast<long>((microSeconds % 1000000) * 1000);
4950
return ts;
5051
}
51-
void resetTimerfd(int timerfd, const Date &expiration)
52+
void resetTimerfd(int timerfd, const TimePoint &expiration)
5253
{
5354
// wake up loop by timerfd_settime()
5455
struct itimerspec newValue;
@@ -62,12 +63,10 @@ void resetTimerfd(int timerfd, const Date &expiration)
6263
// LOG_SYSERR << "timerfd_settime()";
6364
}
6465
}
65-
void readTimerfd(int timerfd, const Date &now)
66+
void readTimerfd(int timerfd, const TimePoint &now)
6667
{
6768
uint64_t howmany;
6869
ssize_t n = ::read(timerfd, &howmany, sizeof howmany);
69-
LOG_TRACE << "TimerQueue::handleRead() " << howmany << " at "
70-
<< now.toFormattedString(true);
7170
if (n != sizeof howmany)
7271
{
7372
LOG_ERROR << "TimerQueue::handleRead() reads " << n
@@ -78,7 +77,7 @@ void readTimerfd(int timerfd, const Date &now)
7877
void TimerQueue::handleRead()
7978
{
8079
loop_->assertInLoopThread();
81-
const Date now = Date::date();
80+
const auto now = std::chrono::steady_clock::now();
8281
readTimerfd(timerfd_, now);
8382

8483
std::vector<TimerPtr> expired = getExpired(now);
@@ -98,20 +97,21 @@ void TimerQueue::handleRead()
9897
reset(expired, now);
9998
}
10099
#else
101-
int howMuchTimeFromNow(const Date &when)
100+
int64_t howMuchTimeFromNow(const TimePoint &when)
102101
{
103-
int64_t microSeconds =
104-
when.microSecondsSinceEpoch() - Date::date().microSecondsSinceEpoch();
102+
auto microSeconds = std::chrono::duration_cast<std::chrono::microseconds>(
103+
when - std::chrono::steady_clock::now())
104+
.count();
105105
if (microSeconds < 1000)
106106
{
107107
microSeconds = 1000;
108108
}
109-
return static_cast<int>(microSeconds / 1000);
109+
return microSeconds / 1000;
110110
}
111111
void TimerQueue::processTimers()
112112
{
113113
loop_->assertInLoopThread();
114-
const Date now = Date::date();
114+
const auto now = std::chrono::steady_clock::now();
115115

116116
std::vector<TimerPtr> expired = getExpired(now);
117117

@@ -162,7 +162,7 @@ void TimerQueue::reset()
162162
timerfdChannelPtr_->enableReading();
163163
if (!timers_.empty())
164164
{
165-
const Date nextExpire = timers_.top()->when();
165+
const auto nextExpire = timers_.top()->when();
166166
resetTimerfd(timerfd_, nextExpire);
167167
}
168168
});
@@ -182,8 +182,8 @@ TimerQueue::~TimerQueue()
182182
}
183183

184184
TimerId TimerQueue::addTimer(const TimerCallback &cb,
185-
const Date &when,
186-
double interval)
185+
const TimePoint &when,
186+
const TimeInterval &interval)
187187
{
188188
std::shared_ptr<Timer> timerPtr =
189189
std::make_shared<Timer>(cb, when, interval);
@@ -192,8 +192,8 @@ TimerId TimerQueue::addTimer(const TimerCallback &cb,
192192
return timerPtr->id();
193193
}
194194
TimerId TimerQueue::addTimer(TimerCallback &&cb,
195-
const Date &when,
196-
double interval)
195+
const TimePoint &when,
196+
const TimeInterval &interval)
197197
{
198198
std::shared_ptr<Timer> timerPtr =
199199
std::make_shared<Timer>(std::move(cb), when, interval);
@@ -233,7 +233,7 @@ bool TimerQueue::insert(const TimerPtr &timerPtr)
233233
return earliestChanged;
234234
}
235235
#ifndef __linux__
236-
int TimerQueue::getTimeout() const
236+
int64_t TimerQueue::getTimeout() const
237237
{
238238
loop_->assertInLoopThread();
239239
if (timers_.empty())
@@ -247,7 +247,7 @@ int TimerQueue::getTimeout() const
247247
}
248248
#endif
249249

250-
std::vector<TimerPtr> TimerQueue::getExpired(const Date &now)
250+
std::vector<TimerPtr> TimerQueue::getExpired(const TimePoint &now)
251251
{
252252
std::vector<TimerPtr> expired;
253253
while (!timers_.empty())
@@ -262,7 +262,8 @@ std::vector<TimerPtr> TimerQueue::getExpired(const Date &now)
262262
}
263263
return expired;
264264
}
265-
void TimerQueue::reset(const std::vector<TimerPtr> &expired, const Date &now)
265+
void TimerQueue::reset(const std::vector<TimerPtr> &expired,
266+
const TimePoint &now)
266267
{
267268
loop_->assertInLoopThread();
268269
for (auto const &timerPtr : expired)
@@ -277,7 +278,7 @@ void TimerQueue::reset(const std::vector<TimerPtr> &expired, const Date &now)
277278
#ifdef __linux__
278279
if (!timers_.empty())
279280
{
280-
const Date nextExpire = timers_.top()->when();
281+
const auto nextExpire = timers_.top()->when();
281282
resetTimerfd(timerfd_, nextExpire);
282283
}
283284
#endif

trantor/net/inner/TimerQueue.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
#include <trantor/utils/NonCopyable.h>
1818
#include <trantor/net/callbacks.h>
19-
#include <trantor/utils/Date.h>
2019
#include "Timer.h"
2120
#include <queue>
2221
#include <memory>
@@ -42,15 +41,17 @@ class TimerQueue : NonCopyable
4241
explicit TimerQueue(EventLoop *loop);
4342
~TimerQueue();
4443
TimerId addTimer(const TimerCallback &cb,
45-
const Date &when,
46-
double interval);
47-
TimerId addTimer(TimerCallback &&cb, const Date &when, double interval);
44+
const TimePoint &when,
45+
const TimeInterval &interval);
46+
TimerId addTimer(TimerCallback &&cb,
47+
const TimePoint &when,
48+
const TimeInterval &interval);
4849
void addTimerInLoop(const TimerPtr &timer);
4950
void invalidateTimer(TimerId id);
5051
#ifdef __linux__
5152
void reset();
5253
#else
53-
int getTimeout() const;
54+
int64_t getTimeout() const;
5455
void processTimers();
5556
#endif
5657
protected:
@@ -65,8 +66,8 @@ class TimerQueue : NonCopyable
6566
bool callingExpiredTimers_;
6667
bool insert(const TimerPtr &timePtr);
6768
std::vector<TimerPtr> getExpired();
68-
void reset(const std::vector<TimerPtr> &expired, const Date &now);
69-
std::vector<TimerPtr> getExpired(const Date &now);
69+
void reset(const std::vector<TimerPtr> &expired, const TimePoint &now);
70+
std::vector<TimerPtr> getExpired(const TimePoint &now);
7071

7172
private:
7273
std::unordered_set<uint64_t> timerIdSet_;

trantor/tests/TimerTest.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,7 @@ int main()
2626
loop.runAfter(5, []() { std::cout << "runAt 5s later" << std::endl; });
2727
loop.runEvery(1, []() { std::cout << "runEvery 1s" << std::endl; });
2828
loop.runAfter(4, []() { std::cout << "runAfter 4s" << std::endl; });
29+
loop.runAfter(10min,
30+
[]() { std::cout << "*********** run after 10 min\n"; });
2931
loop.loop();
3032
}

0 commit comments

Comments
 (0)