task
using movex::cyber::common::GlobalData;
// 创建任务
template <typename F, typename... Args>
static auto Async(F&& f, Args&&... args)
-> std::future<typename std::result_of<F(Args...)>::type> {
return GlobalData::Instance()->IsRealityMode()
? TaskManager::Instance()->Enqueue(std::forward<F>(f),
std::forward<Args>(args)...)
: std::async(
std::launch::async,
std::bind(std::forward<F>(f), std::forward<Args>(args)...));
}
static inline void Yield() {
if (croutine::CRoutine::GetCurrentRoutine()) {
croutine::CRoutine::Yield();
} else {
std::this_thread::yield();
}
}
template <typename Rep, typename Period>
static void SleepFor(const std::chrono::duration<Rep, Period>& sleep_duration) {
auto routine = croutine::CRoutine::GetCurrentRoutine();
if (routine == nullptr) {
std::this_thread::sleep_for(sleep_duration);
} else {
routine->Sleep(sleep_duration);
}
}
static inline void USleep(useconds_t usec) {
auto routine = croutine::CRoutine::GetCurrentRoutine();
if (routine == nullptr) {
std::this_thread::sleep_for(std::chrono::microseconds{usec});
} else {
routine->Sleep(croutine::Duration(usec));
}
}
task_manager
task_manager.h
class TaskManager {
public:
~TaskManager();
void Shutdown();
template <typename F, typename... Args>
auto Enqueue(F&& func, Args&&... args)
-> std::future<typename std::result_of<F(Args...)>::type> {
using return_type = typename std::result_of<F(Args...)>::type;
auto task = std::make_shared<std::packaged_task<return_type()>>(
std::bind(std::forward<F>(func), std::forward<Args>(args)...));
if (!stop_.load()) {
task_queue_->Enqueue([task]() { (*task)(); });
// 唤醒所有任务
for (auto& task : tasks_) {
scheduler::Instance()->NotifyTask(task);
}
}
std::future<return_type> res(task->get_future());
return res;
}
private:
uint32_t num_threads_ = 0;
uint32_t task_queue_size_ = 1000;
std::atomic<bool> stop_ = {false};
std::vector<uint64_t> tasks_;
std::shared_ptr<base::BoundedQueue<std::function<void()>>> task_queue_;
DECLARE_SINGLETON(TaskManager);
};
task_manager.cc
using movex::cyber::common::GlobalData;
static const char* const task_prefix = "/internal/task";
TaskManager::TaskManager()
: task_queue_size_(1000),
task_queue_(new base::BoundedQueue<std::function<void()>>()) {
// 初始化任务队列和任务策略
if (!task_queue_->Init(task_queue_size_, new base::BlockWaitStrategy())) {
AERROR << "Task queue init failed";
throw std::runtime_error("Task queue init failed");
}
// 任务回调函数
auto func = [this]() {
while (!stop_) {
std::function<void()> task;
// 判断队列是否为空,空则等待
if (!task_queue_->Dequeue(&task)) {
auto routine = croutine::CRoutine::GetCurrentRoutine();
routine->HangUp();
continue;
}
task();
}
};
// 创建协程任务
num_threads_ = scheduler::Instance()->TaskPoolSize();
auto factory = croutine::CreateRoutineFactory(std::move(func));
tasks_.reserve(num_threads_);
for (uint32_t i = 0; i < num_threads_; i++) {
auto task_name = task_prefix + std::to_string(i);
tasks_.push_back(common::GlobalData::RegisterTaskName(task_name));
// 创建新的协程任务
if (!scheduler::Instance()->CreateTask(factory, task_name)) {
AERROR << "CreateTask failed:" << task_name;
}
}
}
TaskManager::~TaskManager() { Shutdown(); }
// 删除协程任务
void TaskManager::Shutdown() {
if (stop_.exchange(true)) {
return;
}
for (uint32_t i = 0; i < num_threads_; i++) {
scheduler::Instance()->RemoveTask(task_prefix + std::to_string(i));
}
}
功能分析
从上述TaskManager的构造函数可以看出在TaskManager初始化任务的时候会创建scheduler::Instance()->TaskPoolSize()个任务,用户异步协程的运行在用户调用cyber::Async的时候会更具是否处于正式环境调用Enqueue或者std::async函数
问题分析
cyber::Async在一定意义上不具备真正的实时性,在默认情况下协程的优先级为最低,所以task中添加的任务会在系统空闲的时候在调用