#pragma once #include #include #include #include #include #include #include #include namespace mbgl { /* An `EstablishedActor` is one half of the pair of types that comprise an actor (see `Actor`), the other half being `AspiringActor`. It is responsible for managing the lifetime of the target object `O` and the open/closed state of the parent's `mailbox`. The `O` object's lifetime is contained by that of its owning `EstablishedActor`: the `EstablishedActor` constructor executes the `O` constructor via "placement new", constructing it at the address provided by the parent `AspiringActor`, and the `~EstablishedActor` destructor similarly executes the `~O` destructor (after closing the mailbox). `EstablishedActor` should therefore live entirely on the thread intended to own `O`. */ template class EstablishedActor { public: // Construct the Object from a parameter pack `args` (i.e. `Object(args...)`) template ::value || std::is_constructible, Args...>::value >::type * = nullptr> EstablishedActor(Scheduler& scheduler, AspiringActor& parent_, Args&& ... args) : parent(parent_) { emplaceObject(std::forward(args)...); parent.mailbox->open(scheduler); } // Construct the `Object` from a tuple containing the constructor arguments (i.e. // `Object(std::get<0>(args), std::get<1>(args), ...)`) template >::value> EstablishedActor(Scheduler& scheduler, AspiringActor& parent_, ArgsTuple&& args) : parent(parent_) { emplaceObject(std::forward(args), std::make_index_sequence{}); parent.mailbox->open(scheduler); } EstablishedActor(const EstablishedActor&) = delete; ~EstablishedActor() { parent.mailbox->close(); parent.object().~Object(); } private: // Enabled for Objects with a constructor taking ActorRef as the first parameter template , Args...>::value>::type * = nullptr> void emplaceObject(Args&&... args_) { new (&parent.objectStorage) Object(parent.self(), std::forward(args_)...); } // Enabled for plain Objects template ::value>::type * = nullptr> void emplaceObject(Args&&... args_) { new (&parent.objectStorage) Object(std::forward(args_)...); } // Used to expand a tuple holding the constructor arguments template void emplaceObject(ArgsTuple&& args, std::index_sequence) { emplaceObject(std::move(std::get(std::forward(args)))...); (void) args; // mark args as used: if it's empty tuple, it's not actually used above. } AspiringActor& parent; }; } // namespace mbgl