summaryrefslogtreecommitdiff
path: root/include/mbgl/util/thread.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'include/mbgl/util/thread.hpp')
-rw-r--r--include/mbgl/util/thread.hpp49
1 files changed, 9 insertions, 40 deletions
diff --git a/include/mbgl/util/thread.hpp b/include/mbgl/util/thread.hpp
index 9eecb64920..1fcc431b28 100644
--- a/include/mbgl/util/thread.hpp
+++ b/include/mbgl/util/thread.hpp
@@ -40,27 +40,18 @@ template<class Object>
class Thread : public Scheduler {
public:
template <class... Args>
- Thread(const std::string& name, Args&&... args) {
+ Thread(const std::string& name, Args&&... args)
+ : object(std::make_unique<Actor<Object>>()) {
+
std::unique_ptr<std::promise<void>> running_ = std::make_unique<std::promise<void>>();
running = running_->get_future();
- // Pre-create a "holding" mailbox for this actor, whose messages are
- // guaranteed not to be consumed until we explicitly call start(), which
- // we'll do on the target thread, once its RunLoop and Object instance
- // are ready.
- // Meanwhile, this allows us to immediately provide ActorRef using this
- // mailbox to queue any messages that come in before the thread is
- // ready. (See actor().)
- std::shared_ptr<Mailbox> mailbox_ = std::make_shared<Mailbox>();
- mailbox = mailbox_;
-
- auto tuple = std::make_tuple(std::forward<Args>(args)...);
+ auto capturedArgs = Actor<Object>::captureArguments(std::forward<Args>(args)...);
thread = std::thread([
this,
name,
- tuple,
- sharedMailbox = std::move(mailbox_),
+ capturedArgs,
runningPromise = std::move(running_)
] {
platform::setCurrentThreadName(name);
@@ -69,16 +60,7 @@ public:
util::RunLoop loop_(util::RunLoop::Type::New);
loop = &loop_;
- // Construct the Actor<Object> into the pre-allocated memory
- // at `actorStorage`.
- Actor<Object>* actor = emplaceActor(
- std::move(sharedMailbox),
- std::move(tuple),
- std::make_index_sequence<std::tuple_size<decltype(tuple)>::value>{});
-
- // Replace the NoopScheduler on the mailbox with the RunLoop to
- // begin actually processing messages.
- actor->mailbox->start(this);
+ object->activate(*this, std::move(capturedArgs));
runningPromise->set_value();
@@ -100,7 +82,7 @@ public:
// messages posted on this scheduler after
// we delete the RunLoop.
loop->invoke([&] {
- reinterpret_cast<const Actor<Object>*>(&actorStorage)->~Actor<Object>();
+ object.reset();
joinable.set_value();
});
@@ -115,14 +97,7 @@ public:
// to the non-owning reference to outlive this object
// and be used after the `Thread<>` gets destroyed.
ActorRef<std::decay_t<Object>> actor() {
- // The actor->object reference we provide here will not actually be
- // valid until the child thread constructs Actor<Object> into
- // actorStorage using "placement new".
- // We guarantee that the object reference isn't actually used by
- // creating this mailbox without a scheduler, and only starting it
- // after the actor has been constructed.
- auto actor = reinterpret_cast<Actor<Object>*>(&actorStorage);
- return ActorRef<std::decay_t<Object>>(actor->object, mailbox);
+ return object->self();
}
// Pauses the `Object` thread. It will prevent the object to wake
@@ -170,13 +145,7 @@ private:
loop->schedule(mailbox_);
}
- template <typename ArgsTuple, std::size_t... I>
- Actor<Object>* emplaceActor(std::shared_ptr<Mailbox> sharedMailbox, ArgsTuple args, std::index_sequence<I...>) {
- return new (&actorStorage) Actor<Object>(std::move(sharedMailbox), std::move(std::get<I>(std::forward<ArgsTuple>(args)))...);
- }
-
- std::weak_ptr<Mailbox> mailbox;
- std::aligned_storage_t<sizeof(Actor<Object>)> actorStorage;
+ std::unique_ptr<Actor<Object>> object;
std::thread thread;