From 84b0b35f6dcea1c42d6586d7058b980685f19599 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Wed, 22 Jan 2020 18:29:01 +0200 Subject: [core] Use weak scheduler inside mailbox There is no guarantee that scheduler is alive when message is pushed to the mailbox. --- include/mbgl/actor/mailbox.hpp | 4 +++- src/mbgl/actor/mailbox.cpp | 30 ++++++++++++++++-------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/include/mbgl/actor/mailbox.hpp b/include/mbgl/actor/mailbox.hpp index 2b9838ef29..1e18d593d3 100644 --- a/include/mbgl/actor/mailbox.hpp +++ b/include/mbgl/actor/mailbox.hpp @@ -7,6 +7,8 @@ #include #include +#include + namespace mbgl { class Scheduler; @@ -38,7 +40,7 @@ public: static std::function makeClosure(std::weak_ptr); private: - optional scheduler; + mapbox::base::WeakPtr weakScheduler; std::recursive_mutex receivingMutex; std::mutex pushingMutex; diff --git a/src/mbgl/actor/mailbox.cpp b/src/mbgl/actor/mailbox.cpp index 070e14bdb0..79467a9258 100644 --- a/src/mbgl/actor/mailbox.cpp +++ b/src/mbgl/actor/mailbox.cpp @@ -8,26 +8,25 @@ namespace mbgl { Mailbox::Mailbox() = default; -Mailbox::Mailbox(Scheduler& scheduler_) - : scheduler(&scheduler_) { -} +Mailbox::Mailbox(Scheduler& scheduler_) : weakScheduler(scheduler_.makeWeakPtr()) {} void Mailbox::open(Scheduler& scheduler_) { - assert(!scheduler); + assert(!weakScheduler); // As with close(), block until neither receive() nor push() are in progress, and acquire the two // mutexes in the same order. std::lock_guard receivingLock(receivingMutex); std::lock_guard pushingLock(pushingMutex); - - scheduler = &scheduler_; + + weakScheduler = scheduler_.makeWeakPtr(); if (closed) { return; } if (!queue.empty()) { - (*scheduler)->schedule(makeClosure(shared_from_this())); + auto guard = weakScheduler.lock(); + if (weakScheduler) weakScheduler->schedule(makeClosure(shared_from_this())); } } @@ -43,8 +42,9 @@ void Mailbox::close() { closed = true; } -bool Mailbox::isOpen() const { return bool(scheduler); } - +bool Mailbox::isOpen() const { + return bool(weakScheduler); +} void Mailbox::push(std::unique_ptr message) { std::lock_guard pushingLock(pushingMutex); @@ -56,15 +56,17 @@ void Mailbox::push(std::unique_ptr message) { std::lock_guard queueLock(queueMutex); bool wasEmpty = queue.empty(); queue.push(std::move(message)); - if (wasEmpty && scheduler) { - (*scheduler)->schedule(makeClosure(shared_from_this())); + auto guard = weakScheduler.lock(); + if (wasEmpty && weakScheduler) { + weakScheduler->schedule(makeClosure(shared_from_this())); } } void Mailbox::receive() { std::lock_guard receivingLock(receivingMutex); - - assert(scheduler); + + auto guard = weakScheduler.lock(); + assert(weakScheduler); if (closed) { return; @@ -84,7 +86,7 @@ void Mailbox::receive() { (*message)(); if (!wasEmpty) { - (*scheduler)->schedule(makeClosure(shared_from_this())); + weakScheduler->schedule(makeClosure(shared_from_this())); } } -- cgit v1.2.1