Manually split send_immediately and send_later implementations.
This commit is contained in:
parent
44b548c307
commit
2181783bee
@ -291,12 +291,20 @@ class PromiseFuture {
|
|||||||
FutureActor<T> future_;
|
FutureActor<T> future_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <ActorSendType send_type, class T, class ActorAT, class ActorBT, class ResultT, class... DestArgsT,
|
template <class T, class ActorAT, class ActorBT, class ResultT, class... DestArgsT, class... ArgsT>
|
||||||
class... ArgsT>
|
FutureActor<T> send_promise_immediately(ActorId<ActorAT> actor_id,
|
||||||
FutureActor<T> send_promise(ActorId<ActorAT> actor_id, ResultT (ActorBT::*func)(PromiseActor<T> &&, DestArgsT...),
|
ResultT (ActorBT::*func)(PromiseActor<T> &&, DestArgsT...), ArgsT &&...args) {
|
||||||
ArgsT &&...args) {
|
|
||||||
PromiseFuture<T> pf;
|
PromiseFuture<T> pf;
|
||||||
Scheduler::instance()->send_closure<send_type>(
|
Scheduler::instance()->send_closure_immediately(
|
||||||
|
std::move(actor_id), create_immediate_closure(func, pf.move_promise(), std::forward<ArgsT>(args)...));
|
||||||
|
return pf.move_future();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class ActorAT, class ActorBT, class ResultT, class... DestArgsT, class... ArgsT>
|
||||||
|
FutureActor<T> send_promise_later(ActorId<ActorAT> actor_id, ResultT (ActorBT::*func)(PromiseActor<T> &&, DestArgsT...),
|
||||||
|
ArgsT &&...args) {
|
||||||
|
PromiseFuture<T> pf;
|
||||||
|
Scheduler::instance()->send_closure_later(
|
||||||
std::move(actor_id), create_immediate_closure(func, pf.move_promise(), std::forward<ArgsT>(args)...));
|
std::move(actor_id), create_immediate_closure(func, pf.move_promise(), std::forward<ArgsT>(args)...));
|
||||||
return pf.move_future();
|
return pf.move_future();
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,6 @@ extern int VERBOSITY_NAME(actor);
|
|||||||
|
|
||||||
class ActorInfo;
|
class ActorInfo;
|
||||||
|
|
||||||
enum class ActorSendType { Immediate, Later };
|
|
||||||
|
|
||||||
class Scheduler;
|
class Scheduler;
|
||||||
class SchedulerGuard {
|
class SchedulerGuard {
|
||||||
public:
|
public:
|
||||||
@ -109,14 +107,21 @@ class Scheduler {
|
|||||||
template <class... ArgsT>
|
template <class... ArgsT>
|
||||||
void destroy_on_scheduler(int32 sched_id, ArgsT &...values);
|
void destroy_on_scheduler(int32 sched_id, ArgsT &...values);
|
||||||
|
|
||||||
template <ActorSendType send_type, class EventT>
|
template <class EventT>
|
||||||
void send_lambda(ActorRef actor_ref, EventT &&func);
|
void send_lambda_immediately(ActorRef actor_ref, EventT &&func);
|
||||||
|
|
||||||
template <ActorSendType send_type, class EventT>
|
template <class EventT>
|
||||||
void send_closure(ActorRef actor_ref, EventT &&closure);
|
void send_lambda_later(ActorRef actor_ref, EventT &&func);
|
||||||
|
|
||||||
template <ActorSendType send_type>
|
template <class EventT>
|
||||||
void send(ActorRef actor_ref, Event &&event);
|
void send_closure_immediately(ActorRef actor_ref, EventT &&closure);
|
||||||
|
|
||||||
|
template <class EventT>
|
||||||
|
void send_closure_later(ActorRef actor_ref, EventT &&closure);
|
||||||
|
|
||||||
|
void send_immediately(ActorRef actor_ref, Event &&event);
|
||||||
|
|
||||||
|
void send_later(ActorRef actor_ref, Event &&event);
|
||||||
|
|
||||||
void before_tail_send(const ActorId<> &actor_id);
|
void before_tail_send(const ActorId<> &actor_id);
|
||||||
|
|
||||||
@ -199,11 +204,16 @@ class Scheduler {
|
|||||||
|
|
||||||
void flush_mailbox(ActorInfo *actor_info);
|
void flush_mailbox(ActorInfo *actor_info);
|
||||||
|
|
||||||
void get_actor_sched_id(const ActorInfo *actor_info, int32 &actor_sched_id, bool &on_current_sched,
|
void get_actor_sched_id_to_send_immediately(const ActorInfo *actor_info, int32 &actor_sched_id,
|
||||||
bool &can_send_immediately);
|
bool &on_current_sched, bool &can_send_immediately);
|
||||||
|
|
||||||
template <ActorSendType send_type, class RunFuncT, class EventFuncT>
|
void get_actor_sched_id_to_send_later(const ActorInfo *actor_info, int32 &actor_sched_id, bool &on_current_sched);
|
||||||
void send_impl(const ActorId<> &actor_id, const RunFuncT &run_func, const EventFuncT &event_func);
|
|
||||||
|
template <class RunFuncT, class EventFuncT>
|
||||||
|
void send_immediately_impl(const ActorId<> &actor_id, const RunFuncT &run_func, const EventFuncT &event_func);
|
||||||
|
|
||||||
|
template <class EventFuncT>
|
||||||
|
void send_later_impl(const ActorId<> &actor_id, const EventFuncT &event_func);
|
||||||
|
|
||||||
Timestamp run_timeout();
|
Timestamp run_timeout();
|
||||||
void run_mailbox();
|
void run_mailbox();
|
||||||
@ -275,8 +285,8 @@ void send_closure(ActorIdT &&actor_id, FunctionT function, ArgsT &&...args) {
|
|||||||
using FunctionClassT = member_function_class_t<FunctionT>;
|
using FunctionClassT = member_function_class_t<FunctionT>;
|
||||||
static_assert(std::is_base_of<FunctionClassT, ActorT>::value, "unsafe send_closure");
|
static_assert(std::is_base_of<FunctionClassT, ActorT>::value, "unsafe send_closure");
|
||||||
|
|
||||||
Scheduler::instance()->send_closure<ActorSendType::Immediate>(
|
Scheduler::instance()->send_closure_immediately(std::forward<ActorIdT>(actor_id),
|
||||||
std::forward<ActorIdT>(actor_id), create_immediate_closure(function, std::forward<ArgsT>(args)...));
|
create_immediate_closure(function, std::forward<ArgsT>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ActorIdT, class FunctionT, class... ArgsT>
|
template <class ActorIdT, class FunctionT, class... ArgsT>
|
||||||
@ -285,23 +295,23 @@ void send_closure_later(ActorIdT &&actor_id, FunctionT function, ArgsT &&...args
|
|||||||
using FunctionClassT = member_function_class_t<FunctionT>;
|
using FunctionClassT = member_function_class_t<FunctionT>;
|
||||||
static_assert(std::is_base_of<FunctionClassT, ActorT>::value, "unsafe send_closure");
|
static_assert(std::is_base_of<FunctionClassT, ActorT>::value, "unsafe send_closure");
|
||||||
|
|
||||||
Scheduler::instance()->send<ActorSendType::Later>(std::forward<ActorIdT>(actor_id),
|
Scheduler::instance()->send_later(std::forward<ActorIdT>(actor_id),
|
||||||
Event::delayed_closure(function, std::forward<ArgsT>(args)...));
|
Event::delayed_closure(function, std::forward<ArgsT>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class... ArgsT>
|
template <class... ArgsT>
|
||||||
void send_lambda(ActorRef actor_ref, ArgsT &&...args) {
|
void send_lambda(ActorRef actor_ref, ArgsT &&...args) {
|
||||||
Scheduler::instance()->send_lambda<ActorSendType::Immediate>(actor_ref, std::forward<ArgsT>(args)...);
|
Scheduler::instance()->send_lambda_immediately(actor_ref, std::forward<ArgsT>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class... ArgsT>
|
template <class... ArgsT>
|
||||||
void send_event(ActorRef actor_ref, ArgsT &&...args) {
|
void send_event(ActorRef actor_ref, ArgsT &&...args) {
|
||||||
Scheduler::instance()->send<ActorSendType::Immediate>(actor_ref, std::forward<ArgsT>(args)...);
|
Scheduler::instance()->send_immediately(actor_ref, std::forward<ArgsT>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class... ArgsT>
|
template <class... ArgsT>
|
||||||
void send_event_later(ActorRef actor_ref, ArgsT &&...args) {
|
void send_event_later(ActorRef actor_ref, ArgsT &&...args) {
|
||||||
Scheduler::instance()->send<ActorSendType::Later>(actor_ref, std::forward<ArgsT>(args)...);
|
Scheduler::instance()->send_later(actor_ref, std::forward<ArgsT>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -301,8 +301,8 @@ void Scheduler::do_event(ActorInfo *actor_info, Event &&event) {
|
|||||||
// can't clear event here. It may be already destroyed during destroy_actor
|
// can't clear event here. It may be already destroyed during destroy_actor
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scheduler::get_actor_sched_id(const ActorInfo *actor_info, int32 &actor_sched_id, bool &on_current_sched,
|
void Scheduler::get_actor_sched_id_to_send_immediately(const ActorInfo *actor_info, int32 &actor_sched_id,
|
||||||
bool &can_send_immediately) {
|
bool &on_current_sched, bool &can_send_immediately) {
|
||||||
bool is_migrating;
|
bool is_migrating;
|
||||||
std::tie(actor_sched_id, is_migrating) = actor_info->migrate_dest_flag_atomic();
|
std::tie(actor_sched_id, is_migrating) = actor_info->migrate_dest_flag_atomic();
|
||||||
on_current_sched = !is_migrating && sched_id_ == actor_sched_id;
|
on_current_sched = !is_migrating && sched_id_ == actor_sched_id;
|
||||||
@ -310,6 +310,14 @@ void Scheduler::get_actor_sched_id(const ActorInfo *actor_info, int32 &actor_sch
|
|||||||
can_send_immediately = on_current_sched && !actor_info->is_running() && actor_info->mailbox_.empty();
|
can_send_immediately = on_current_sched && !actor_info->is_running() && actor_info->mailbox_.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Scheduler::get_actor_sched_id_to_send_later(const ActorInfo *actor_info, int32 &actor_sched_id,
|
||||||
|
bool &on_current_sched) {
|
||||||
|
bool is_migrating;
|
||||||
|
std::tie(actor_sched_id, is_migrating) = actor_info->migrate_dest_flag_atomic();
|
||||||
|
on_current_sched = !is_migrating && sched_id_ == actor_sched_id;
|
||||||
|
CHECK(has_guard_ || !on_current_sched);
|
||||||
|
}
|
||||||
|
|
||||||
void Scheduler::register_migrated_actor(ActorInfo *actor_info) {
|
void Scheduler::register_migrated_actor(ActorInfo *actor_info) {
|
||||||
VLOG(actor) << "Register migrated actor " << *actor_info << ", " << tag("actor_count", actor_count_);
|
VLOG(actor) << "Register migrated actor " << *actor_info << ", " << tag("actor_count", actor_count_);
|
||||||
actor_count_++;
|
actor_count_++;
|
||||||
@ -549,7 +557,7 @@ Timestamp Scheduler::run_timeout() {
|
|||||||
while (!timeout_queue_.empty() && timeout_queue_.top_key() < now) {
|
while (!timeout_queue_.empty() && timeout_queue_.top_key() < now) {
|
||||||
HeapNode *node = timeout_queue_.pop();
|
HeapNode *node = timeout_queue_.pop();
|
||||||
ActorInfo *actor_info = ActorInfo::from_heap_node(node);
|
ActorInfo *actor_info = ActorInfo::from_heap_node(node);
|
||||||
send<ActorSendType::Immediate>(actor_info->actor_id(), Event::timeout());
|
send_immediately(actor_info->actor_id(), Event::timeout());
|
||||||
}
|
}
|
||||||
return get_timeout();
|
return get_timeout();
|
||||||
}
|
}
|
||||||
|
@ -108,12 +108,12 @@ ActorOwn<ActorT> Scheduler::register_actor_impl(Slice name, ActorT *actor_ptr, A
|
|||||||
|
|
||||||
ActorId<ActorT> actor_id = weak_info->actor_id(actor_ptr);
|
ActorId<ActorT> actor_id = weak_info->actor_id(actor_ptr);
|
||||||
if (sched_id != sched_id_) {
|
if (sched_id != sched_id_) {
|
||||||
send<ActorSendType::Later>(actor_id, Event::start());
|
send_later(actor_id, Event::start());
|
||||||
do_migrate_actor(actor_info, sched_id);
|
do_migrate_actor(actor_info, sched_id);
|
||||||
} else {
|
} else {
|
||||||
pending_actors_list_.put(weak_info->get_list_node());
|
pending_actors_list_.put(weak_info->get_list_node());
|
||||||
if (ActorTraits<ActorT>::need_start_up) {
|
if (ActorTraits<ActorT>::need_start_up) {
|
||||||
send<ActorSendType::Later>(actor_id, Event::start());
|
send_later(actor_id, Event::start());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,8 +178,9 @@ inline void Scheduler::before_tail_send(const ActorId<> &actor_id) {
|
|||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
template <ActorSendType send_type, class RunFuncT, class EventFuncT>
|
template <class RunFuncT, class EventFuncT>
|
||||||
void Scheduler::send_impl(const ActorId<> &actor_id, const RunFuncT &run_func, const EventFuncT &event_func) {
|
void Scheduler::send_immediately_impl(const ActorId<> &actor_id, const RunFuncT &run_func,
|
||||||
|
const EventFuncT &event_func) {
|
||||||
ActorInfo *actor_info = actor_id.get_actor_info();
|
ActorInfo *actor_info = actor_id.get_actor_info();
|
||||||
if (unlikely(actor_info == nullptr || close_flag_)) {
|
if (unlikely(actor_info == nullptr || close_flag_)) {
|
||||||
return;
|
return;
|
||||||
@ -188,9 +189,9 @@ void Scheduler::send_impl(const ActorId<> &actor_id, const RunFuncT &run_func, c
|
|||||||
int32 actor_sched_id;
|
int32 actor_sched_id;
|
||||||
bool on_current_sched;
|
bool on_current_sched;
|
||||||
bool can_send_immediately;
|
bool can_send_immediately;
|
||||||
get_actor_sched_id(actor_info, actor_sched_id, on_current_sched, can_send_immediately);
|
get_actor_sched_id_to_send_immediately(actor_info, actor_sched_id, on_current_sched, can_send_immediately);
|
||||||
|
|
||||||
if (likely(send_type == ActorSendType::Immediate && can_send_immediately)) { // run immediately
|
if (likely(can_send_immediately)) { // run immediately
|
||||||
EventGuard guard(this, actor_info);
|
EventGuard guard(this, actor_info);
|
||||||
run_func(actor_info);
|
run_func(actor_info);
|
||||||
} else {
|
} else {
|
||||||
@ -202,9 +203,27 @@ void Scheduler::send_impl(const ActorId<> &actor_id, const RunFuncT &run_func, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <ActorSendType send_type, class EventT>
|
template <class EventFuncT>
|
||||||
void Scheduler::send_lambda(ActorRef actor_ref, EventT &&func) {
|
void Scheduler::send_later_impl(const ActorId<> &actor_id, const EventFuncT &event_func) {
|
||||||
return send_impl<send_type>(
|
ActorInfo *actor_info = actor_id.get_actor_info();
|
||||||
|
if (unlikely(actor_info == nullptr || close_flag_)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 actor_sched_id;
|
||||||
|
bool on_current_sched;
|
||||||
|
get_actor_sched_id_to_send_later(actor_info, actor_sched_id, on_current_sched);
|
||||||
|
|
||||||
|
if (on_current_sched) {
|
||||||
|
add_to_mailbox(actor_info, event_func());
|
||||||
|
} else {
|
||||||
|
send_to_scheduler(actor_sched_id, actor_id, event_func());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class EventT>
|
||||||
|
void Scheduler::send_lambda_immediately(ActorRef actor_ref, EventT &&func) {
|
||||||
|
return send_immediately_impl(
|
||||||
actor_ref.get(),
|
actor_ref.get(),
|
||||||
[&](ActorInfo *actor_info) {
|
[&](ActorInfo *actor_info) {
|
||||||
event_context_ptr_->link_token = actor_ref.token();
|
event_context_ptr_->link_token = actor_ref.token();
|
||||||
@ -217,9 +236,18 @@ void Scheduler::send_lambda(ActorRef actor_ref, EventT &&func) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <ActorSendType send_type, class EventT>
|
template <class EventT>
|
||||||
void Scheduler::send_closure(ActorRef actor_ref, EventT &&closure) {
|
void Scheduler::send_lambda_later(ActorRef actor_ref, EventT &&func) {
|
||||||
return send_impl<send_type>(
|
return send_later_impl(actor_ref.get(), [&] {
|
||||||
|
auto event = Event::from_lambda(std::forward<EventT>(func));
|
||||||
|
event.set_link_token(actor_ref.token());
|
||||||
|
return event;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class EventT>
|
||||||
|
void Scheduler::send_closure_immediately(ActorRef actor_ref, EventT &&closure) {
|
||||||
|
return send_immediately_impl(
|
||||||
actor_ref.get(),
|
actor_ref.get(),
|
||||||
[&](ActorInfo *actor_info) {
|
[&](ActorInfo *actor_info) {
|
||||||
event_context_ptr_->link_token = actor_ref.token();
|
event_context_ptr_->link_token = actor_ref.token();
|
||||||
@ -232,14 +260,27 @@ void Scheduler::send_closure(ActorRef actor_ref, EventT &&closure) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <ActorSendType send_type>
|
template <class EventT>
|
||||||
void Scheduler::send(ActorRef actor_ref, Event &&event) {
|
void Scheduler::send_closure_later(ActorRef actor_ref, EventT &&closure) {
|
||||||
|
return send_later_impl(actor_ref.get(), [&] {
|
||||||
|
auto event = Event::immediate_closure(std::forward<EventT>(closure));
|
||||||
|
event.set_link_token(actor_ref.token());
|
||||||
|
return event;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Scheduler::send_immediately(ActorRef actor_ref, Event &&event) {
|
||||||
event.set_link_token(actor_ref.token());
|
event.set_link_token(actor_ref.token());
|
||||||
return send_impl<send_type>(
|
return send_immediately_impl(
|
||||||
actor_ref.get(), [&](ActorInfo *actor_info) { do_event(actor_info, std::move(event)); },
|
actor_ref.get(), [&](ActorInfo *actor_info) { do_event(actor_info, std::move(event)); },
|
||||||
[&] { return std::move(event); });
|
[&] { return std::move(event); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void Scheduler::send_later(ActorRef actor_ref, Event &&event) {
|
||||||
|
event.set_link_token(actor_ref.token());
|
||||||
|
return send_later_impl(actor_ref.get(), [&] { return std::move(event); });
|
||||||
|
}
|
||||||
|
|
||||||
inline void Scheduler::subscribe(PollableFd fd, PollFlags flags) {
|
inline void Scheduler::subscribe(PollableFd fd, PollFlags flags) {
|
||||||
instance()->poll_.subscribe(std::move(fd), flags);
|
instance()->poll_.subscribe(std::move(fd), flags);
|
||||||
}
|
}
|
||||||
@ -256,7 +297,7 @@ inline void Scheduler::yield_actor(Actor *actor) {
|
|||||||
yield_actor(actor->get_info());
|
yield_actor(actor->get_info());
|
||||||
}
|
}
|
||||||
inline void Scheduler::yield_actor(ActorInfo *actor_info) {
|
inline void Scheduler::yield_actor(ActorInfo *actor_info) {
|
||||||
send<ActorSendType::Later>(actor_info->actor_id(), Event::yield());
|
send_later(actor_info->actor_id(), Event::yield());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Scheduler::stop_actor(Actor *actor) {
|
inline void Scheduler::stop_actor(Actor *actor) {
|
||||||
|
@ -126,8 +126,8 @@ class QueryActor final : public td::Actor {
|
|||||||
callback_->on_result(std::move(query));
|
callback_->on_result(std::move(query));
|
||||||
} else {
|
} else {
|
||||||
auto future = td::Random::fast(0, 3) == 0
|
auto future = td::Random::fast(0, 3) == 0
|
||||||
? td::send_promise<td::ActorSendType::Immediate>(rand_elem(workers_), &Worker::query, x, p)
|
? td::send_promise_immediately(rand_elem(workers_), &Worker::query, x, p)
|
||||||
: td::send_promise<td::ActorSendType::Later>(rand_elem(workers_), &Worker::query, x, p);
|
: td::send_promise_later(rand_elem(workers_), &Worker::query, x, p);
|
||||||
if (future.is_ready()) {
|
if (future.is_ready()) {
|
||||||
query.result = future.move_as_ok();
|
query.result = future.move_as_ok();
|
||||||
callback_->on_result(std::move(query));
|
callback_->on_result(std::move(query));
|
||||||
@ -301,9 +301,8 @@ class SimpleActor final : public td::Actor {
|
|||||||
}
|
}
|
||||||
q_++;
|
q_++;
|
||||||
p_ = td::Random::fast_bool() ? 1 : 10000;
|
p_ = td::Random::fast_bool() ? 1 : 10000;
|
||||||
auto future = td::Random::fast(0, 3) == 0
|
auto future = td::Random::fast(0, 3) == 0 ? td::send_promise_immediately(worker_, &Worker::query, q_, p_)
|
||||||
? td::send_promise<td::ActorSendType::Immediate>(worker_, &Worker::query, q_, p_)
|
: td::send_promise_later(worker_, &Worker::query, q_, p_);
|
||||||
: td::send_promise<td::ActorSendType::Later>(worker_, &Worker::query, q_, p_);
|
|
||||||
if (future.is_ready()) {
|
if (future.is_ready()) {
|
||||||
auto result = future.move_as_ok();
|
auto result = future.move_as_ok();
|
||||||
CHECK(result == fast_pow_mod_uint32(q_, p_));
|
CHECK(result == fast_pow_mod_uint32(q_, p_));
|
||||||
|
Loading…
Reference in New Issue
Block a user