Apollo  6.0
Open source self driving car software
croutine.h
Go to the documentation of this file.
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 #ifndef CYBER_CROUTINE_CROUTINE_H_
18 #define CYBER_CROUTINE_CROUTINE_H_
19 
20 #include <atomic>
21 #include <chrono>
22 #include <functional>
23 #include <memory>
24 #include <mutex>
25 #include <set>
26 #include <string>
27 
28 #include "cyber/common/log.h"
30 
31 namespace apollo {
32 namespace cyber {
33 namespace croutine {
34 
35 using RoutineFunc = std::function<void()>;
36 using Duration = std::chrono::microseconds;
37 
39 
40 class CRoutine {
41  public:
42  explicit CRoutine(const RoutineFunc &func);
43  virtual ~CRoutine();
44 
45  // static interfaces
46  static void Yield();
47  static void Yield(const RoutineState &state);
48  static void SetMainContext(const std::shared_ptr<RoutineContext> &context);
49  static CRoutine *GetCurrentRoutine();
50  static char **GetMainStack();
51 
52  // public interfaces
53  bool Acquire();
54  void Release();
55 
56  // It is caller's responsibility to check if state_ is valid before calling
57  // SetUpdateFlag().
58  void SetUpdateFlag();
59 
60  // acquire && release should be called before Resume
61  // when work-steal like mechanism used
62  RoutineState Resume();
63  RoutineState UpdateState();
64  RoutineContext *GetContext();
65  char **GetStack();
66 
67  void Run();
68  void Stop();
69  void Wake();
70  void HangUp();
71  void Sleep(const Duration &sleep_duration);
72 
73  // getter and setter
74  RoutineState state() const;
75  void set_state(const RoutineState &state);
76 
77  uint64_t id() const;
78  void set_id(uint64_t id);
79 
80  const std::string &name() const;
81  void set_name(const std::string &name);
82 
83  int processor_id() const;
84  void set_processor_id(int processor_id);
85 
86  uint32_t priority() const;
87  void set_priority(uint32_t priority);
88 
89  std::chrono::steady_clock::time_point wake_time() const;
90 
91  void set_group_name(const std::string &group_name) {
92  group_name_ = group_name;
93  }
94 
95  const std::string &group_name() { return group_name_; }
96 
97  private:
98  CRoutine(CRoutine &) = delete;
99  CRoutine &operator=(CRoutine &) = delete;
100 
101  std::string name_;
102  std::chrono::steady_clock::time_point wake_time_ =
103  std::chrono::steady_clock::now();
104 
105  RoutineFunc func_;
106  RoutineState state_;
107 
108  std::shared_ptr<RoutineContext> context_;
109 
110  std::atomic_flag lock_ = ATOMIC_FLAG_INIT;
111  std::atomic_flag updated_ = ATOMIC_FLAG_INIT;
112 
113  bool force_stop_ = false;
114 
115  int processor_id_ = -1;
116  uint32_t priority_ = 0;
117  uint64_t id_ = 0;
118 
119  std::string group_name_;
120 
121  static thread_local CRoutine *current_routine_;
122  static thread_local char *main_stack_;
123 };
124 
125 inline void CRoutine::Yield(const RoutineState &state) {
126  auto routine = GetCurrentRoutine();
127  routine->set_state(state);
128  SwapContext(GetCurrentRoutine()->GetStack(), GetMainStack());
129 }
130 
131 inline void CRoutine::Yield() {
132  SwapContext(GetCurrentRoutine()->GetStack(), GetMainStack());
133 }
134 
135 inline CRoutine *CRoutine::GetCurrentRoutine() { return current_routine_; }
136 
137 inline char **CRoutine::GetMainStack() { return &main_stack_; }
138 
139 inline RoutineContext *CRoutine::GetContext() { return context_.get(); }
140 
141 inline char **CRoutine::GetStack() { return &(context_->sp); }
142 
143 inline void CRoutine::Run() { func_(); }
144 
145 inline void CRoutine::set_state(const RoutineState &state) { state_ = state; }
146 
147 inline RoutineState CRoutine::state() const { return state_; }
148 
149 inline std::chrono::steady_clock::time_point CRoutine::wake_time() const {
150  return wake_time_;
151 }
152 
153 inline void CRoutine::Wake() { state_ = RoutineState::READY; }
154 
156 
157 inline void CRoutine::Sleep(const Duration &sleep_duration) {
158  wake_time_ = std::chrono::steady_clock::now() + sleep_duration;
160 }
161 
162 inline uint64_t CRoutine::id() const { return id_; }
163 
164 inline void CRoutine::set_id(uint64_t id) { id_ = id; }
165 
166 inline const std::string &CRoutine::name() const { return name_; }
167 
168 inline void CRoutine::set_name(const std::string &name) { name_ = name; }
169 
170 inline int CRoutine::processor_id() const { return processor_id_; }
171 
172 inline void CRoutine::set_processor_id(int processor_id) {
173  processor_id_ = processor_id;
174 }
175 
177  // Synchronous Event Mechanism
178  if (state_ == RoutineState::SLEEP &&
179  std::chrono::steady_clock::now() > wake_time_) {
180  state_ = RoutineState::READY;
181  return state_;
182  }
183 
184  // Asynchronous Event Mechanism
185  if (!updated_.test_and_set(std::memory_order_release)) {
186  if (state_ == RoutineState::DATA_WAIT || state_ == RoutineState::IO_WAIT) {
187  state_ = RoutineState::READY;
188  }
189  }
190  return state_;
191 }
192 
193 inline uint32_t CRoutine::priority() const { return priority_; }
194 
195 inline void CRoutine::set_priority(uint32_t priority) { priority_ = priority; }
196 
197 inline bool CRoutine::Acquire() {
198  return !lock_.test_and_set(std::memory_order_acquire);
199 }
200 
201 inline void CRoutine::Release() {
202  return lock_.clear(std::memory_order_release);
203 }
204 
205 inline void CRoutine::SetUpdateFlag() {
206  updated_.clear(std::memory_order_release);
207 }
208 
209 } // namespace croutine
210 } // namespace cyber
211 } // namespace apollo
212 
213 #endif // CYBER_CROUTINE_CROUTINE_H_
char ** GetStack()
Definition: croutine.h:141
void set_id(uint64_t id)
Definition: croutine.h:164
uint64_t id() const
Definition: croutine.h:162
void(* func)(void *)
Definition: routine_context.h:41
void Run()
Definition: croutine.h:143
Definition: croutine.h:40
int processor_id() const
Definition: croutine.h:170
RoutineState state() const
Definition: croutine.h:147
void SetUpdateFlag()
Definition: croutine.h:205
void Sleep(const Duration &sleep_duration)
Definition: croutine.h:157
void set_name(const std::string &name)
Definition: croutine.h:168
PlanningContext is the runtime context in planning. It is persistent across multiple frames...
Definition: atomic_hash_map.h:25
const std::string & group_name()
Definition: croutine.h:95
static CRoutine * GetCurrentRoutine()
Definition: croutine.h:135
std::function< void()> RoutineFunc
Definition: croutine.h:35
void set_group_name(const std::string &group_name)
Definition: croutine.h:91
void HangUp()
Definition: croutine.h:155
std::chrono::steady_clock::time_point wake_time() const
Definition: croutine.h:149
bool Acquire()
Definition: croutine.h:197
void set_priority(uint32_t priority)
Definition: croutine.h:195
RoutineContext * GetContext()
Definition: croutine.h:139
static void Yield()
Definition: croutine.h:131
void set_state(const RoutineState &state)
Definition: croutine.h:145
Definition: routine_context.h:42
RoutineState
Definition: croutine.h:38
void set_processor_id(int processor_id)
Definition: croutine.h:172
void Release()
Definition: croutine.h:201
static char ** GetMainStack()
Definition: croutine.h:137
std::chrono::microseconds Duration
Definition: croutine.h:36
void SwapContext(char **src_sp, char **dest_sp)
Definition: routine_context.h:53
void Wake()
Definition: croutine.h:153
uint32_t priority() const
Definition: croutine.h:193
RoutineState UpdateState()
Definition: croutine.h:176
const std::string & name() const
Definition: croutine.h:166