decorated_tuple::decorated_tuple(cow_ptr&& d, vector_type&& v)
    : decorated_(std::move(d)),
      mapping_(std::move(v)),
      type_token_(0xFFFFFFFF) {
  CAF_ASSERT(mapping_.empty()
              || *(std::max_element(mapping_.begin(), mapping_.end()))
                 < static_cast<const cow_ptr&>(decorated_)->size());
  // calculate type token
  for (size_t i = 0; i < mapping_.size(); ++i) {
    type_token_ <<= 6;
    type_token_ |= decorated_->type_nr_at(mapping_[i]);
  }
}
Beispiel #2
0
message message::drop(size_t n) const {
  CAF_ASSERT(vals_);
  if (n == 0) {
    return *this;
  }
  if (n >= size()) {
    return message{};
  }
  std::vector<size_t> mapping (size() - n);
  size_t i = n;
  std::generate(mapping.begin(), mapping.end(), [&] { return i++; });
  return message {detail::decorated_tuple::make(vals_, mapping)};
}
 // acquires both locks
 void prepend(pointer value) {
   CAF_ASSERT(value != nullptr);
   node* tmp = new node(value);
   node* first = nullptr;
   // acquire both locks since we might touch last_ too
   lock_guard guard1(head_lock_);
   lock_guard guard2(tail_lock_);
   first = head_.load();
   CAF_ASSERT(first != nullptr);
   auto next = first->next.load();
   // first_ always points to a dummy with no value,
   // hence we put the new element second
   if (next) {
     CAF_ASSERT(first != tail_);
     tmp->next = next;
   } else {
     // queue is empty
     CAF_ASSERT(first == tail_);
     tail_ = tmp;
   }
   first->next = tmp;
 }
bool downstream_manager::check_paths_impl(path_algorithm algo,
                                          path_predicate&) const noexcept {
  // Return the result for empty ranges as specified by the C++ standard.
  switch (algo) {
    default:
      CAF_ASSERT(algo == path_algorithm::all_of);
      return true;
    case path_algorithm::any_of:
      return false;
    case path_algorithm::none_of:
      return true;
  }
}
decorated_tuple::decorated_tuple(cow_ptr&& d, vector_type&& v)
    : m_decorated(std::move(d)),
      m_mapping(std::move(v)),
      m_type_token(0xFFFFFFFF) {
  CAF_ASSERT(m_mapping.empty()
              || *(std::max_element(m_mapping.begin(), m_mapping.end()))
                 < static_cast<const cow_ptr&>(m_decorated)->size());
  // calculate type token
  for (size_t i = 0; i < m_mapping.size(); ++i) {
    m_type_token <<= 6;
    m_type_token |= m_decorated->type_nr_at(m_mapping[i]);
  }
}
Beispiel #6
0
 bool synchronized_await(Mutex& mtx, CondVar& cv, const TimePoint& timeout) {
   CAF_ASSERT(!closed());
   if (try_block()) {
     std::unique_lock<Mutex> guard(mtx);
     while (blocked()) {
       if (cv.wait_until(guard, timeout) == std::cv_status::timeout) {
         // if we're unable to set the queue from blocked to empty,
         // than there's a new element in the list
         return !try_unblock();
       }
     }
   }
   return true;
 }
Beispiel #7
0
actor actor::splice_impl(std::initializer_list<actor> xs) {
  CAF_ASSERT(xs.size() >= 2);
  actor_system* sys = nullptr;
  std::vector<strong_actor_ptr> tmp;
  for (auto& x : xs) {
    if (! sys)
      sys = &(x->home_system());
    tmp.push_back(actor_cast<strong_actor_ptr>(x));
  }
  return make_actor<decorator::splitter, actor>(sys->next_actor_id(),
                                                sys->node(), sys,
                                                std::move(tmp),
                                                std::set<std::string>{});
}
bool abstract_actor::link_impl(linking_operation op, const actor_addr& other) {
  CAF_LOG_TRACE(CAF_ARG(op) << ", " << CAF_TSARG(other));
  switch (op) {
    case establish_link_op:
      return establish_link_impl(other);
    case establish_backlink_op:
      return establish_backlink_impl(other);
    case remove_link_op:
      return remove_link_impl(other);
    default:
      CAF_ASSERT(op == remove_backlink_op);
      return remove_backlink_impl(other);
  }
}
Beispiel #9
0
 void run() {
   CAF_SET_LOGGER_SYS(&system());
   CAF_LOG_TRACE(CAF_ARG(id_));
   // scheduling loop
   for (;;) {
     auto job = policy_.dequeue(this);
     CAF_ASSERT(job != nullptr);
     CAF_ASSERT(job->subtype() != resumable::io_actor);
     CAF_LOG_DEBUG("resume actor:" << CAF_ARG(id_of(job)));
     CAF_PUSH_AID_FROM_PTR(dynamic_cast<abstract_actor*>(job));
     policy_.before_resume(this, job);
     auto res = job->resume(this, max_throughput_);
     policy_.after_resume(this, job);
     switch (res) {
       case resumable::resume_later: {
         // keep reference to this actor, as it remains in the "loop"
         policy_.resume_job_later(this, job);
         break;
       }
       case resumable::done: {
         policy_.after_completion(this, job);
         intrusive_ptr_release(job);
         break;
       }
       case resumable::awaiting_message: {
         // resumable will maybe be enqueued again later, deref it for now
         intrusive_ptr_release(job);
         break;
       }
       case resumable::shutdown_execution_unit: {
         policy_.after_completion(this, job);
         policy_.before_shutdown(this);
         return;
       }
     }
   }
 }
Beispiel #10
0
void scribe::consume(execution_unit* ctx, const void*, size_t num_bytes) {
  CAF_ASSERT(ctx != nullptr);
  CAF_LOG_TRACE(CAF_ARG(num_bytes));
  if (detached()) {
    // we are already disconnected from the broker while the multiplexer
    // did not yet remove the socket, this can happen if an IO event causes
    // the broker to call close_all() while the pollset contained
    // further activities for the broker
    return;
  }
  // keep a strong reference to our parent until we leave scope
  // to avoid UB when becoming detached during invocation
  auto guard = parent_;
  auto& buf = rd_buf();
  CAF_ASSERT(buf.size() >= num_bytes);
  // make sure size is correct, swap into message, and then call client
  buf.resize(num_bytes);
  auto& msg_buf = msg().buf;
  msg_buf.swap(buf);
  invoke_mailbox_element(ctx);
  // swap buffer back to stream and implicitly flush wr_buf()
  msg_buf.swap(buf);
  flush();
}
Beispiel #11
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void CmdAddItemFeature::onActionTriggered(bool isChecked)
{
    if (isCommandEnabled())
    {
        CmdExecuteCommand* exeCmd = createExecuteCommand();
        if (exeCmd)
        {
            CmdExecCommandManager::instance()->processExecuteCommand(exeCmd);
        }
        else
        {
            CAF_ASSERT(0);
        }
    }
}
std::vector<iface_info> get_mac_addresses() {
  int mib[6];
  std::vector<iface_info> result;
  mib[0] = CTL_NET;
  mib[1] = AF_ROUTE;
  mib[2] = 0;
  mib[3] = AF_LINK;
  mib[4] = NET_RT_IFLIST;
  auto indices = if_nameindex();
  std::vector<char> buf;
  for (auto i = indices; !(i->if_index == 0 && i->if_name == nullptr); ++i) {
    mib[5] = static_cast<int>(i->if_index);
    size_t len;
    if (sysctl(mib, 6, nullptr, &len, nullptr, 0) < 0) {
      perror("sysctl 1 error");
      exit(3);
    }
    if (buf.size() < len)
      buf.resize(len);
    CAF_ASSERT(len > 0);
    if (sysctl(mib, 6, buf.data(), &len, nullptr, 0) < 0) {
      perror("sysctl 2 error");
      exit(5);
    }
    auto ifm = reinterpret_cast<if_msghdr*>(buf.data());
    auto sdl = reinterpret_cast<sockaddr_dl*>(ifm + 1);
    auto ptr = reinterpret_cast<unsigned char*>(LLADDR(sdl));
    auto uctoi = [](unsigned char c) -> unsigned {
      return static_cast<unsigned char>(c);
    };
    std::ostringstream oss;
    oss << std::hex;
    oss.fill('0');
    oss.width(2);
    oss << uctoi(*ptr++);
    for (auto j = 0; j < 5; ++j) {
      oss << ":";
      oss.width(2);
      oss << uctoi(*ptr++);
    }
    auto addr = oss.str();
    if (addr != "00:00:00:00:00:00") {
      result.emplace_back(i->if_name, std::move(addr));
    }
  }
  if_freenameindex(indices);
  return result;
}
void monitorable_actor::attach(attachable_ptr ptr) {
  CAF_LOG_TRACE("");
  CAF_ASSERT(ptr != nullptr);
  error fail_state;
  auto attached = exclusive_critical_section([&] {
    if (getf(is_terminated_flag)) {
      fail_state = fail_state_;
      return false;
    }
    attach_impl(ptr);
    return true;
  });
  CAF_LOG_DEBUG("cannot attach functor to terminated actor: call immediately");
  if (!attached)
    ptr->actor_exited(fail_state, nullptr);
}
void replace_all(std::string& str,
                 const char (&what)[WhatSize],
                 const char (&with)[WithSize]) {
  // end(what) - 1 points to the null-terminator
  auto next = [&](std::string::iterator pos) -> std::string::iterator {
    return std::search(pos, str.end(), std::begin(what), std::end(what) - 1);
  };
  auto i = next(std::begin(str));
  while (i != std::end(str)) {
    auto before = std::distance(std::begin(str), i);
    CAF_ASSERT(before >= 0);
    str.replace(i, i + WhatSize - 1, with);
    // i became invalidated -> use new iterator pointing
    // to the first character after the replaced text
    i = next(str.begin() + before + (WithSize - 1));
  }
}
Beispiel #15
0
 /// Tries to enqueue a new element to the inbox.
 /// @threadsafe
 inbox_result push_front(pointer new_element) noexcept {
   CAF_ASSERT(new_element != nullptr);
   pointer e = stack_.load();
   auto eof = stack_closed_tag();
   auto blk = reader_blocked_tag();
   while (e != eof) {
     // A tag is never part of a non-empty list.
     new_element->next = e != blk ? e : nullptr;
     if (stack_.compare_exchange_strong(e, new_element))
       return  e == reader_blocked_tag() ? inbox_result::unblocked_reader
                                           : inbox_result::success;
     // Continue with new value of `e`.
   }
   // The queue has been closed, drop messages.
   deleter_type d;
   d(new_element);
   return inbox_result::queue_closed;
 }
 /// Tries to enqueue a new element to the mailbox.
 /// @warning Call only from the reader (owner).
 enqueue_result enqueue(pointer new_element) {
   CAF_ASSERT(new_element != nullptr);
   pointer e = stack_.load();
   for (;;) {
     if (! e) {
       // if tail is nullptr, the queue has been closed
       delete_(new_element);
       return enqueue_result::queue_closed;
     }
     // a dummy is never part of a non-empty list
     new_element->next = is_dummy(e) ? nullptr : e;
     if (stack_.compare_exchange_strong(e, new_element)) {
       return  (e == reader_blocked_dummy()) ? enqueue_result::unblocked_reader
                                             : enqueue_result::success;
     }
     // continue with new value of e
   }
 }
void monitorable_actor::add_link(abstract_actor* x) {
  // Add backlink on `x` first and add the local attachable only on success.
  CAF_LOG_TRACE(CAF_ARG(x));
  CAF_ASSERT(x != nullptr);
  error fail_state;
  bool send_exit_immediately = false;
  auto tmp = default_attachable::make_link(address(), x->address());
  joined_exclusive_critical_section(this, x, [&] {
    if (getf(is_terminated_flag)) {
      fail_state = fail_state_;
      send_exit_immediately = true;
    } else if (x->add_backlink(this)) {
      attach_impl(tmp);
    }
  });
  if (send_exit_immediately)
    x->enqueue(nullptr, invalid_message_id,
                 make_message(exit_msg{address(), fail_state}), nullptr);
}
actor_addr actor_namespace::read(deserializer* source) {
  CAF_ASSERT(source != nullptr);
  node_id::host_id_type hid;
  auto aid = source->read<uint32_t>();                 // actor id
  source->read_raw(node_id::host_id_size, hid.data()); // host id
  auto pid = source->read<uint32_t>();                 // process id
  node_id this_node = detail::singletons::get_node_id();
  if (aid == 0 && pid == 0) {
    // 0:0 identifies an invalid actor
    return invalid_actor_addr;
  }
  if (pid == this_node.process_id() && hid == this_node.host_id()) {
    // identifies this exact process on this host, ergo: local actor
    auto a = detail::singletons::get_actor_registry()->get(aid);
    // might be invalid
    return a ? a->address() : invalid_actor_addr;
  }
  // identifies a remote actor; create proxy if needed
  return get_or_put({pid, hid}, aid)->address();
}
void actor_namespace::write(serializer* sink, const actor_addr& addr) {
  CAF_ASSERT(sink != nullptr);
  if (! addr) {
    node_id::host_id_type zero;
    std::fill(zero.begin(), zero.end(), 0);
    sink->write_value(static_cast<actor_id>(0));         // actor id
    sink->write_raw(node_id::host_id_size, zero.data()); // host id
    sink->write_value(static_cast<uint32_t>(0));         // process id
  } else {
    // register locally running actors to be able to deserialize them later
    if (! addr.is_remote()) {
      auto reg = detail::singletons::get_actor_registry();
      reg->put(addr.id(), actor_cast<abstract_actor_ptr>(addr));
    }
    auto pinf = addr.node();
    sink->write_value(addr.id());                                  // actor id
    sink->write_raw(node_id::host_id_size, pinf.host_id().data()); // host id
    sink->write_value(pinf.process_id());                          // process id
  }
}
Beispiel #20
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void PdmUiFieldHandle::notifyFieldChanged(const QVariant& oldFieldValue, const QVariant& newFieldValue)
{
    if (oldFieldValue != newFieldValue)
    {
        PdmFieldHandle* fieldHandle = this->fieldHandle();
        CAF_ASSERT(fieldHandle && fieldHandle->ownerObject());

        PdmUiObjectHandle* uiObjHandle = uiObj(fieldHandle->ownerObject());
        if (uiObjHandle)
        {
            uiObjHandle->fieldChangedByUi(fieldHandle, oldFieldValue, newFieldValue);
            uiObjHandle->updateConnectedEditors();
        }

        // Update field editors
        this->updateConnectedEditors();

        PdmUiModelChangeDetector::instance()->setModelChanged();
    }
}
Beispiel #21
0
void logger::run() {
  std::ostringstream fname;
  fname << "actor_log_" << detail::get_process_id() << "_" << time(0)
        << "_" << to_string(system_.node())
        << ".log";
  std::fstream out(fname.str().c_str(), std::ios::out | std::ios::app);
  std::unique_ptr<event> ptr;
  for (;;) {
    // make sure we have data to read
    queue_.synchronized_await(queue_mtx_, queue_cv_);
    // read & process event
    ptr.reset(queue_.try_pop());
    CAF_ASSERT(ptr != nullptr);
    if (ptr->msg.empty()) {
      out.close();
      return;
    }
    out << ptr->msg << std::flush;
  }
}
void abstract_actor::cleanup(uint32_t reason) {
  CAF_LOG_TRACE(CAF_ARG(reason));
  CAF_ASSERT(reason != exit_reason::not_exited);
  // move everyhting out of the critical section before processing it
  attachable_ptr head;
  { // lifetime scope of guard
    guard_type guard{mtx_};
    if (exit_reason_ != exit_reason::not_exited) {
      // already exited
      return;
    }
    exit_reason_ = reason;
    attachables_head_.swap(head);
  }
  CAF_LOG_INFO_IF(! is_remote(), "cleanup actor with ID " << id_
                                << "; exit reason = " << reason);
  // send exit messages
  for (attachable* i = head.get(); i != nullptr; i = i->next.get()) {
    i->actor_exited(this, reason);
  }
}
Beispiel #23
0
//--------------------------------------------------------------------------------------------------
/// 
//--------------------------------------------------------------------------------------------------
void PdmUiDateEditor::configureAndUpdateUi(const QString& uiConfigName)
{
    CAF_ASSERT(!m_dateEdit.isNull());

    PdmUiFieldEditorHandle::updateLabelFromField(m_label, uiConfigName);

    m_dateEdit->setEnabled(!field()->isUiReadOnly(uiConfigName));

    caf::PdmUiObjectHandle* uiObject = uiObj(field()->fieldHandle()->ownerObject());
    if (uiObject)
    {
        uiObject->editorAttribute(field()->fieldHandle(), uiConfigName, &m_attributes);
    }

    if (!m_attributes.dateFormat.isEmpty())
    {
        m_dateEdit->setDisplayFormat(m_attributes.dateFormat);
    }

    m_dateEdit->setDate(field()->uiValue().toDate());
}
bool monitorable_actor::add_backlink(abstract_actor* x) {
  // Called in an exclusive critical section.
  CAF_LOG_TRACE(CAF_ARG(x));
  CAF_ASSERT(x);
  error fail_state;
  bool send_exit_immediately = false;
  default_attachable::observe_token tk{x->address(),
                                       default_attachable::link};
  auto tmp = default_attachable::make_link(address(), x->address());
  auto success = false;
  if (getf(is_terminated_flag)) {
    fail_state = fail_state_;
    send_exit_immediately = true;
  } else if (detach_impl(tk, true, true) == 0) {
    attach_impl(tmp);
    success = true;
  }
  if (send_exit_immediately)
    x->enqueue(nullptr, invalid_message_id,
               make_message(exit_msg{address(), fail_state}), nullptr);
  return success;
}
const uniform_type_info* uniform_typeid_by_nr(uint16_t nr) {
  CAF_ASSERT(nr > 0 && nr < detail::type_nrs);
  return uti_map().by_type_nr(nr);
}
error decorated_tuple::save(size_t pos, serializer& sink) const {
  CAF_ASSERT(pos < size());
  return decorated_->save(mapping_[pos], sink);
}
type_erased_value_ptr decorated_tuple::copy(size_t pos) const {
  CAF_ASSERT(pos < size());
  return decorated_->copy(mapping_[pos]);
}
std::string decorated_tuple::stringify(size_t pos) const {
  CAF_ASSERT(pos < size());
  return decorated_->stringify(mapping_[pos]);
}
const void* decorated_tuple::get(size_t pos) const noexcept {
  CAF_ASSERT(pos < size());
  return decorated_->get(mapping_[pos]);
}
message_data::rtti_pair decorated_tuple::type(size_t pos) const noexcept {
  CAF_ASSERT(pos < size());
  return decorated_->type(mapping_[pos]);
}