[core] Introduce Pass<> class and use it for Scheduler

Thus we enforce client to retain the returned `Scheduler` objects.
This commit is contained in:
Mikhail Pozdnyakov
2019-12-02 10:40:59 +02:00
parent e373d8a592
commit 7bacf5696c
5 changed files with 32 additions and 14 deletions

View File

@@ -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>

View File

@@ -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>

View File

@@ -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

View File

@@ -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())

View File

@@ -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());
}
EXPECT_EQ(shedulers.front(), std::shared_ptr<Scheduler>(Scheduler::GetSequenced()));
}