summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com>2019-12-02 10:40:59 +0200
committerMikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com>2019-12-02 14:12:18 +0200
commit7bacf5696ca90dd3f3496988ad0658b357cb7ec1 (patch)
tree55c0988f8ea6a5c2f32c1f9df7d4e3f0bc26481c
parente373d8a5924e4f4cf3904ecacbf1d1cf86a5d60f (diff)
downloadqtlocation-mapboxgl-7bacf5696ca90dd3f3496988ad0658b357cb7ec1.tar.gz
[core] Introduce Pass<> class and use it for Scheduler
Thus we enforce client to retain the returned `Scheduler` objects.
-rw-r--r--include/mbgl/actor/scheduler.hpp21
-rw-r--r--next/CMakeLists.txt1
-rw-r--r--src/mbgl/actor/scheduler.cpp8
-rw-r--r--test/actor/actor.test.cpp2
-rw-r--r--test/util/async_task.test.cpp14
5 files changed, 32 insertions, 14 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 <typename T>
+class Pass {
+public:
+ Pass(T&& obj_) : obj(std::forward<T>(obj_)) {}
+ Pass(Pass&&) = default;
+ Pass(const Pass&) = delete;
+ operator T() && { return std::move(obj); }
+
+private:
+ T obj;
+};
+
+template <typename T>
+using PassRefPtr = Pass<std::shared_ptr<T>>;
+
/*
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<Scheduler> GetBackground();
+ static PassRefPtr<Scheduler> 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<Scheduler> GetSequenced();
+ static PassRefPtr<Scheduler> GetSequenced();
protected:
template <typename TaskFn, typename ReplyFn>
diff --git a/next/CMakeLists.txt b/next/CMakeLists.txt
index 6ed7b7a12e..e47be97fe1 100644
--- a/next/CMakeLists.txt
+++ b/next/CMakeLists.txt
@@ -45,6 +45,7 @@ add_compile_options(
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<NOT:$<PLATFORM_ID:Windows>>>:-Werror>
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<PLATFORM_ID:Android>>:-Wno-error=tautological-constant-compare>
$<$<CXX_COMPILER_ID:GNU>:-Wno-error=maybe-uninitialized>
+ $<$<CXX_COMPILER_ID:GNU>:-Wno-error=return-type>
$<$<CXX_COMPILER_ID:GNU>:-Wno-error=unknown-pragmas>
$<$<CXX_COMPILER_ID:AppleClang>:-Wno-error=deprecated-declarations>
$<$<CXX_COMPILER_ID:AppleClang>:-Wno-error=unused-parameter>
diff --git a/src/mbgl/actor/scheduler.cpp b/src/mbgl/actor/scheduler.cpp
index 0e051d0273..d765cfcf65 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> Scheduler::GetBackground() {
+PassRefPtr<Scheduler> Scheduler::GetBackground() {
static std::weak_ptr<Scheduler> weak;
static std::mutex mtx;
@@ -38,11 +38,11 @@ std::shared_ptr<Scheduler> Scheduler::GetBackground() {
weak = scheduler = std::make_shared<ThreadPool>();
}
- return scheduler;
+ return PassRefPtr<Scheduler>(std::move(scheduler));
}
// static
-std::shared_ptr<Scheduler> Scheduler::GetSequenced() {
+PassRefPtr<Scheduler> Scheduler::GetSequenced() {
const std::size_t kSchedulersCount = 10;
static std::vector<std::weak_ptr<Scheduler>> weaks(kSchedulersCount);
static std::mutex mtx;
@@ -65,7 +65,7 @@ std::shared_ptr<Scheduler> Scheduler::GetSequenced() {
break;
}
- return result;
+ return PassRefPtr<Scheduler>(std::move(result));
}
} //namespace mbgl
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<void> callbackFiredPromise;
- auto retainer = Scheduler::GetBackground();
+ std::shared_ptr<Scheduler> retainer = Scheduler::GetBackground();
auto test = std::make_unique<Actor<Test>>(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<Scheduler> retainer = Scheduler::GetBackground();
auto mailbox = std::make_shared<Mailbox>(*retainer);
TestWorker worker(&async);
@@ -134,7 +134,7 @@ TEST(AsyncTask, ThreadSafety) {
AsyncTask async([&count] { ++count; });
- auto retainer = Scheduler::GetBackground();
+ std::shared_ptr<Scheduler> retainer = Scheduler::GetBackground();
auto mailbox = std::make_shared<Mailbox>(*retainer);
TestWorker worker(&async);
@@ -166,7 +166,7 @@ TEST(AsyncTask, scheduleAndReplyValue) {
loop.stop();
};
- auto sheduler = Scheduler::GetBackground();
+ std::shared_ptr<Scheduler> 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<Scheduler> sheduler = Scheduler::GetSequenced();
sheduler->schedule(first);
sheduler->schedule(second);
@@ -206,10 +206,10 @@ TEST(AsyncTask, MultipleSequencedSchedulers) {
std::vector<std::shared_ptr<Scheduler>> shedulers;
for (int i = 0; i < 10; ++i) {
- auto scheduler = Scheduler::GetSequenced();
+ std::shared_ptr<Scheduler> 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>(Scheduler::GetSequenced()));
+}