Commit 91946b53 authored by Dominik Charousset's avatar Dominik Charousset

Re-organize BASP header + documentation update

The BASP header has been re-organized for better readability and in advance
of future extensions. This is a breaking change!
parent a8c30ef2
......@@ -527,7 +527,7 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/manual/variables.tex.in"
# check for doxygen and add custom "doc" target to Makefile
find_package(Doxygen)
if(DOXYGEN_FOUND)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in"
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile.in"
"${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile"
@ONLY)
add_custom_target(doc "${DOXYGEN_EXECUTABLE}"
......
......@@ -549,7 +549,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = @CMAKE_HOME_DIRECTORY@/libcaf_core/caf @CMAKE_HOME_DIRECTORY@/libcaf_core/caf/mixin @CMAKE_HOME_DIRECTORY@/libcaf_core/caf/policy @CMAKE_HOME_DIRECTORY@/libcaf_io/caf/io
INPUT = @CMAKE_HOME_DIRECTORY@/libcaf_core/caf @CMAKE_HOME_DIRECTORY@/libcaf_core/caf/mixin @CMAKE_HOME_DIRECTORY@/libcaf_core/caf/policy @CMAKE_HOME_DIRECTORY@/libcaf_io/caf/io @CMAKE_HOME_DIRECTORY@/libcaf_io/caf/io/network
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
......@@ -626,7 +626,7 @@ EXAMPLE_RECURSIVE = YES
# directories that contain image that are included in the documentation (see
# the \image command).
IMAGE_PATH =
IMAGE_PATH = @CMAKE_HOME_DIRECTORY@/doc/
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
......
......@@ -148,8 +148,7 @@
/// The {@link math_actor.cpp Math Actor Example} shows the usage
/// of {@link receive_loop} and {@link caf::arg_match arg_match}.
/// The {@link dining_philosophers.cpp Dining Philosophers Example}
/// introduces event-based actors and includes a lot of `libcaf
/// features.
/// introduces event-based actors covers various features of CAF.
///
/// @namespace caf
/// Root namespace of libcaf.
......@@ -164,35 +163,38 @@
/// Contains policies encapsulating characteristics or algorithms.
///
/// @namespace caf::io
/// Contains all network-related classes and functions.
/// Contains all IO-related classes and functions.
///
/// @namespace caf::io::network
/// Contains classes and functions used for network abstraction.
///
/// @namespace caf::io::basp
/// Contains all classes and functions for the Binary Actor Sytem Protocol.
///
/// @defgroup MessageHandling Message handling.
/// @defgroup MessageHandling Message Handling
///
/// This is the beating heart of `libcaf`. Actor programming is
/// all about message handling.
/// This is the beating heart of CAF, since actor programming is
/// a message oriented programming paradigm.
///
/// A message in `libcaf` is a n-tuple of values (with size >= 1)
/// You can use almost every type in a messages - as long as it is announced,
/// i.e., known by the type system of `libcaf`.
/// A message in CAF is a n-tuple of values (with size >= 1).
/// You can use almost every type in a messages as long as it is announced,
/// i.e., known by the type system of CAF.
///
/// @defgroup BlockingAPI Blocking API.
/// @defgroup BlockingAPI Blocking API
///
/// Blocking functions to receive messages.
///
/// The blocking API of libcaf is intended to be used for migrating
/// previously threaded applications. When writing new code, you should use
/// ibcafs nonblocking become/unbecome API.
/// The blocking API of CAF is intended to be used for migrating
/// previously threaded applications. When writing new code, you should
/// consider the nonblocking API based on `become` and `unbecome` first.
///
/// @section Send Send messages
/// @section Send Sending Messages
///
/// The function `send` can be used to send a message to an actor.
/// The first argument is the receiver of the message followed by any number
/// of values:
///
/// @code
/// ~~
/// // spawn some actors
/// auto a1 = spawn(...);
/// auto a2 = spawn(...);
......@@ -206,14 +208,14 @@
/// send(a1, msg);
/// send(a2, msg);
/// send(a3, msg);
/// @endcode
/// ~~
///
/// @section Receive Receive messages
///
/// The function `receive` takes a `behavior` as argument. The behavior
/// is a list of { pattern >> callback } rules.
///
/// @code
/// ~~
/// receive
/// (
/// on(atom("hello"), arg_match) >> [](const std::string& msg)
......@@ -226,7 +228,7 @@
/// return make_message(atom("result"), i0 + i1 + i2);
/// }
/// );
/// @endcode
/// ~~
///
/// Please read the manual for further details about pattern matching.
///
......@@ -239,7 +241,7 @@
/// what operation the sender of a message wanted by receiving just two integers.
///
/// Example actor:
/// @code
/// ~~
/// void math_actor() {
/// receive_loop (
/// on(atom("plus"), arg_match) >> [](int a, int b) {
......@@ -250,9 +252,9 @@
/// }
/// );
/// }
/// @endcode
/// ~~
///
/// @section ReceiveLoops Receive loops
/// @section ReceiveLoops Receive Loops
///
/// Previous examples using `receive` create behaviors on-the-fly.
/// This is inefficient in a loop since the argument passed to receive
......@@ -270,7 +272,7 @@
/// `receive_while` creates a functor evaluating a lambda expression.
/// The loop continues until the given lambda returns `false`. A simple example:
///
/// @code
/// ~~
/// // receive two integers
/// vector<int> received_values;
/// receive_while([&]() { return received_values.size() < 2; }) (
......@@ -279,23 +281,23 @@
/// }
/// );
/// // ...
/// @endcode
/// ~~
///
/// `receive_for` is a simple ranged-based loop:
///
/// @code
/// ~~
/// std::vector<int> vec {1, 2, 3, 4};
/// auto i = vec.begin();
/// receive_for(i, vec.end()) (
/// on(atom("get")) >> [&]() -> message { return {atom("result"), *i}; }
/// );
/// @endcode
/// ~~
///
/// `do_receive` returns a functor providing the function `until` that
/// takes a lambda expression. The loop continues until the given lambda
/// returns true. Example:
///
/// @code
/// ~~
/// // receive ints until zero was received
/// vector<int> received_values;
/// do_receive (
......@@ -305,29 +307,29 @@
/// )
/// .until([&]() { return received_values.back() == 0 });
/// // ...
/// @endcode
/// ~~
///
/// @section FutureSend Send delayed messages
/// @section FutureSend Sending Delayed Messages
///
/// The function `delayed_send` provides a simple way to delay a message.
/// This is particularly useful for recurring events, e.g., periodical polling.
/// Usage example:
///
/// @code
/// delayed_send(self, std::chrono::seconds(1), atom("poll"));
/// ~~
/// delayed_send(self, std::chrono::seconds(1), poll_atom::value);
/// receive_loop (
/// // ...
/// on(atom("poll")) >> [] {
/// [](poll_atom) {
/// // ... poll something ...
/// // and do it again after 1sec
/// delayed_send(self, std::chrono::seconds(1), atom("poll"));
/// delayed_send(self, std::chrono::seconds(1), poll_atom::value);
/// }
/// );
/// @endcode
/// ~~
///
/// See also the {@link dancing_kirby.cpp dancing kirby example}.
///
/// @defgroup ImplicitConversion Implicit type conversions.
/// @defgroup ImplicitConversion Implicit Type Conversions
///
/// The message passing of `libcaf` prohibits pointers in messages because
/// it enforces network transparent messaging.
......@@ -337,7 +339,7 @@
/// It also converts unicode literals to the corresponding STL container.
///
/// A few examples:
/// @code
/// ~~
/// // sends an std::string containing "hello actor!" to itself
/// send(self, "hello actor!");
///
......@@ -355,9 +357,9 @@
/// // equal to: on(std::string("hello actor!"))
/// on("hello actor!") >> [] { }
/// );
/// @endcode
/// ~~
///
/// @defgroup ActorCreation Actor creation.
/// @defgroup ActorCreation Creating Actors
// examples
......
......@@ -22,7 +22,7 @@
namespace caf {
/// @ingroup ActorCreation
/// @addtogroup ActorCreation
/// @{
/// Stores options passed to the `spawn` function family.
......
......@@ -12,6 +12,7 @@ set (LIBCAF_IO_SRCS
src/abstract_broker.cpp
src/broker.cpp
src/default_multiplexer.cpp
src/doorman.cpp
src/max_msg_size.cpp
src/middleman.cpp
src/hook.cpp
......@@ -22,6 +23,7 @@ set (LIBCAF_IO_SRCS
src/remote_group.cpp
src/manager.cpp
src/set_middleman.cpp
src/scribe.cpp
src/stream_manager.cpp
src/test_multiplexer.cpp
src/unpublish.cpp
......
This diff is collapsed.
This diff is collapsed.
......@@ -32,8 +32,9 @@
namespace caf {
namespace io {
/// A broker mediates between actor systems and other components in the network.
/// @extends local_actor
/// Describes a dynamically typed broker.
/// @extends abstract_broker
/// @ingroup Broker
class broker : public abstract_event_based_actor<behavior, false,
abstract_broker> {
public:
......@@ -50,7 +51,7 @@ public:
CAF_ASSERT(sptr->hdl() == hdl);
return spawn_functor(nullptr,
[sptr](broker* forked) {
sptr->set_broker(forked);
sptr->set_parent(forked);
forked->scribes_.emplace(sptr->hdl(), sptr);
},
fun, hdl, std::forward<Ts>(xs)...);
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_IO_DOORMAN_HPP
#define CAF_IO_DOORMAN_HPP
#include <cstddef>
#include "caf/message.hpp"
#include "caf/io/accept_handle.hpp"
#include "caf/io/system_messages.hpp"
#include "caf/io/network/acceptor_manager.hpp"
namespace caf {
namespace io {
/// Manages incoming connections.
/// @ingroup Broker
class doorman : public network::acceptor_manager {
public:
doorman(abstract_broker* parent, accept_handle hdl, uint16_t local_port);
~doorman();
inline accept_handle hdl() const {
return hdl_;
}
void io_failure(network::operation op) override;
// needs to be launched explicitly
virtual void launch() = 0;
uint16_t port() const {
return port_;
}
protected:
void detach_from_parent() override;
message detach_message() override;
inline new_connection_msg& accept_msg() {
return accept_msg_.get_as_mutable<new_connection_msg>(0);
}
inline const new_connection_msg& accept_msg() const {
return accept_msg_.get_as<new_connection_msg>(0);
}
accept_handle hdl_;
message accept_msg_;
uint16_t port_;
};
} // namespace io
} // namespace caf
#endif // CAF_IO_DOORMAN_HPP
......@@ -187,7 +187,7 @@ public:
"Cannot fork: new broker misses required handlers");
return spawn_functor_impl<no_spawn_options, impl>(
nullptr, [&sptr](abstract_broker* forked) {
sptr->set_broker(forked);
sptr->set_parent(forked);
forked->add_scribe(sptr);
},
std::move(fun), hdl, std::forward<Ts>(xs)...);
......
......@@ -23,11 +23,11 @@
namespace caf {
namespace io {
class basp_broker;
class abstract_broker;
class broker;
class middleman;
class basp_broker;
class receive_policy;
class abstract_broker;
namespace network {
......
......@@ -30,6 +30,8 @@ namespace network {
/// callbacks for incoming connections as well as for error handling.
class acceptor_manager : public manager {
public:
acceptor_manager(abstract_broker* ptr);
~acceptor_manager();
/// Called by the underlying IO device to indicate that
......
......@@ -115,7 +115,7 @@ template <class Socket>
connection_handle asio_multiplexer::add_tcp_scribe(abstract_broker* self,
Socket&& sock) {
CAF_LOG_TRACE("");
class impl : public abstract_broker::scribe {
class impl : public scribe {
public:
impl(abstract_broker* ptr, Socket&& s)
: scribe(ptr, network::conn_hdl_from_socket(s)),
......@@ -130,16 +130,16 @@ connection_handle asio_multiplexer::add_tcp_scribe(abstract_broker* self,
launch();
}
}
abstract_broker::buffer_type& wr_buf() override {
std::vector<char>& wr_buf() override {
return stream_.wr_buf();
}
abstract_broker::buffer_type& rd_buf() override {
std::vector<char>& rd_buf() override {
return stream_.rd_buf();
}
void stop_reading() override {
CAF_LOG_TRACE("");
stream_.stop_reading();
disconnect(false);
detach(false);
}
void flush() override {
CAF_LOG_TRACE("");
......@@ -156,7 +156,7 @@ connection_handle asio_multiplexer::add_tcp_scribe(abstract_broker* self,
bool launched_;
stream<Socket> stream_;
};
abstract_broker::scribe_ptr ptr = make_counted<impl>(self, std::move(sock));
auto ptr = make_counted<impl>(self, std::move(sock));
self->add_scribe(ptr);
return ptr->hdl();
}
......@@ -210,7 +210,7 @@ asio_multiplexer::add_tcp_doorman(abstract_broker* self,
default_socket_acceptor&& sock) {
CAF_LOG_TRACE("sock.fd = " << sock.native_handle());
CAF_ASSERT(sock.native_handle() != network::invalid_native_socket);
class impl : public abstract_broker::doorman {
class impl : public doorman {
public:
impl(abstract_broker* ptr, default_socket_acceptor&& s,
network::asio_multiplexer& am)
......@@ -230,7 +230,7 @@ asio_multiplexer::add_tcp_doorman(abstract_broker* self,
void stop_reading() override {
CAF_LOG_TRACE("");
acceptor_.stop();
disconnect(false);
detach(false);
}
void launch() override {
CAF_LOG_TRACE("");
......@@ -240,8 +240,7 @@ asio_multiplexer::add_tcp_doorman(abstract_broker* self,
private:
network::acceptor<default_socket_acceptor> acceptor_;
};
abstract_broker::doorman_ptr ptr
= make_counted<impl>(self, std::move(sock), *this);
auto ptr = make_counted<impl>(self, std::move(sock), *this);
self->add_doorman(ptr);
return ptr->hdl();
}
......
......@@ -20,9 +20,11 @@
#ifndef CAF_IO_NETWORK_MANAGER_HPP
#define CAF_IO_NETWORK_MANAGER_HPP
#include "caf/message.hpp"
#include "caf/ref_counted.hpp"
#include "caf/intrusive_ptr.hpp"
#include "caf/io/fwd.hpp"
#include "caf/io/network/operation.hpp"
namespace caf {
......@@ -33,14 +35,44 @@ namespace network {
/// for various IO operations.
class manager : public ref_counted {
public:
manager(abstract_broker* parent_ptr);
~manager();
/// Sets the parent for this manager.
/// @pre `parent() == nullptr`
void set_parent(abstract_broker* ptr);
/// Returns the parent broker of this manager.
inline abstract_broker* parent() {
return parent_;
}
/// Returns `true` if this manager has a parent, `false` otherwise.
inline bool detached() const {
return parent_ == nullptr;
}
/// Detach this manager from its parent and invoke `detach_message()``
/// if `invoke_detach_message == true`.
void detach(bool invoke_detach_message);
/// Causes the manager to stop read operations on its IO device.
/// Unwritten bytes are still send before the socket will be closed.
virtual void stop_reading() = 0;
/// Called by the underlying IO device to report failures.
virtual void io_failure(operation op) = 0;
protected:
/// Creates a message signalizing a disconnect to the parent.
virtual message detach_message() = 0;
/// Detaches this manager from its parent.
virtual void detach_from_parent() = 0;
private:
abstract_broker* parent_;
};
} // namespace network
......
......@@ -32,6 +32,8 @@ namespace network {
/// for incoming data as well as for error handling.
class stream_manager : public manager {
public:
stream_manager(abstract_broker* ptr);
~stream_manager();
/// Called by the underlying IO device whenever it received data.
......
......@@ -77,7 +77,7 @@ public:
bool& stopped_reading(connection_handle hdl);
abstract_broker::scribe_ptr& impl_ptr(connection_handle hdl);
intrusive_ptr<scribe>& impl_ptr(connection_handle hdl);
uint16_t& port(accept_handle hdl);
......@@ -85,7 +85,7 @@ public:
/// `false` otherwise.
bool& stopped_reading(accept_handle hdl);
abstract_broker::doorman_ptr& impl_ptr(accept_handle hdl);
intrusive_ptr<doorman>& impl_ptr(accept_handle hdl);
void add_pending_connect(accept_handle src, connection_handle hdl);
......@@ -128,13 +128,13 @@ private:
buffer_type wr_buf;
receive_policy::config recv_conf;
bool stopped_reading = false;
abstract_broker::scribe_ptr ptr;
intrusive_ptr<scribe> ptr;
};
struct doorman_data {
uint16_t port;
bool stopped_reading = false;
abstract_broker::doorman_ptr ptr;
intrusive_ptr<doorman> ptr;
};
std::mutex mx_;
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#ifndef CAF_IO_SCRIBE_HPP
#define CAF_IO_SCRIBE_HPP
#include <vector>
#include "caf/message.hpp"
#include "caf/io/receive_policy.hpp"
#include "caf/io/system_messages.hpp"
#include "caf/io/network/stream_manager.hpp"
namespace caf {
namespace io {
/// Manages a stream.
/// @ingroup Broker
class scribe : public network::stream_manager {
public:
scribe(abstract_broker* parent, connection_handle hdl);
~scribe();
/// Implicitly starts the read loop on first call.
virtual void configure_read(receive_policy::config config) = 0;
/// Grants access to the output buffer.
virtual std::vector<char>& wr_buf() = 0;
/// Flushes the output buffer, i.e., sends the content of
/// the buffer via the network.
virtual void flush() = 0;
inline connection_handle hdl() const {
return hdl_;
}
void io_failure(network::operation op) override;
void consume(const void* data, size_t num_bytes) override;
protected:
virtual std::vector<char>& rd_buf() = 0;
inline new_data_msg& read_msg() {
return read_msg_.get_as_mutable<new_data_msg>(0);
}
inline const new_data_msg& read_msg() const {
return read_msg_.get_as<new_data_msg>(0);
}
void detach_from_parent() override;
message detach_message() override;
private:
connection_handle hdl_;
message read_msg_;
};
} // namespace io
} // namespace caf
#endif // CAF_IO_SCRIBE_HPP
......@@ -97,114 +97,6 @@ void abstract_broker::cleanup(uint32_t reason) {
deref(); // release implicit reference count from middleman
}
void abstract_broker::servant::set_broker(abstract_broker* new_broker) {
if (! disconnected_) {
broker_ = new_broker;
}
}
abstract_broker::servant::~servant() {
CAF_LOG_TRACE("");
}
abstract_broker::servant::servant(abstract_broker* ptr) : disconnected_(false), broker_(ptr) {
// nop
}
void abstract_broker::servant::disconnect(bool invoke_disconnect_message) {
CAF_LOG_TRACE("");
if (! disconnected_) {
CAF_LOG_DEBUG("disconnect servant from broker");
disconnected_ = true;
remove_from_broker();
if (invoke_disconnect_message) {
auto msg = disconnect_message();
broker_->invoke_message(broker_->address(),invalid_message_id, msg);
}
}
}
abstract_broker::scribe::scribe(abstract_broker* ptr, connection_handle conn_hdl)
: servant(ptr),
hdl_(conn_hdl) {
std::vector<char> tmp;
read_msg_ = make_message(new_data_msg{hdl_, std::move(tmp)});
}
void abstract_broker::scribe::remove_from_broker() {
CAF_LOG_TRACE("hdl = " << hdl().id());
broker_->scribes_.erase(hdl());
}
abstract_broker::scribe::~scribe() {
CAF_LOG_TRACE("");
}
message abstract_broker::scribe::disconnect_message() {
return make_message(connection_closed_msg{hdl()});
}
void abstract_broker::scribe::consume(const void*, size_t num_bytes) {
CAF_LOG_TRACE(CAF_ARG(num_bytes));
if (disconnected_) {
// 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;
}
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);
read_msg().buf.swap(buf);
broker_->invoke_message(invalid_actor_addr, invalid_message_id, read_msg_);
// swap buffer back to stream and implicitly flush wr_buf()
if (broker_->exit_reason() == exit_reason::not_exited) {
read_msg().buf.swap(buf);
flush();
}
}
void abstract_broker::scribe::io_failure(network::operation op) {
CAF_LOG_TRACE("id = " << hdl().id()
<< ", " << CAF_TARG(op, static_cast<int>));
// keep compiler happy when compiling w/o logging
static_cast<void>(op);
disconnect(true);
}
abstract_broker::doorman::doorman(abstract_broker* ptr,
accept_handle acc_hdl,
uint16_t p)
: servant(ptr),
hdl_(acc_hdl),
port_(p) {
auto hdl2 = connection_handle::from_int(-1);
accept_msg_ = make_message(new_connection_msg{hdl_, hdl2});
}
abstract_broker::doorman::~doorman() {
CAF_LOG_TRACE("");
}
void abstract_broker::doorman::remove_from_broker() {
CAF_LOG_TRACE("hdl = " << hdl().id());
broker_->doormen_.erase(hdl());
}
message abstract_broker::doorman::disconnect_message() {
return make_message(acceptor_closed_msg{hdl()});
}
void abstract_broker::doorman::io_failure(network::operation op) {
CAF_LOG_TRACE("id = " << hdl().id() << ", "
<< CAF_TARG(op, static_cast<int>));
// keep compiler happy when compiling w/o logging
static_cast<void>(op);
disconnect(true);
}
abstract_broker::~abstract_broker() {
CAF_LOG_TRACE("");
}
......@@ -216,7 +108,7 @@ void abstract_broker::configure_read(connection_handle hdl,
by_id(hdl).configure_read(cfg);
}
abstract_broker::buffer_type& abstract_broker::wr_buf(connection_handle hdl) {
std::vector<char>& abstract_broker::wr_buf(connection_handle hdl) {
return by_id(hdl).wr_buf();
}
......@@ -240,6 +132,9 @@ std::vector<connection_handle> abstract_broker::connections() const {
return result;
}
void abstract_broker::add_scribe(const intrusive_ptr<scribe>& ptr) {
scribes_.emplace(ptr->hdl(), ptr);
}
connection_handle abstract_broker::add_tcp_scribe(const std::string& hostname,
uint16_t port) {
CAF_LOG_TRACE(CAF_ARG(hostname) << ", " << CAF_ARG(port));
......@@ -257,6 +152,12 @@ abstract_broker::add_tcp_scribe(network::native_socket fd) {
return backend().add_tcp_scribe(this, fd);
}
void abstract_broker::add_doorman(const intrusive_ptr<doorman>& ptr) {
doormen_.emplace(ptr->hdl(), ptr);
if (is_initialized())
ptr->launch();
}
std::pair<accept_handle, uint16_t>
abstract_broker::add_tcp_doorman(uint16_t port, const char* in,
bool reuse_addr) {
......@@ -351,13 +252,13 @@ void abstract_broker::invoke_message(mailbox_element_ptr& ptr) {
}
void abstract_broker::invoke_message(const actor_addr& sender,
message_id mid, message& msg) {
message_id mid,
message& msg) {
auto ptr = mailbox_element::make(sender, mid, message{});
ptr->msg.swap(msg);
invoke_message(ptr);
if (ptr) {
if (ptr)
ptr->msg.swap(msg);
}
}
void abstract_broker::close_all() {
......
......@@ -23,6 +23,10 @@ namespace caf {
namespace io {
namespace network {
acceptor_manager::acceptor_manager(abstract_broker* ptr) : manager(ptr) {
// nop
}
acceptor_manager::~acceptor_manager() {
// nop
}
......
This diff is collapsed.
......@@ -83,9 +83,9 @@ actor_proxy_ptr basp_broker_state::make_proxy(const node_id& nid,
});
// tell remote side we are monitoring this actor now
instance.write(self->wr_buf(this_context->hdl),
basp::message_type::announce_proxy_instance, nullptr, 0,
this_node(), nid,
invalid_actor_id, aid,
nullptr, basp::announce_proxy_instance, 0);
invalid_actor_id, aid);
instance.tbl().flush(*path);
self->parent().notify<hook::new_remote_actor>(res->address());
return res;
......
......@@ -733,7 +733,7 @@ void default_multiplexer::dispatch_runnable(runnable_ptr ptr) {
connection_handle default_multiplexer::add_tcp_scribe(abstract_broker* self,
default_socket&& sock) {
CAF_LOG_TRACE("");
class impl : public abstract_broker::scribe {
class impl : public scribe {
public:
impl(abstract_broker* ptr, default_socket&& s)
: scribe(ptr, network::conn_hdl_from_socket(s)),
......@@ -746,16 +746,16 @@ connection_handle default_multiplexer::add_tcp_scribe(abstract_broker* self,
stream_.configure_read(config);
if (! launched_) launch();
}
abstract_broker::buffer_type& wr_buf() override {
std::vector<char>& wr_buf() override {
return stream_.wr_buf();
}
abstract_broker::buffer_type& rd_buf() override {
std::vector<char>& rd_buf() override {
return stream_.rd_buf();
}
void stop_reading() override {
CAF_LOG_TRACE("");
stream_.stop_reading();
disconnect(false);
detach(false);
}
void flush() override {
CAF_LOG_TRACE("");
......@@ -771,7 +771,7 @@ connection_handle default_multiplexer::add_tcp_scribe(abstract_broker* self,
bool launched_;
stream<default_socket> stream_;
};
abstract_broker::scribe_ptr ptr = make_counted<impl>(self, std::move(sock));
auto ptr = make_counted<impl>(self, std::move(sock));
self->add_scribe(ptr);
return ptr->hdl();
}
......@@ -781,7 +781,7 @@ default_multiplexer::add_tcp_doorman(abstract_broker* self,
default_socket_acceptor&& sock) {
CAF_LOG_TRACE("sock.fd = " << sock.fd());
CAF_ASSERT(sock.fd() != network::invalid_native_socket);
class impl : public abstract_broker::doorman {
class impl : public doorman {
public:
impl(abstract_broker* ptr, default_socket_acceptor&& s)
: doorman(ptr, network::accept_hdl_from_socket(s), port_of_fd(s.fd())),
......@@ -799,7 +799,7 @@ default_multiplexer::add_tcp_doorman(abstract_broker* self,
void stop_reading() override {
CAF_LOG_TRACE("");
acceptor_.stop_reading();
disconnect(false);
detach(false);
}
void launch() override {
CAF_LOG_TRACE("");
......@@ -808,7 +808,7 @@ default_multiplexer::add_tcp_doorman(abstract_broker* self,
private:
network::acceptor<default_socket_acceptor> acceptor_;
};
abstract_broker::doorman_ptr ptr = make_counted<impl>(self, std::move(sock));
auto ptr = make_counted<impl>(self, std::move(sock));
self->add_doorman(ptr);
return ptr->hdl();
}
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/io/doorman.hpp"
#include "caf/detail/logging.hpp"
#include "caf/io/abstract_broker.hpp"
namespace caf {
namespace io {
doorman::doorman(abstract_broker* ptr, accept_handle acc_hdl, uint16_t p)
: network::acceptor_manager(ptr),
hdl_(acc_hdl),
accept_msg_(make_message(new_connection_msg{hdl_, connection_handle{}})),
port_(p) {
// nop
}
doorman::~doorman() {
// nop
}
void doorman::detach_from_parent() {
CAF_LOG_TRACE("hdl = " << hdl().id());
parent()->doormen_.erase(hdl());
}
message doorman::detach_message() {
return make_message(acceptor_closed_msg{hdl()});
}
void doorman::io_failure(network::operation op) {
CAF_LOG_TRACE("id = " << hdl().id() << ", "
<< CAF_TARG(op, static_cast<int>));
// keep compiler happy when compiling w/o logging
static_cast<void>(op);
detach(true);
}
} // namespace io
} // namespace caf
......@@ -19,14 +19,40 @@
#include "caf/io/network/manager.hpp"
#include "caf/detail/logging.hpp"
#include "caf/io/abstract_broker.hpp"
namespace caf {
namespace io {
namespace network {
manager::manager(abstract_broker* ptr) : parent_(ptr) {
// nop
}
manager::~manager() {
// nop
}
void manager::set_parent(abstract_broker* ptr) {
if (! detached())
parent_ = ptr;
}
void manager::detach(bool invoke_disconnect_message) {
CAF_LOG_TRACE("");
if (! detached()) {
CAF_LOG_DEBUG("disconnect servant from broker");
detach_from_parent();
if (invoke_disconnect_message) {
auto msg = detach_message();
parent_->invoke_message(parent_->address(),invalid_message_id, msg);
}
parent_ = nullptr;
}
}
} // namespace network
} // namespace io
} // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2015 *
* Dominik Charousset <dominik.charousset (at) haw-hamburg.de> *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#include "caf/io/scribe.hpp"
#include "caf/detail/logging.hpp"
#include "caf/io/abstract_broker.hpp"
namespace caf {
namespace io {
scribe::scribe(abstract_broker* ptr, connection_handle conn_hdl)
: network::stream_manager(ptr),
hdl_(conn_hdl) {
std::vector<char> tmp;
read_msg_ = make_message(new_data_msg{hdl_, std::move(tmp)});
}
void scribe::detach_from_parent() {
CAF_LOG_TRACE("hdl = " << hdl().id());
parent()->scribes_.erase(hdl());
}
scribe::~scribe() {
CAF_LOG_TRACE("");
}
message scribe::detach_message() {
return make_message(connection_closed_msg{hdl()});
}
void scribe::consume(const void*, size_t num_bytes) {
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;
}
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);
read_msg().buf.swap(buf);
parent()->invoke_message(invalid_actor_addr, invalid_message_id, read_msg_);
// swap buffer back to stream and implicitly flush wr_buf()
read_msg().buf.swap(buf);
flush();
}
void scribe::io_failure(network::operation op) {
CAF_LOG_TRACE("id = " << hdl().id()
<< ", " << CAF_TARG(op, static_cast<int>));
// keep compiler happy when compiling w/o logging
static_cast<void>(op);
detach(true);
}
} // namespace io
} // namespace caf
......@@ -23,6 +23,10 @@ namespace caf {
namespace io {
namespace network {
stream_manager::stream_manager(abstract_broker* ptr) : manager(ptr) {
// nop
}
stream_manager::~stream_manager() {
// nop
}
......
......@@ -40,32 +40,32 @@ connection_handle test_multiplexer::new_tcp_scribe(const std::string& host,
void test_multiplexer::assign_tcp_scribe(abstract_broker* ptr,
connection_handle hdl) {
class impl : public abstract_broker::scribe {
class impl : public scribe {
public:
impl(abstract_broker* self, connection_handle ch, test_multiplexer* mpx)
: abstract_broker::scribe(self, ch),
: scribe(self, ch),
mpx_(mpx) {
// nop
}
void configure_read(receive_policy::config config) {
void configure_read(receive_policy::config config) override {
mpx_->read_config(hdl()) = config;
}
abstract_broker::buffer_type& wr_buf() {
std::vector<char>& wr_buf() override {
return mpx_->output_buffer(hdl());
}
abstract_broker::buffer_type& rd_buf() {
std::vector<char>& rd_buf() override {
return mpx_->input_buffer(hdl());
}
void stop_reading() {
void stop_reading() override {
mpx_->stopped_reading(hdl()) = true;
disconnect(false);
detach(false);
}
void flush() {
void flush() override {
// nop
}
......@@ -106,7 +106,7 @@ test_multiplexer::new_tcp_doorman(uint16_t port, const char*, bool) {
void test_multiplexer::assign_tcp_doorman(abstract_broker* ptr,
accept_handle hdl) {
class impl : public abstract_broker::doorman {
class impl : public doorman {
public:
impl(abstract_broker* self, accept_handle ah, test_multiplexer* mpx)
: doorman(self, ah, mpx->port(ah)),
......@@ -127,7 +127,7 @@ void test_multiplexer::assign_tcp_doorman(abstract_broker* ptr,
void stop_reading() {
mpx_->stopped_reading(hdl()) = true;
disconnect(false);
detach(false);
}
void launch() {
......@@ -204,7 +204,7 @@ bool& test_multiplexer::stopped_reading(connection_handle hdl) {
return scribe_data_[hdl].stopped_reading;
}
abstract_broker::scribe_ptr& test_multiplexer::impl_ptr(connection_handle hdl) {
intrusive_ptr<scribe>& test_multiplexer::impl_ptr(connection_handle hdl) {
return scribe_data_[hdl].ptr;
}
......@@ -216,7 +216,7 @@ bool& test_multiplexer::stopped_reading(accept_handle hdl) {
return doorman_data_[hdl].stopped_reading;
}
abstract_broker::doorman_ptr& test_multiplexer::impl_ptr(accept_handle hdl) {
intrusive_ptr<doorman>& test_multiplexer::impl_ptr(accept_handle hdl) {
return doorman_data_[hdl].ptr;
}
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment