inline void operator()(const actor_ptr& sender, const message_id& mid) const { CPPA_REQUIRE(rsn != exit_reason::not_exited); if (mid.is_request() && sender != nullptr) { sender->enqueue({nullptr, sender, mid.response_id()}, make_any_tuple(atom("EXITED"), rsn)); } }
message_future timed_sync_send(actor_ptr whom, const std::chrono::duration<Rep,Period>& rel_time, Ts&&... what) { static_assert(sizeof...(Ts) > 0, "no message to send"); return timed_sync_send_tuple(std::move(whom), rel_time, make_any_tuple(std::forward<Ts>(what)...)); }
message_future timed_sync_send(actor_destination whom, const util::duration& rtime, Ts&&... what) { static_assert(sizeof...(Ts) > 0, "no message to send"); return timed_sync_send_tuple(std::move(whom), rtime, make_any_tuple(std::forward<Ts>(what)...)); }
message_future timed_sync_send_tuple(actor_ptr whom, const std::chrono::duration<Rep,Period>& rel_time, any_tuple what) { auto mf = sync_send_tuple(std::move(whom), std::move(what)); auto tmp = make_any_tuple(atom("TIMEOUT")); get_scheduler()->delayed_reply(self, rel_time, mf.id(), std::move(tmp)); return mf; }
void delayed_send(message_header hdr, const Duration& rel_time, any_tuple data ) { auto tup = make_any_tuple(atom("SEND"), util::duration{rel_time}, std::move(hdr), std::move(data)); m_timer->enqueue(message_header{}, std::move(tup), nullptr); }
message_future timed_sync_send_tuple(actor_destination dest, const util::duration& rtime, any_tuple what) { auto mf = sync_send_tuple(std::move(dest), std::move(what)); message_header hdr{self, self, mf.id()}; auto tmp = make_any_tuple(atom("TIMEOUT")); get_scheduler()->delayed_send(std::move(hdr), rtime, std::move(tmp)); return mf; }
void delayed_send(const channel_ptr& to, const Duration& rel_time, any_tuple data ) { auto tup = make_any_tuple(atom("SEND"), util::duration{rel_time}, to, std::move(data)); delayed_send_helper()->enqueue(self, std::move(tup)); }
inline void delayed_send(const channel_ptr& whom, const std::chrono::duration<Rep,Period>& rtime, Ts&&... what) { static_assert(sizeof...(Ts) > 0, "no message to send"); if (whom) { delayed_send_tuple(whom, rtime, make_any_tuple(std::forward<Ts>(what)...)); } }
void delayed_reply(message_header hdr, const Duration& rel_time, any_tuple data ) { CPPA_REQUIRE(hdr.id.valid() && hdr.id.is_response()); auto tup = make_any_tuple(atom("SEND"), util::duration{rel_time}, std::move(hdr), std::move(data)); m_timer->enqueue(message_header{}, std::move(tup), nullptr); }
inline void delayed_send(channel_destination dest, const util::duration& rtime, Ts&&... what) { static_assert(sizeof...(Ts) > 0, "no message to send"); if (dest.receiver) { delayed_send_tuple(std::move(dest), rtime, make_any_tuple(std::forward<Ts>(what)...)); } }
message_id local_actor::timed_sync_send_tuple_impl(message_priority mp, const actor& dest, const util::duration& rtime, any_tuple&& what) { auto nri = new_request_id(); if (mp == message_priority::high) nri = nri.with_high_priority(); dest->enqueue({address(), dest, nri}, std::move(what)); auto rri = nri.response_id(); get_scheduler()->delayed_send({address(), this, rri}, rtime, make_any_tuple(sync_timeout_msg{})); return rri; }
void request_timeout(const util::duration& d) { if (d.valid()) { if (d.is_zero()) { // immediately enqueue timeout enqueue(nullptr, make_any_tuple(atom("TIMEOUT"), ++m_active_timeout_id)); } else { get_scheduler()->delayed_send(this, d, atom("TIMEOUT"), ++m_active_timeout_id); } m_has_pending_timeout_request = true; } else m_has_pending_timeout_request = false; }
message_id local_actor::timed_sync_send_tuple_impl(message_priority mp, const actor& dest, const util::duration& rtime, any_tuple&& what) { if (!dest) { throw std::invalid_argument("cannot send synchronous message " "to invalid_actor"); } auto nri = new_request_id(); if (mp == message_priority::high) nri = nri.with_high_priority(); dest->enqueue({address(), dest, nri}, std::move(what), m_host); auto rri = nri.response_id(); get_scheduling_coordinator()->delayed_send({address(), this, rri}, rtime, make_any_tuple(sync_timeout_msg{})); return rri; }
void request_timeout(const util::duration& d) { if (d.valid()) { m_has_timeout = true; auto tid = ++m_timeout_id; auto msg = make_any_tuple(timeout_msg{tid}); if (d.is_zero()) { // immediately enqueue timeout message if duration == 0s this->enqueue({this->address(), this}, std::move(msg), this->m_host); //auto e = this->new_mailbox_element(this, std::move(msg)); //this->m_mailbox.enqueue(e); } else this->delayed_send_tuple(this, d, std::move(msg)); } else m_has_timeout = false; }
void delayed_reply(const actor_ptr& to, const Duration& rel_time, message_id_t id, any_tuple data ) { CPPA_REQUIRE(!id.valid() || id.is_response()); if (id.valid()) { auto tup = make_any_tuple(atom("REPLY"), util::duration{rel_time}, to, id, std::move(data)); delayed_send_helper()->enqueue(self, std::move(tup)); } else { this->delayed_send(to, rel_time, std::move(data)); } }
void default_actor_addressing::put(const process_information& node, actor_id aid, const actor_proxy_ptr& proxy) { auto& submap = m_proxies[node]; auto i = submap.find(aid); if (i == submap.end()) { submap.insert(make_pair(aid, proxy)); m_parent->enqueue(node, {nullptr, nullptr}, make_any_tuple(atom("MONITOR"), process_information::get(), aid)); } else { CPPA_LOGMF(CPPA_ERROR, self, "proxy for " << aid << ":" << to_string(node) << " already exists"); } }
bool actor::establish_backlink(const actor_ptr& other) { std::uint32_t reason = exit_reason::not_exited; if (other && other != this) { guard_type guard{m_mtx}; reason = m_exit_reason; if (reason == exit_reason::not_exited) { auto i = std::find(m_links.begin(), m_links.end(), other); if (i == m_links.end()) { m_links.push_back(other); return true; } } } // send exit message without lock if (reason != exit_reason::not_exited) { send_as(this, other, make_any_tuple(atom("EXIT"), reason)); } return false; }
bool abstract_actor::link_to_impl(const actor_addr& other) { if (other && other != this) { guard_type guard{m_mtx}; auto ptr = detail::raw_access::get(other); // send exit message if already exited if (exited()) { ptr->enqueue({address(), ptr}, make_any_tuple(exit_msg{address(), exit_reason()}), m_host); } // add link if not already linked to other // (checked by establish_backlink) else if (ptr->establish_backlink(address())) { m_links.push_back(ptr); return true; } } return false; }
actor_ptr spawn(const program& prog, const char* kernel_name, const dim_vec& global_dims, const dim_vec& offsets = {}, const dim_vec& local_dims = {}) { std::function<option<cow_tuple<typename util::rm_ref<Args>::type...>>(any_tuple)> map_args = [] (any_tuple msg) { return tuple_cast<typename util::rm_ref<Args>::type...>(msg); }; std::function<any_tuple(Ret&)> map_result = [] (Ret& result) { return make_any_tuple(std::move(result)); }; return this->spawn<Ret,Args...>(prog, kernel_name, global_dims, offsets, local_dims, std::move(map_args), std::move(map_result)); }
void abstract_actor::cleanup(std::uint32_t reason) { // log as 'actor' CPPA_LOGM_TRACE("cppa::actor", CPPA_ARG(m_id) << ", " << CPPA_ARG(reason) << ", " << CPPA_ARG(m_is_proxy)); CPPA_REQUIRE(reason != exit_reason::not_exited); // move everyhting out of the critical section before processing it decltype(m_links) mlinks; decltype(m_attachables) mattachables; { // lifetime scope of guard guard_type guard{m_mtx}; if (m_exit_reason != exit_reason::not_exited) { // already exited return; } m_exit_reason = reason; mlinks = std::move(m_links); mattachables = std::move(m_attachables); // make sure lists are empty m_links.clear(); m_attachables.clear(); } CPPA_LOGC_INFO_IF(not is_proxy(), "cppa::actor", __func__, "actor with ID " << m_id << " had " << mlinks.size() << " links and " << mattachables.size() << " attached functors; exit reason = " << reason << ", class = " << detail::demangle(typeid(*this))); // send exit messages auto msg = make_any_tuple(exit_msg{address(), reason}); CPPA_LOGM_DEBUG("cppa::actor", "send EXIT to " << mlinks.size() << " links"); for (auto& aptr : mlinks) { aptr->enqueue({address(), aptr, message_id{}.with_high_priority()}, msg, m_host); } CPPA_LOGM_DEBUG("cppa::actor", "run " << mattachables.size() << " attachables"); for (attachable_ptr& ptr : mattachables) { ptr->actor_exited(reason); } }
bool abstract_actor::establish_backlink(const actor_addr& other) { std::uint32_t reason = exit_reason::not_exited; if (other && other != this) { guard_type guard{m_mtx}; reason = m_exit_reason; if (reason == exit_reason::not_exited) { auto i = std::find(m_links.begin(), m_links.end(), other); if (i == m_links.end()) { m_links.push_back(detail::raw_access::get(other)); return true; } } } // send exit message without lock if (reason != exit_reason::not_exited) { auto ptr = detail::raw_access::unsafe_cast(other); ptr->enqueue({address(), ptr}, make_any_tuple(exit_msg{address(), exit_reason()}), m_host); } return false; }
inline void send_as(actor_ptr from, channel_ptr whom, Ts&&... what) { send_tuple_as(std::move(from), std::move(whom), make_any_tuple(std::forward<Ts>(what)...)); }
void anon_send_exit(const actor_addr& whom, std::uint32_t reason) { if (!whom) return; auto ptr = detail::raw_access::get(whom); ptr->enqueue({invalid_actor_addr, ptr, message_id{}.with_high_priority()}, make_any_tuple(exit_msg{invalid_actor_addr, reason}), nullptr); }
inline void send_tpl_impl(T* whom, Args&&... what) { if (whom) self->send_message(whom, make_any_tuple(std::forward<Args>(what)...)); }
inline void send(destination_header hdr, Ts&&... what) { static_assert(sizeof...(Ts) > 0, "no message to send"); send_tuple(std::move(hdr), make_any_tuple(std::forward<Ts>(what)...)); }
inline void delayed_reply(const std::chrono::duration<Rep, Period>& rtime, Ts&&... what) { delayed_reply_tuple(rtime, make_any_tuple(std::forward<Ts>(what)...)); }
any_tuple as_any_tuple(void* instance) const override { return make_any_tuple(deref(instance)); }
inline void reply_to(const response_handle& handle, Ts&&... what) { if (handle.valid()) { handle.apply(make_any_tuple(std::forward<Ts>(what)...)); } }
inline void reply(Ts&&... what) { self->reply_message(make_any_tuple(std::forward<Ts>(what)...)); }
inline message_future sync_send(actor_ptr whom, Ts&&... what) { static_assert(sizeof...(Ts) > 0, "no message to send"); return sync_send_tuple(std::move(whom), make_any_tuple(std::forward<Ts>(what)...)); }