From 23523621fd44135102bd6e0ceea9a392eaebaae3 Mon Sep 17 00:00:00 2001 From: Mikhail Pozdnyakov Date: Mon, 2 Dec 2019 10:40:59 +0200 Subject: [core] Introduce Pass<> class and use it for Scheduler Thus we enforce client to retain the returned `Scheduler` objects. --- include/mbgl/actor/scheduler.hpp | 21 +++++++++++++++++++-- src/mbgl/actor/scheduler.cpp | 4 ++-- test/actor/actor.test.cpp | 2 +- test/util/async_task.test.cpp | 14 +++++++------- 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/include/mbgl/actor/scheduler.hpp b/include/mbgl/actor/scheduler.hpp index 04cbc389e5..d7fec41ea6 100644 --- a/include/mbgl/actor/scheduler.hpp +++ b/include/mbgl/actor/scheduler.hpp @@ -9,6 +9,23 @@ namespace mbgl { class Mailbox; +// Using this type as a return type enforces the client to retain the returned object. +// TODO: Move to a separate file if/when other clients for this aux API turn up. +template +class Pass { +public: + Pass(T&& obj_) : obj(std::forward(obj_)) {} + Pass(Pass&&) = default; + Pass(const Pass&) = delete; + operator T() && { return std::move(obj); } + +private: + T obj; +}; + +template +using PassRefPtr = Pass>; + /* A `Scheduler` is responsible for coordinating the processing of messages by one or more actors via their mailboxes. It's an abstract interface. Currently, @@ -72,7 +89,7 @@ public: // The scheduled tasks might run in parallel on different // threads. // TODO : Rename to GetPool() - static std::shared_ptr GetBackground(); + static PassRefPtr GetBackground(); // Get the *sequenced* scheduler for asynchronous tasks. // Unlike the method above, the returned scheduler @@ -82,7 +99,7 @@ public: // // Sequenced scheduler can be used for running tasks // on the same thread-unsafe object. - static std::shared_ptr GetSequenced(); + static PassRefPtr GetSequenced(); protected: template diff --git a/src/mbgl/actor/scheduler.cpp b/src/mbgl/actor/scheduler.cpp index 0e051d0273..c9e258b50a 100644 --- a/src/mbgl/actor/scheduler.cpp +++ b/src/mbgl/actor/scheduler.cpp @@ -27,7 +27,7 @@ Scheduler* Scheduler::GetCurrent() { } // static -std::shared_ptr Scheduler::GetBackground() { +PassRefPtr Scheduler::GetBackground() { static std::weak_ptr weak; static std::mutex mtx; @@ -42,7 +42,7 @@ std::shared_ptr Scheduler::GetBackground() { } // static -std::shared_ptr Scheduler::GetSequenced() { +PassRefPtr Scheduler::GetSequenced() { const std::size_t kSchedulersCount = 10; static std::vector> weaks(kSchedulersCount); static std::mutex mtx; diff --git a/test/actor/actor.test.cpp b/test/actor/actor.test.cpp index c2a41fe787..03eb9b8301 100644 --- a/test/actor/actor.test.cpp +++ b/test/actor/actor.test.cpp @@ -156,7 +156,7 @@ TEST(Actor, DestructionAllowedInReceiveOnSameThread) { }; std::promise callbackFiredPromise; - auto retainer = Scheduler::GetBackground(); + std::shared_ptr retainer = Scheduler::GetBackground(); auto test = std::make_unique>(retainer); // Callback (triggered while mutex is locked in Mailbox::receive()) diff --git a/test/util/async_task.test.cpp b/test/util/async_task.test.cpp index 8c79c51405..e2f988751e 100644 --- a/test/util/async_task.test.cpp +++ b/test/util/async_task.test.cpp @@ -105,7 +105,7 @@ TEST(AsyncTask, RequestCoalescingMultithreaded) { unsigned count = 0, numThreads = 25; AsyncTask async([&count] { ++count; }); - auto retainer = Scheduler::GetBackground(); + std::shared_ptr retainer = Scheduler::GetBackground(); auto mailbox = std::make_shared(*retainer); TestWorker worker(&async); @@ -134,7 +134,7 @@ TEST(AsyncTask, ThreadSafety) { AsyncTask async([&count] { ++count; }); - auto retainer = Scheduler::GetBackground(); + std::shared_ptr retainer = Scheduler::GetBackground(); auto mailbox = std::make_shared(*retainer); TestWorker worker(&async); @@ -166,7 +166,7 @@ TEST(AsyncTask, scheduleAndReplyValue) { loop.stop(); }; - auto sheduler = Scheduler::GetBackground(); + std::shared_ptr sheduler = Scheduler::GetBackground(); sheduler->scheduleAndReplyValue(runInBackground, onResult); loop.run(); } @@ -194,7 +194,7 @@ TEST(AsyncTask, SequencedScheduler) { loop.stop(); }; - auto sheduler = Scheduler::GetSequenced(); + std::shared_ptr sheduler = Scheduler::GetSequenced(); sheduler->schedule(first); sheduler->schedule(second); @@ -206,10 +206,10 @@ TEST(AsyncTask, MultipleSequencedSchedulers) { std::vector> shedulers; for (int i = 0; i < 10; ++i) { - auto scheduler = Scheduler::GetSequenced(); + std::shared_ptr scheduler = Scheduler::GetSequenced(); EXPECT_TRUE(std::none_of( shedulers.begin(), shedulers.end(), [&scheduler](const auto &item) { return item == scheduler; })); shedulers.emplace_back(std::move(scheduler)); } - EXPECT_EQ(shedulers.front(), Scheduler::GetSequenced()); -} \ No newline at end of file + EXPECT_EQ(shedulers.front(), std::shared_ptr(Scheduler::GetSequenced())); +} -- cgit v1.2.1