-
Notifications
You must be signed in to change notification settings - Fork 6k
[Impeller] Gives ownership of the worker concurrent loop to the context. #41527
Changes from all commits
f339f1e
b8b9a82
eb00af9
07935ac
09d6627
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,14 +11,15 @@ | |
|
|
||
| namespace fml { | ||
|
|
||
| std::shared_ptr<ConcurrentMessageLoop> ConcurrentMessageLoop::Create( | ||
| std::unique_ptr<ConcurrentMessageLoop> ConcurrentMessageLoop::Create( | ||
| size_t worker_count) { | ||
| return std::shared_ptr<ConcurrentMessageLoop>{ | ||
| return std::unique_ptr<ConcurrentMessageLoop>{ | ||
| new ConcurrentMessageLoop(worker_count)}; | ||
| } | ||
|
|
||
| ConcurrentMessageLoop::ConcurrentMessageLoop(size_t worker_count) | ||
| : worker_count_(std::max<size_t>(worker_count, 1ul)) { | ||
| : worker_count_(std::max<size_t>(worker_count, 1ul)), | ||
| task_runner_(new ConcurrentTaskRunner(this)) { | ||
| for (size_t i = 0; i < worker_count_; ++i) { | ||
| workers_.emplace_back([i, this]() { | ||
| fml::Thread::SetCurrentThreadName(fml::Thread::ThreadConfig( | ||
|
|
@@ -33,6 +34,10 @@ ConcurrentMessageLoop::ConcurrentMessageLoop(size_t worker_count) | |
| } | ||
|
|
||
| ConcurrentMessageLoop::~ConcurrentMessageLoop() { | ||
| { | ||
| std::scoped_lock lock(task_runner_->weak_loop_mutex_); | ||
| task_runner_->weak_loop_ = nullptr; | ||
| } | ||
| Terminate(); | ||
| for (auto& worker : workers_) { | ||
| worker.join(); | ||
|
|
@@ -43,33 +48,18 @@ size_t ConcurrentMessageLoop::GetWorkerCount() const { | |
| return worker_count_; | ||
| } | ||
|
|
||
| std::shared_ptr<ConcurrentTaskRunner> ConcurrentMessageLoop::GetTaskRunner() { | ||
| return std::make_shared<ConcurrentTaskRunner>(weak_from_this()); | ||
| } | ||
|
|
||
| void ConcurrentMessageLoop::PostTask(const fml::closure& task) { | ||
| if (!task) { | ||
| return; | ||
| } | ||
|
|
||
| std::unique_lock lock(tasks_mutex_); | ||
|
|
||
| // Don't just drop tasks on the floor in case of shutdown. | ||
| if (shutdown_) { | ||
| FML_DLOG(WARNING) | ||
| << "Tried to post a task to shutdown concurrent message " | ||
| "loop. The task will be executed on the callers thread."; | ||
| lock.unlock(); | ||
| task(); | ||
| return; | ||
| } | ||
|
|
||
| tasks_.push(task); | ||
|
|
||
| // Unlock the mutex before notifying the condition variable because that mutex | ||
| // has to be acquired on the other thread anyway. Waiting in this scope till | ||
| // it is acquired there is a pessimization. | ||
| lock.unlock(); | ||
| { | ||
| std::unique_lock lock(tasks_mutex_); | ||
| tasks_.push(task); | ||
| } | ||
|
|
||
| tasks_condition_.notify_one(); | ||
| } | ||
|
|
@@ -148,9 +138,8 @@ std::vector<fml::closure> ConcurrentMessageLoop::GetThreadTasksLocked() { | |
| return pending_tasks; | ||
| } | ||
|
|
||
| ConcurrentTaskRunner::ConcurrentTaskRunner( | ||
| std::weak_ptr<ConcurrentMessageLoop> weak_loop) | ||
| : weak_loop_(std::move(weak_loop)) {} | ||
| ConcurrentTaskRunner::ConcurrentTaskRunner(ConcurrentMessageLoop* weak_loop) | ||
| : weak_loop_(weak_loop) {} | ||
|
|
||
| ConcurrentTaskRunner::~ConcurrentTaskRunner() = default; | ||
|
|
||
|
|
@@ -159,15 +148,12 @@ void ConcurrentTaskRunner::PostTask(const fml::closure& task) { | |
| return; | ||
| } | ||
|
|
||
| if (auto loop = weak_loop_.lock()) { | ||
| loop->PostTask(task); | ||
| return; | ||
| { | ||
| std::scoped_lock lock(weak_loop_mutex_); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This adds a small amount of overhead compared to the shared_ptr, but we could share the |
||
| if (weak_loop_) { | ||
| weak_loop_->PostTask(task); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There may be undefined behavior if a method like At the point where this call happens, another thread may have already dropped the last reference to the The
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yep, good observation. In order for it to get undefined behavior The order of operations of deallocation is well defined. At the point where we are clearing out the reference the Let me know if you you think we are still missing something. |
||
| } | ||
| } | ||
|
|
||
| FML_DLOG(WARNING) | ||
| << "Tried to post to a concurrent message loop that has already died. " | ||
| "Executing the task on the callers thread."; | ||
| task(); | ||
| } | ||
|
|
||
| bool ConcurrentMessageLoop::RunsTasksOnCurrentThread() { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tasks could always be dropped when shutting down a ConcurrentMessageLoop, there was no guarantee that they would all be executed despite a few places that attempted to make that a thing. Specifically if more than N tasks were queued up and the loop was deleted, task[N+1, ..] would be dropped.
Dropping late tasks matches he behavior elsewhere in the engine (for example platform channel messages).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mainly notes for myself: