void actor_ostream::redirect_all(actor_system& sys, std::string fn, int flags) {
  auto pr = sys.scheduler().printer();
  pr->enqueue(make_mailbox_element(nullptr, message_id::make(), {},
                                    redirect_atom::value,
                                    std::move(fn), flags),
              nullptr);
}
Beispiel #2
0
void manager::detach(execution_unit*, bool invoke_disconnect_message) {
  CAF_LOG_TRACE(CAF_ARG(invoke_disconnect_message));
  // This function gets called from the multiplexer when an error occurs or
  // from the broker when closing this manager. In both cases, we need to make
  // sure this manager does not receive further socket events.
  remove_from_loop();
  // Disconnect from the broker if not already detached.
  if (!detached()) {
    CAF_LOG_DEBUG("disconnect servant from broker");
    auto raw_ptr = parent();
    // Keep a strong reference to our parent until we go out of scope.
    strong_actor_ptr ptr;
    ptr.swap(parent_);
    detach_from(raw_ptr);
    if (invoke_disconnect_message) {
      auto mptr = make_mailbox_element(nullptr, invalid_message_id,
                                       {}, detach_message());
      switch (raw_ptr->consume(*mptr)) {
        case im_success:
          raw_ptr->finalize();
          break;
        case im_skipped:
          raw_ptr->push_to_cache(std::move(mptr));
          break;
        case im_dropped:
          CAF_LOG_INFO("broker dropped disconnect message");
          break;
      }
    }
  }
}
actor_ostream& actor_ostream::write(std::string arg) {
  printer_->enqueue(make_mailbox_element(nullptr, message_id::make(), {},
                                         add_atom::value, self_,
                                         std::move(arg)),
                    nullptr);
  return *this;
}
bool monitorable_actor::cleanup(error&& reason, execution_unit* host) {
  CAF_LOG_TRACE(CAF_ARG(reason));
  attachable_ptr head;
  bool set_fail_state = exclusive_critical_section([&]() -> bool {
    if (!getf(is_cleaned_up_flag)) {
      // local actors pass fail_state_ as first argument
      if (&fail_state_ != &reason)
        fail_state_ = std::move(reason);
      attachables_head_.swap(head);
      flags(flags() | is_terminated_flag | is_cleaned_up_flag);
      on_cleanup();
      return true;
    }
    return false;
  });
  if (!set_fail_state)
    return false;
  CAF_LOG_DEBUG("cleanup" << CAF_ARG(id())
                << CAF_ARG(node()) << CAF_ARG(reason));
  // send exit messages
  for (attachable* i = head.get(); i != nullptr; i = i->next.get())
    i->actor_exited(reason, host);
  // tell printer to purge its state for us if we ever used aout()
  if (getf(abstract_actor::has_used_aout_flag)) {
    auto pr = home_system().scheduler().printer();
    pr->enqueue(make_mailbox_element(nullptr, make_message_id(), {},
                                      delete_atom::value, id()),
                nullptr);
  }
  return true;
}
void actor_ostream::redirect(abstract_actor* self, std::string fn, int flags) {
  if (!self)
    return;
  auto pr = self->home_system().scheduler().printer();
  pr->enqueue(make_mailbox_element(nullptr, message_id::make(), {},
                                    redirect_atom::value, self->id(),
                                    std::move(fn), flags),
              nullptr);
}
Beispiel #6
0
void scribe::data_transferred(execution_unit* ctx, size_t written,
                              size_t remaining) {
  CAF_LOG_TRACE(CAF_ARG(written) << CAF_ARG(remaining));
  if (detached())
    return;
  data_transferred_msg tmp{hdl(), written, remaining};
  auto ptr = make_mailbox_element(nullptr, invalid_message_id, {}, tmp);
  parent()->context(ctx);
  parent()->consume(std::move(ptr));
}
bool monitorable_actor::handle_system_message(mailbox_element& x,
                                              execution_unit* ctx,
                                              bool trap_exit) {
  auto& msg = x.content();
  if (!trap_exit && msg.size() == 1 && msg.match_element<exit_msg>(0)) {
    // exits for non-normal exit reasons
    auto& em = msg.get_mutable_as<exit_msg>(0);
    if (em.reason)
      cleanup(std::move(em.reason), ctx);
    return true;
  }
  if (msg.size() > 1 && msg.match_element<sys_atom>(0)) {
    if (!x.sender)
      return true;
    error err;
    mailbox_element_ptr res;
    msg.apply(
      [&](sys_atom, get_atom, std::string& what) {
        CAF_LOG_TRACE(CAF_ARG(what));
        if (what != "info") {
          err = sec::unsupported_sys_key;
          return;
        }
        res = make_mailbox_element(ctrl(), x.mid.response_id(), {},
                                    ok_atom::value, std::move(what),
                                    strong_actor_ptr{ctrl()}, name());
      }
    );
    if (!res && !err)
      err = sec::unsupported_sys_message;
    if (err && x.mid.is_request())
      res = make_mailbox_element(ctrl(), x.mid.response_id(),
                                  {}, std::move(err));
    if (res) {
      auto s = actor_cast<strong_actor_ptr>(x.sender);
      if (s)
        s->enqueue(std::move(res), ctx);
    }
    return true;
  }
  return false;
}
void response_promise::deliver_impl(message msg) {
  CAF_LOG_TRACE(CAF_ARG(msg));
  if (!stages_.empty()) {
    auto next = std::move(stages_.back());
    stages_.pop_back();
    next->enqueue(make_mailbox_element(std::move(source_), id_,
                                       std::move(stages_), std::move(msg)),
                  context());
    return;
  }
  if (source_) {
    source_->enqueue(std::move(self_), id_.response_id(),
                     std::move(msg), context());
    source_.reset();
    return;
  }
  CAF_LOG_INFO_IF(self_ != nullptr, "response promise already satisfied");
  CAF_LOG_INFO_IF(self_ == nullptr, "invalid response promise");
}
Beispiel #9
0
 typename response_type<
   typename Handle::signatures,
   detail::implicit_conversions_t<typename std::decay<Ts>::type>...
 >::delegated_type
 delegate(const Handle& dest, Ts&&... xs) {
   static_assert(sizeof...(Ts) > 0, "nothing to delegate");
   using token =
     detail::type_list<
       typename detail::implicit_conversions<
         typename std::decay<Ts>::type
       >::type...>;
   static_assert(response_type_unbox<signatures_of_t<Handle>, token>::valid,
                 "receiver does not accept given message");
   auto mid = current_element_->mid;
   current_element_->mid = P == message_priority::high
                           ? mid.with_high_priority()
                           : mid.with_normal_priority();
   dest->enqueue(make_mailbox_element(std::move(current_element_->sender),
                                      mid, std::move(current_element_->stages),
                                      std::forward<Ts>(xs)...),
                 context());
   return {};
 }
actor_ostream& actor_ostream::flush() {
  printer_->enqueue(make_mailbox_element(nullptr, message_id::make(), {},
                                          flush_atom::value, self_),
                    nullptr);
  return *this;
}
void actor_companion::enqueue(strong_actor_ptr src, message_id mid,
                              message content, execution_unit* eu) {
  auto ptr = make_mailbox_element(std::move(src), mid, {}, std::move(content));
  enqueue(std::move(ptr), eu);
}
 void eq_impl(message_id mid, strong_actor_ptr sender,
              execution_unit* ctx, Ts&&... xs) {
   enqueue(make_mailbox_element(std::move(sender), mid,
                                {}, std::forward<Ts>(xs)...),
           ctx);
 }
void abstract_broker::enqueue(strong_actor_ptr src, message_id mid,
                              message msg, execution_unit*) {
  enqueue(make_mailbox_element(std::move(src), mid, {}, std::move(msg)),
          &backend());
}
Beispiel #14
0
void basp_broker_state::deliver(const node_id& src_nid, actor_id src_aid,
                                strong_actor_ptr dest, message_id mid,
                                std::vector<strong_actor_ptr>& stages,
                                message& msg) {
  CAF_LOG_TRACE(CAF_ARG(src_nid) << CAF_ARG(src_aid) << CAF_ARG(dest)
                << CAF_ARG(msg) << CAF_ARG(mid));
  auto src = src_nid == this_node() ? system().registry().get(src_aid)
                                    : proxies().get_or_put(src_nid, src_aid);
  // Intercept link messages. Forwarding actor proxies signalize linking
  // by sending link_atom/unlink_atom message with src = dest.
  if (msg.type_token() == make_type_token<atom_value, strong_actor_ptr>()) {
    switch (static_cast<uint64_t>(msg.get_as<atom_value>(0))) {
      default:
        break;
      case link_atom::value.uint_value(): {
        if (src_nid != this_node()) {
          CAF_LOG_WARNING("received link message for an other node");
          return;
        }
        auto ptr = msg.get_as<strong_actor_ptr>(1);
        if (!ptr) {
          CAF_LOG_WARNING("received link message with invalid target");
          return;
        }
        if (!src) {
          CAF_LOG_DEBUG("received link for invalid actor, report error");
          anon_send(actor_cast<actor>(ptr),
                    make_error(sec::remote_linking_failed));
          return;
        }
        static_cast<actor_proxy*>(ptr->get())->local_link_to(src->get());
        return;
      }
      case unlink_atom::value.uint_value(): {
        if (src_nid != this_node()) {
          CAF_LOG_WARNING("received unlink message for an other node");
          return;
        }
        auto ptr = msg.get_as<strong_actor_ptr>(1);
        if (!ptr) {
          CAF_LOG_DEBUG("received unlink message with invalid target");
          return;
        }
        if (!src) {
          CAF_LOG_DEBUG("received unlink for invalid actor, report error");
          return;
        }
        static_cast<actor_proxy*>(ptr->get())->local_unlink_from(src->get());
        return;
      }
    }
  }
  if (!dest) {
    auto rsn = exit_reason::remote_link_unreachable;
    CAF_LOG_INFO("cannot deliver message, destination not found");
    self->parent().notify<hook::invalid_message_received>(src_nid, src,
                                                          invalid_actor_id,
                                                          mid, msg);
    if (mid.valid() && src) {
      detail::sync_request_bouncer srb{rsn};
      srb(src, mid);
    }
    return;
  }
  self->parent().notify<hook::message_received>(src_nid, src, dest, mid, msg);
  dest->enqueue(make_mailbox_element(std::move(src), mid, std::move(stages),
                                      std::move(msg)),
                nullptr);
}