Commit 2e6411dc authored by Dominik Charousset's avatar Dominik Charousset

Modularize network backend

parent 89d97d9f
......@@ -3,7 +3,7 @@ project(caf_io C CXX)
# get header files; only needed by CMake generators,
# e.g., for creating proper Xcode projects
file(GLOB LIBCAF_IO_HDRS "caf/io/*.hpp")
file(GLOB LIBCAF_IO_HDRS "caf/io/*.hpp" "caf/io/network/*.hpp")
# list cpp files excluding platform-dependent files
set (LIBCAF_IO_SRCS
......@@ -12,10 +12,14 @@ set (LIBCAF_IO_SRCS
src/max_msg_size.cpp
src/middleman.cpp
src/hook.cpp
src/network.cpp
src/default_multiplexer.cpp
src/publish_local_groups.cpp
src/remote_actor_proxy.cpp
src/remote_group.cpp)
src/remote_group.cpp
src/manager.cpp
src/stream_manager.cpp
src/acceptor_manager.cpp
src/multiplexer.cpp)
# build shared library if not compiling static only
if (NOT "${CAF_BUILD_STATIC_ONLY}" STREQUAL "yes")
......
This diff is collapsed.
......@@ -52,11 +52,16 @@ class basp_broker : public broker, public actor_namespace::backend {
behavior make_behavior() override;
/*
template <class SocketAcceptor>
void publish(abstract_actor_ptr whom, SocketAcceptor fd) {
auto hdl = add_acceptor(std::move(fd));
announce_published_actor(hdl, whom);
}
*/
void announce_published_actor(accept_handle hdl,
const abstract_actor_ptr& whom);
actor_proxy_ptr make_proxy(const id_type&, actor_id) override;
......@@ -132,9 +137,6 @@ class basp_broker : public broker, public actor_namespace::backend {
optional<skip_message_t> kill_proxy(connection_context& ctx, actor_id aid,
std::uint32_t reason);
void announce_published_actor(accept_handle hdl,
const abstract_actor_ptr& whom);
void new_data(connection_context& ctx, buffer_type& buf);
void init_handshake_as_client(connection_context& ctx,
......
......@@ -27,17 +27,20 @@
#include "caf/extend.hpp"
#include "caf/local_actor.hpp"
#include "caf/io/network.hpp"
#include "caf/io/accept_handle.hpp"
#include "caf/io/system_messages.hpp"
#include "caf/io/connection_handle.hpp"
#include "caf/mixin/functor_based.hpp"
#include "caf/mixin/behavior_stack_based.hpp"
#include "caf/policy/not_prioritizing.hpp"
#include "caf/policy/sequential_invoke.hpp"
#include "caf/io/fwd.hpp"
#include "caf/io/accept_handle.hpp"
#include "caf/io/receive_policy.hpp"
#include "caf/io/system_messages.hpp"
#include "caf/io/connection_handle.hpp"
#include "caf/io/network/stream_manager.hpp"
#include "caf/io/network/acceptor_manager.hpp"
namespace caf {
namespace io {
......@@ -76,6 +79,10 @@ class broker : public extend<local_actor>::
virtual message disconnect_message() = 0;
inline broker* parent() {
return m_broker;
}
servant(broker* ptr);
void set_broker(broker* ptr);
......@@ -140,6 +147,8 @@ class broker : public extend<local_actor>::
message m_read_msg;
};
using scribe_pointer = intrusive_ptr<scribe>;
/**
* Manages incoming connections.
*/
......@@ -176,6 +185,8 @@ class broker : public extend<local_actor>::
message m_accept_msg;
};
using doorman_pointer = intrusive_ptr<doorman>;
class continuation;
// a broker needs friends
......@@ -241,6 +252,20 @@ class broker : public extend<local_actor>::
fun, hdl, std::forward<Ts>(vs)...);
}
inline void add_scribe(const scribe_pointer& ptr) {
m_scribes.insert(std::make_pair(ptr->hdl(), ptr));
}
inline void add_doorman(const doorman_pointer& ptr) {
m_doormen.insert(std::make_pair(ptr->hdl(), ptr));
if (is_initialized()) {
ptr->launch();
}
}
void invoke_message(const actor_addr& sender, message_id mid, message& msg);
/*
template <class Socket>
connection_handle add_connection(Socket sock) {
CAF_LOG_TRACE("");
......@@ -290,7 +315,7 @@ class broker : public extend<local_actor>::
template <class SocketAcceptor>
accept_handle add_acceptor(SocketAcceptor sock) {
CAF_LOG_TRACE("sock.fd = " << sock.fd());
CAF_REQUIRE(sock.fd() != network::invalid_socket);
CAF_REQUIRE(sock.fd() != network::invalid_native_socket);
class impl : public doorman {
public:
impl(broker* parent, SocketAcceptor&& s)
......@@ -322,6 +347,7 @@ class broker : public extend<local_actor>::
}
return ptr->hdl();
}
*/
void enqueue(const actor_addr&, message_id, message,
execution_unit*) override;
......@@ -381,10 +407,6 @@ class broker : public extend<local_actor>::
void cleanup(uint32_t reason);
using scribe_pointer = intrusive_ptr<scribe>;
using doorman_pointer = intrusive_ptr<doorman>;
virtual behavior make_behavior() = 0;
/** @endcond */
......@@ -413,9 +435,6 @@ class broker : public extend<local_actor>::
// throws on error
inline doorman& by_id(accept_handle hdl) { return by_id(hdl, m_doormen); }
void invoke_message(const actor_addr& sender, message_id mid,
message& msg);
bool invoke_message_from_cache();
void erase_io(int id);
......
......@@ -29,7 +29,13 @@ class middleman;
class receive_policy;
class remote_actor_proxy;
namespace network {
class multiplexer;
} // namespace network
} // namespace io
} // namespace caf
#endif // CAF_IO_FWD_HPP
\ No newline at end of file
#endif // CAF_IO_FWD_HPP
......@@ -32,7 +32,7 @@
#include "caf/io/hook.hpp"
#include "caf/io/broker.hpp"
#include "caf/io/network.hpp"
#include "caf/io/network/multiplexer.hpp"
namespace caf {
namespace io {
......@@ -78,14 +78,14 @@ class middleman : public detail::abstract_singleton {
*/
template <class F>
void run_later(F fun) {
m_backend.dispatch(fun);
m_backend->dispatch(fun);
}
/**
* Returns the IO backend used by this middleman.
*/
inline network::multiplexer& backend() {
return m_backend;
return *m_backend;
}
/**
......@@ -128,9 +128,9 @@ class middleman : public detail::abstract_singleton {
// guarded by singleton-getter `instance`
middleman();
// networking backend
network::multiplexer m_backend;
std::unique_ptr<network::multiplexer> m_backend;
// prevents backend from shutting down unless explicitly requested
network::supervisor* m_supervisor;
network::multiplexer::supervisor_ptr m_supervisor;
// runs the backend
std::thread m_thread;
// keeps track of "singleton-like" brokers
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* 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 LICENCE_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_NETWORK_ACCEPTOR_MANAGER_HPP
#define CAF_IO_NETWORK_ACCEPTOR_MANAGER_HPP
#include "caf/io/network/manager.hpp"
namespace caf {
namespace io {
namespace network {
/**
* An acceptor manager configures an acceptor and provides
* callbacks for incoming connections as well as for error handling.
*/
class acceptor_manager : public manager {
public:
~acceptor_manager();
/**
* Called by the underlying IO device to indicate that
* a new connection is awaiting acceptance.
*/
virtual void new_connection() = 0;
};
} // namespace network
} // namespace io
} // namespace caf
#endif // CAF_IO_NETWORK_ACCEPTOR_MANAGER_HPP
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* 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 LICENCE_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_NETWORK_MANAGER_HPP
#define CAF_IO_NETWORK_MANAGER_HPP
#include "caf/ref_counted.hpp"
#include "caf/intrusive_ptr.hpp"
#include "caf/io/network/operation.hpp"
namespace caf {
namespace io {
namespace network {
/**
* A manager configures an IO device and provides callbacks
* for various IO operations.
*/
class manager : public ref_counted {
public:
virtual ~manager();
/**
* 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;
};
/**
* @relates manager
*/
using manager_ptr = intrusive_ptr<manager>;
} // namespace network
} // namespace io
} // namespace caf
#endif // CAF_IO_NETWORK_MANAGER_HPP
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* 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 LICENCE_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_NETWORK_MULTIPLEXER_HPP
#define CAF_IO_NETWORK_MULTIPLEXER_HPP
#include <string>
#include <thread>
#include <functional>
#include "caf/extend.hpp"
#include "caf/memory_managed.hpp"
#include "caf/io/fwd.hpp"
#include "caf/io/accept_handle.hpp"
#include "caf/io/connection_handle.hpp"
#include "caf/io/network/native_socket.hpp"
#include "caf/mixin/memory_cached.hpp"
#include "caf/detail/memory.hpp"
namespace boost {
namespace asio {
class io_service;
} // namespace asio
} // namespace boost
namespace caf {
namespace io {
namespace network {
/**
* Low-level backend for IO multiplexing.
*/
class multiplexer {
public:
virtual ~multiplexer();
/**
* Creates a new TCP doorman from a native socket handle.
*/
virtual connection_handle add_tcp_scribe(broker* ptr, native_socket fd) = 0;
/**
* Tries to connect to host `h` on given `port` and returns a
* new scribe managing the connection on success.
*/
virtual connection_handle add_tcp_scribe(broker* ptr, const std::string& h,
uint16_t port) = 0;
/**
* Creates a new TCP doorman from a native socket handle.
*/
virtual accept_handle add_tcp_doorman(broker* ptr, native_socket fd) = 0;
/**
* Tries to create a new TCP doorman running on port `p`, optionally
* accepting only connections from host `h`.
*/
virtual accept_handle add_tcp_doorman(broker* ptr, uint16_t p,
const char* h = nullptr) = 0;
/**
* Simple wrapper for runnables
*/
struct runnable : extend<memory_managed>::with<mixin::memory_cached> {
virtual void run() = 0;
virtual ~runnable();
};
using runnable_ptr = std::unique_ptr<runnable, detail::disposer>;
/**
* Makes sure the multipler does not exit its event loop until
* the destructor of `supervisor` has been called.
*/
struct supervisor {
public:
virtual ~supervisor();
};
using supervisor_ptr = std::unique_ptr<supervisor>;
/**
* Creates a supervisor to keep the event loop running.
*/
virtual supervisor_ptr make_supervisor() = 0;
/**
* Creates an instance using the networking backend compiled with CAF.
*/
static std::unique_ptr<multiplexer> make();
/**
* Runs the multiplexers event loop.
*/
virtual void run() = 0;
/**
* Invokes @p fun in the multiplexer's event loop.
*/
template <class F>
void dispatch(F fun) {
if (std::this_thread::get_id() == thread_id()) {
fun();
return;
}
struct impl : runnable {
F f;
impl(F&& mf) : f(std::move(mf)) { }
void run() override {
f();
}
};
dispatch_runnable(runnable_ptr{detail::memory::create<impl>(std::move(fun))});
}
/**
* Retrieves a pointer to the implementation or `nullptr` if CAF was
* compiled using the default backend.
*/
virtual boost::asio::io_service* pimpl();
inline const std::thread::id& thread_id() const {
return m_tid;
}
inline void thread_id(std::thread::id tid) {
m_tid = std::move(tid);
}
protected:
/**
* Implementation-specific dispatching to the multiplexer's thread.
*/
virtual void dispatch_runnable(runnable_ptr ptr) = 0;
/**
* Must be set by the subclass.
*/
std::thread::id m_tid;
};
using multiplexer_ptr = std::unique_ptr<multiplexer>;
} // namespace network
} // namespace io
} // namespace caf
#endif // CAF_IO_NETWORK_MULTIPLEXER_HPP
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* 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 LICENCE_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_NETWORK_NATIVE_SOCKET_HPP
#define CAF_IO_NETWORK_NATIVE_SOCKET_HPP
#include "caf/config.hpp"
#ifdef CAF_WINDOWS
# include <winsock2.h>
#endif
namespace caf {
namespace io {
namespace network {
#ifdef CAF_WINDOWS
using native_socket = SOCKET;
constexpr native_socket invalid_native_socket = INVALID_SOCKET;
#else
using native_socket = int;
constexpr native_socket invalid_native_socket = -1;
#endif
} // namespace network
} // namespace io
} // namespace caf
#endif // CAF_IO_NETWORK_NATIVE_SOCKET_HPP
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* 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 LICENCE_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_NETWORK_OPERATION_HPP
#define CAF_IO_NETWORK_OPERATION_HPP
namespace caf {
namespace io {
namespace network {
/**
* Identifies network IO operations, i.e., read or write.
*/
enum class operation {
read,
write,
propagate_error
};
} // namespace network
} // namespace io
} // namespace caf
#endif // CAF_IO_NETWORK_OPERATION_HPP
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* 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 LICENCE_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_NETWORK_STREAM_MANAGER_HPP
#define CAF_IO_NETWORK_STREAM_MANAGER_HPP
#include <cstddef>
#include "caf/io/network/manager.hpp"
namespace caf {
namespace io {
namespace network {
/**
* A stream manager configures an IO stream and provides callbacks
* for incoming data as well as for error handling.
*/
class stream_manager : public manager {
public:
virtual ~stream_manager();
/**
* Called by the underlying IO device whenever it received data.
*/
virtual void consume(const void* data, size_t num_bytes) = 0;
};
} // namespace network
} // namespace io
} // namespace caf
#endif // CAF_IO_NETWORK_STREAM_MANAGER_HPP
......@@ -20,38 +20,40 @@
#ifndef CAF_IO_PUBLISH_IMPL_HPP
#define CAF_IO_PUBLISH_IMPL_HPP
#include <future>
#include "caf/actor_cast.hpp"
#include "caf/abstract_actor.hpp"
#include "caf/detail/singletons.hpp"
#include "caf/detail/actor_registry.hpp"
#include "caf/io/network.hpp"
#include "caf/io/middleman.hpp"
#include "caf/io/basp_broker.hpp"
namespace caf {
namespace io {
template <class ActorHandle, class SocketAcceptor>
void publish_impl(ActorHandle whom, SocketAcceptor fd, uint16_t port) {
template <class... Ts>
void publish_impl(abstract_actor_ptr whom, uint16_t port, Ts&&... args) {
using namespace detail;
auto mm = middleman::instance();
// we can't move fd into our lambda in C++11 ...
using pair_type = std::pair<ActorHandle, SocketAcceptor>;
auto data = std::make_shared<pair_type>(whom, std::move(fd));
mm->run_later([mm, data, whom, port] {
std::promise<bool> res;
mm->run_later([&] {
auto bro = mm->get_named_broker<basp_broker>(atom("_BASP"));
bro->publish(std::move(data->first), std::move(data->second));
mm->notify<hook::actor_published>(whom->address(), port);
try {
auto hdl = mm->backend().add_tcp_doorman(bro.get(), port,
std::forward<Ts>(args)...);
bro->announce_published_actor(hdl, whom);
mm->notify<hook::actor_published>(whom->address(), port);
res.set_value(true);
}
catch (...) {
res.set_exception(std::current_exception());
}
});
}
inline void publish_impl(abstract_actor_ptr whom, uint16_t port,
const char* ipaddr) {
using namespace detail;
auto mm = middleman::instance();
network::default_socket_acceptor fd{mm->backend()};
network::ipv4_bind(fd, port, ipaddr);
publish_impl(std::move(whom), std::move(fd), port);
// block caller and re-throw exception here in case of an error
res.get_future().get();
}
} // namespace io
......
......@@ -56,7 +56,7 @@ inline actor remote_actor(Socket fd) {
* @throws std::invalid_argument Thrown when connecting to a typed actor.
*/
inline actor remote_actor(const char* host, uint16_t port) {
auto res = remote_actor_impl(host, port, std::set<std::string>{});
auto res = remote_actor_impl(std::set<std::string>{}, host, port);
return actor_cast<actor>(res);
}
......@@ -64,7 +64,7 @@ inline actor remote_actor(const char* host, uint16_t port) {
* @copydoc remote_actor(const char*, uint16_t)
*/
inline actor remote_actor(const std::string& host, uint16_t port) {
auto res = remote_actor_impl(host, port, std::set<std::string>{});
auto res = remote_actor_impl(std::set<std::string>{}, host, port);
return actor_cast<actor>(res);
}
......
......@@ -31,9 +31,9 @@
#include "caf/abstract_actor.hpp"
#include "caf/binary_deserializer.hpp"
#include "caf/io/network.hpp"
#include "caf/io/middleman.hpp"
#include "caf/io/basp_broker.hpp"
#include "caf/io/network/multiplexer.hpp"
#include "caf/detail/logging.hpp"
......@@ -44,36 +44,34 @@ constexpr uint32_t max_iface_size = 100;
constexpr uint32_t max_iface_clause_size = 500;
template <class Socket>
abstract_actor_ptr remote_actor_impl(Socket fd,
const std::set<std::string>& ifs) {
using string_set = std::set<std::string>;
template <class... Ts>
abstract_actor_ptr remote_actor_impl(const std::set<std::string>& ifs,
Ts&&... args) {
auto mm = middleman::instance();
std::string error_msg;
std::promise<abstract_actor_ptr> result_promise;
// we can't move fd into our lambda in C++11 ...
auto fd_ptr = std::make_shared<Socket>(std::move(fd));
basp_broker::client_handshake_data hdata{
invalid_node_id, &result_promise, &error_msg, &ifs};
auto hdata_ptr = &hdata;
mm->run_later([=] {
auto bro = mm->get_named_broker<basp_broker>(atom("_BASP"));
auto hdl = bro->add_connection(std::move(*fd_ptr));
bro->init_client(hdl, hdata_ptr);
basp_broker::client_handshake_data hdata{invalid_node_id, &result_promise,
&error_msg, &ifs};
mm->run_later([&] {
try {
auto bro = mm->get_named_broker<basp_broker>(atom("_BASP"));
auto hdl = mm->backend().add_tcp_scribe(bro.get(),
std::forward<Ts>(args)...);
bro->init_client(hdl, &hdata);
}
catch (...) {
result_promise.set_exception(std::current_exception());
}
});
auto result = result_promise.get_future().get();
if (!result) throw std::runtime_error(error_msg);
if (!result) {
throw std::runtime_error(error_msg);
}
return result;
}
inline abstract_actor_ptr
remote_actor_impl(const std::string& host, uint16_t port,
const std::set<std::string>& ifs) {
auto mm = middleman::instance();
network::default_socket fd{mm->backend()};
network::ipv4_connect(fd, host, port);
return remote_actor_impl(std::move(fd), ifs);
}
} // namespace io
} // namespace caf
......
......@@ -26,6 +26,8 @@
#include "caf/io/middleman.hpp"
#include "caf/io/connection_handle.hpp"
#include "caf/io/network/native_socket.hpp"
namespace caf {
namespace io {
......@@ -34,9 +36,8 @@ namespace io {
*/
template <spawn_options Os = no_spawn_options,
typename F = std::function<void(broker*)>, class... Ts>
actor spawn_io(F fun, Ts&&... args) {
return spawn<broker::functor_based>(std::move(fun),
std::forward<Ts>(args)...);
actor spawn_io(F fun, Ts&&... vs) {
return spawn<broker::functor_based>(std::move(fun), std::forward<Ts>(vs)...);
}
/**
......@@ -45,63 +46,36 @@ actor spawn_io(F fun, Ts&&... args) {
template <spawn_options Os = no_spawn_options,
typename F = std::function<void(broker*)>, class... Ts>
actor spawn_io_client(F fun, const std::string& host,
uint16_t port, Ts&&... args) {
network::default_socket sock{middleman::instance()->backend()};
network::ipv4_connect(sock, host, port);
auto hdl = network::conn_hdl_from_socket(sock);
uint16_t port, Ts&&... vs) {
// provoke compiler error early
using fun_res = decltype(fun((broker*) 0, hdl, std::forward<Ts>(args)...));
using fun_res = decltype(fun(static_cast<broker*>(nullptr),
connection_handle{},
std::forward<Ts>(vs)...));
// prevent warning about unused local type
static_assert(std::is_same<fun_res, fun_res>::value,
"your compiler is lying to you");
"your compiler is lying to you");
return spawn_class<broker::functor_based>(
nullptr,
[&](broker* ptr) {
auto hdl2 = ptr->add_connection(std::move(sock));
CAF_REQUIRE(hdl == hdl2);
static_cast<void>(hdl2); // prevent warning
},
std::move(fun), hdl, std::forward<Ts>(args)...);
[&](broker::functor_based* ptr) {
auto mm = middleman::instance();
auto hdl = mm->backend().add_tcp_scribe(ptr, host, port);
ptr->init(std::move(fun), hdl, std::forward<Ts>(vs)...);
});
}
struct is_socket_test {
template <class T>
static auto test(T* ptr) -> decltype(ptr->native_handle(),
std::true_type{});
template <class>
static auto test(...) -> std::false_type;
};
template <class T>
struct is_socket : decltype(is_socket_test::test<T>(0)) {
};
/**
* Spawns a new broker as server running on given `port`.
*/
template <spawn_options Os = no_spawn_options,
typename F = std::function<void(broker*)>,
typename Socket = network::default_socket_acceptor, class... Ts>
typename std::enable_if<is_socket<Socket>::value, actor>::type
spawn_io_server(F fun, Socket sock, Ts&&... args) {
class F = std::function<void(broker*)>, class... Ts>
actor spawn_io_server(F fun, uint16_t port, Ts&&... vs) {
return spawn_class<broker::functor_based>(
nullptr,
[&](broker* ptr) {
ptr->add_acceptor(std::move(sock));
},
std::move(fun), std::forward<Ts>(args)...);
}
/**
* Spawns a new broker as server running on given `port`.
*/
template <spawn_options Os = no_spawn_options,
typename F = std::function<void(broker*)>, class... Ts>
actor spawn_io_server(F fun, uint16_t port, Ts&&... args) {
network::default_socket_acceptor fd{middleman::instance()->backend()};
network::ipv4_bind(fd, port);
return spawn_io_server(std::move(fun), std::move(fd),
std::forward<Ts>(args)...);
[&](broker::functor_based* ptr) {
auto mm = middleman::instance();
mm->backend().add_tcp_doorman(ptr, port);
ptr->init(std::move(fun), std::forward<Ts>(vs)...);
});
}
} // namespace io
......
......@@ -41,7 +41,7 @@ struct typed_remote_actor_helper<List<Ts...>> {
template <class... Vs>
return_type operator()(Vs&&... vs) {
auto iface = return_type::message_types();
auto tmp = remote_actor_impl(std::forward<Vs>(vs)..., std::move(iface));
auto tmp = remote_actor_impl(std::move(iface), std::forward<Vs>(vs)...);
return actor_cast<return_type>(tmp);
}
};
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* 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 LICENCE_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/network/acceptor_manager.hpp"
namespace caf {
namespace io {
namespace network {
acceptor_manager::~acceptor_manager() {
// nop
}
} // namespace network
} // namespace io
} // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* 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 LICENCE_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/network/manager.hpp"
namespace caf {
namespace io {
namespace network {
manager::~manager() {
// nop
}
} // namespace network
} // namespace io
} // namespace caf
......@@ -201,12 +201,13 @@ void middleman::add_broker(broker_ptr bptr) {
void middleman::initialize() {
CAF_LOG_TRACE("");
m_supervisor = new network::supervisor{m_backend};
m_backend = network::multiplexer::make();
m_supervisor = m_backend->make_supervisor();
m_thread = std::thread([this] {
CAF_LOGC_TRACE("caf::io::middleman", "initialize$run", "");
m_backend.run();
m_backend->run();
});
m_backend.m_tid = m_thread.get_id();
m_backend->thread_id(m_thread.get_id());
// announce io-related types
announce_helper<new_data_msg, new_connection_msg,
acceptor_closed_msg, connection_closed_msg,
......@@ -217,10 +218,8 @@ void middleman::initialize() {
void middleman::stop() {
CAF_LOG_TRACE("");
m_backend.dispatch([=] {
m_backend->dispatch([=] {
CAF_LOGC_TRACE("caf::io::middleman", "stop$lambda", "");
delete m_supervisor;
m_supervisor = nullptr;
// m_managers will be modified while we are stopping each manager,
// because each manager will call remove(...)
std::vector<broker_ptr> brokers;
......@@ -231,6 +230,7 @@ void middleman::stop() {
bro->close_all();
}
});
m_supervisor.reset();
m_thread.join();
m_named_brokers.clear();
}
......@@ -239,7 +239,7 @@ void middleman::dispose() {
delete this;
}
middleman::middleman() : m_supervisor(nullptr) {
middleman::middleman() {
// nop
}
......
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* 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 LICENCE_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/network/multiplexer.hpp"
#ifdef CAF_USE_ASIO
# include "caf/io/network/asio_multiplexer.hpp"
using caf_multiplexer_impl = caf::io::network::asio_multiplexer;
#else
# include "caf/io/network/default_multiplexer.hpp"
using caf_multiplexer_impl = caf::io::network::default_multiplexer;
#endif
namespace caf {
namespace io {
namespace network {
multiplexer::~multiplexer() {
// nop
}
boost::asio::io_service* pimpl() {
return nullptr;
}
multiplexer_ptr multiplexer::make() {
return multiplexer_ptr{new caf_multiplexer_impl};
}
boost::asio::io_service* multiplexer::pimpl() {
return nullptr;
}
multiplexer::supervisor::~supervisor() {
// nop
}
multiplexer::runnable::~runnable() {
// nop
}
} // namespace network
} // namespace io
} // namespace caf
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright (C) 2011 - 2014 *
* 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 LICENCE_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/network/stream_manager.hpp"
namespace caf {
namespace io {
namespace network {
stream_manager::~stream_manager() {
// nop
}
} // namespace network
} // namespace io
} // namespace caf
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