Apollo 10.0
自动驾驶开放平台
timer.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2018 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
17#include "cyber/timer/timer.h"
18
19#include <cmath>
20
22
23namespace apollo {
24namespace cyber {
25
26namespace {
27std::atomic<uint64_t> global_timer_id = {0};
28uint64_t GenerateTimerId() { return global_timer_id.fetch_add(1); }
29} // namespace
30
32 timing_wheel_ = TimingWheel::Instance();
33 timer_id_ = GenerateTimerId();
34}
35
36Timer::Timer(TimerOption opt) : timer_opt_(opt) {
37 timing_wheel_ = TimingWheel::Instance();
38 timer_id_ = GenerateTimerId();
39}
40
41Timer::Timer(uint32_t period, std::function<void()> callback, bool oneshot) {
42 timing_wheel_ = TimingWheel::Instance();
43 timer_id_ = GenerateTimerId();
44 timer_opt_.period = period;
45 timer_opt_.callback = callback;
46 timer_opt_.oneshot = oneshot;
47}
48
49void Timer::SetTimerOption(TimerOption opt) { timer_opt_ = opt; }
50
51bool Timer::InitTimerTask() {
52 if (timer_opt_.period == 0) {
53 AERROR << "Max interval must great than 0";
54 return false;
55 }
56
57 if (timer_opt_.period >= TIMER_MAX_INTERVAL_MS) {
58 AERROR << "Max interval must less than " << TIMER_MAX_INTERVAL_MS;
59 return false;
60 }
61
62 task_.reset(new TimerTask(timer_id_));
63 task_->interval_ms = timer_opt_.period;
64 task_->next_fire_duration_ms = task_->interval_ms;
65 if (timer_opt_.oneshot) {
66 std::weak_ptr<TimerTask> task_weak_ptr = task_;
67 task_->callback = [callback = this->timer_opt_.callback, task_weak_ptr]() {
68 auto task = task_weak_ptr.lock();
69 if (task) {
70 std::lock_guard<std::mutex> lg(task->mutex);
71 callback();
72 }
73 };
74 } else {
75 std::weak_ptr<TimerTask> task_weak_ptr = task_;
76 task_->callback = [callback = this->timer_opt_.callback, task_weak_ptr]() {
77 auto task = task_weak_ptr.lock();
78 if (!task) {
79 return;
80 }
81 std::lock_guard<std::mutex> lg(task->mutex);
82 auto start = Time::MonoTime().ToNanosecond();
83 callback();
84 auto end = Time::MonoTime().ToNanosecond();
85 uint64_t execute_time_ns = end - start;
86 uint64_t execute_time_ms =
87#if defined(__aarch64__)
88 ::llround(static_cast<double>(execute_time_ns) / 1e6);
89#else
90 std::llround(static_cast<double>(execute_time_ns) / 1e6);
91#endif
92 if (task->last_execute_time_ns == 0) {
93 task->last_execute_time_ns = start;
94 } else {
95 task->accumulated_error_ns +=
96 start - task->last_execute_time_ns - task->interval_ms * 1000000;
97 }
98 ADEBUG << "start: " << start << "\t last: " << task->last_execute_time_ns
99 << "\t execut time:" << execute_time_ms
100 << "\t accumulated_error_ns: " << task->accumulated_error_ns;
101 task->last_execute_time_ns = start;
102 if (execute_time_ms >= task->interval_ms) {
103 task->next_fire_duration_ms = TIMER_RESOLUTION_MS;
104 } else {
105#if defined(__aarch64__)
106 int64_t accumulated_error_ms = ::llround(
107#else
108 int64_t accumulated_error_ms = std::llround(
109#endif
110 static_cast<double>(task->accumulated_error_ns) / 1e6);
111 if (static_cast<int64_t>(task->interval_ms - execute_time_ms -
112 TIMER_RESOLUTION_MS) >= accumulated_error_ms) {
113 task->next_fire_duration_ms =
114 task->interval_ms - execute_time_ms - accumulated_error_ms;
115 } else {
116 task->next_fire_duration_ms = TIMER_RESOLUTION_MS;
117 }
118 ADEBUG << "error ms: " << accumulated_error_ms
119 << " execute time: " << execute_time_ms
120 << " next fire: " << task->next_fire_duration_ms
121 << " error ns: " << task->accumulated_error_ns;
122 }
123 TimingWheel::Instance()->AddTask(task);
124 };
125 }
126 return true;
127}
128
130 if (!common::GlobalData::Instance()->IsRealityMode()) {
131 return;
132 }
133
134 if (!started_.exchange(true)) {
135 if (InitTimerTask()) {
136 timing_wheel_->AddTask(task_);
137 AINFO << "start timer [" << task_->timer_id_ << "]";
138 }
139 }
140}
141
143 if (started_.exchange(false) && task_) {
144 AINFO << "stop timer, the timer_id: " << timer_id_;
145 // using a shared pointer to hold task_->mutex before task_ reset
146 auto tmp_task = task_;
147 {
148 std::lock_guard<std::mutex> lg(tmp_task->mutex);
149 task_.reset();
150 }
151 }
152}
153
155 if (task_) {
156 Stop();
157 }
158}
159
160} // namespace cyber
161} // namespace apollo
static Time MonoTime()
Definition time.cc:67
uint64_t ToNanosecond() const
convert time to nanosecond.
Definition time.cc:83
void Stop()
Stop the timer
Definition timer.cc:142
void SetTimerOption(TimerOption opt)
Set the Timer Option object
Definition timer.cc:49
void Start()
Start the timer
Definition timer.cc:129
void AddTask(const std::shared_ptr< TimerTask > &task)
#define ADEBUG
Definition log.h:41
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
class register implement
Definition arena_queue.h:37
The options of timer
Definition timer.h:32
uint32_t period
The period of the timer, unit is ms max: 512 * 64 min: 1
Definition timer.h:54
bool oneshot
True: perform the callback only after the first timing cycle False: perform the callback every timed ...
Definition timer.h:63
std::function< void()> callback
The task that the timer needs to perform
Definition timer.h:57