Commit 9fe86509 authored by Dominik Charousset's avatar Dominik Charousset

Merge pull request #317 from ufownl/topic/Achieve_complete_type_safe

Improve type safety of `typed_broker`
parents 63f63a1b 3b6f726a
...@@ -17,18 +17,19 @@ ...@@ -17,18 +17,19 @@
* http://www.boost.org/LICENSE_1_0.txt. * * http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/ ******************************************************************************/
#ifndef CAF_IO_TYPED_BROKER_HPP #ifndef CAF_IO_EXPERIMENTAL_TYPED_BROKER_HPP
#define CAF_IO_TYPED_BROKER_HPP #define CAF_IO_EXPERIMENTAL_TYPED_BROKER_HPP
#include <map> #include <map>
#include <vector> #include <vector>
#include <type_traits>
#include "caf/none.hpp" #include "caf/none.hpp"
#include "caf/config.hpp" #include "caf/config.hpp"
#include "caf/make_counted.hpp" #include "caf/make_counted.hpp"
#include "caf/spawn.hpp" #include "caf/spawn.hpp"
#include "caf/extend.hpp" #include "caf/extend.hpp"
#include "caf/typed_behavior.hpp" #include "caf/typed_actor.hpp"
#include "caf/local_actor.hpp" #include "caf/local_actor.hpp"
#include "caf/detail/logging.hpp" #include "caf/detail/logging.hpp"
...@@ -46,6 +47,13 @@ namespace caf { ...@@ -46,6 +47,13 @@ namespace caf {
namespace io { namespace io {
namespace experimental { namespace experimental {
using minimal_client = typed_actor<reacts_to<new_data_msg>,
reacts_to<connection_closed_msg>>;
using minimal_server =
minimal_client::extend<reacts_to<new_connection_msg>,
reacts_to<acceptor_closed_msg>>;
template <class... Sigs> template <class... Sigs>
class typed_broker; class typed_broker;
...@@ -73,6 +81,8 @@ class typed_broker : public abstract_event_based_actor<typed_behavior<Sigs...>, ...@@ -73,6 +81,8 @@ class typed_broker : public abstract_event_based_actor<typed_behavior<Sigs...>,
public: public:
using signatures = detail::type_list<Sigs...>; using signatures = detail::type_list<Sigs...>;
using actor_hdl = typed_actor<Sigs...>;
using behavior_type = typed_behavior<Sigs...>; using behavior_type = typed_behavior<Sigs...>;
using super = abstract_event_based_actor<behavior_type, false, using super = abstract_event_based_actor<behavior_type, false,
...@@ -180,6 +190,9 @@ public: ...@@ -180,6 +190,9 @@ public:
typename detail::get_callable_trait<F>::arg_types typename detail::get_callable_trait<F>::arg_types
>::type >::type
>::type; >::type;
static_assert(std::is_convertible<typename impl::actor_hdl,
minimal_client>::value,
"Cannot fork: new broker misses required handlers");
return spawn_functor_impl<no_spawn_options, impl>( return spawn_functor_impl<no_spawn_options, impl>(
nullptr, [&sptr](abstract_broker* forked) { nullptr, [&sptr](abstract_broker* forked) {
sptr->set_broker(forked); sptr->set_broker(forked);
...@@ -188,6 +201,33 @@ public: ...@@ -188,6 +201,33 @@ public:
std::move(fun), hdl, std::forward<Ts>(xs)...); std::move(fun), hdl, std::forward<Ts>(xs)...);
} }
connection_handle add_tcp_scribe(const std::string& host, uint16_t port) {
static_assert(std::is_convertible<actor_hdl, minimal_client>::value,
"Cannot add scribe: broker misses required handlers");
return super::add_tcp_scribe(host, port);
}
connection_handle add_tcp_scribe(network::native_socket fd) {
static_assert(std::is_convertible<actor_hdl, minimal_client>::value,
"Cannot add scribe: broker misses required handlers");
return super::add_tcp_scribe(fd);
}
std::pair<accept_handle, uint16_t>
add_tcp_doorman(uint16_t port = 0,
const char* in = nullptr,
bool reuse_addr = false) {
static_assert(std::is_convertible<actor_hdl, minimal_server>::value,
"Cannot add doorman: broker misses required handlers");
return super::add_tcp_doorman(port, in, reuse_addr);
}
accept_handle add_tcp_doorman(network::native_socket fd) {
static_assert(std::is_convertible<actor_hdl, minimal_server>::value,
"Cannot add doorman: broker misses required handlers");
return super::add_tcp_doorman(fd);
}
typed_broker() { typed_broker() {
// nop // nop
} }
...@@ -212,4 +252,4 @@ protected: ...@@ -212,4 +252,4 @@ protected:
} // namespace io } // namespace io
} // namespace caf } // namespace caf
#endif // CAF_IO_TYPED_BROKER_HPP #endif // CAF_IO_EXPERIMENTAL_TYPED_BROKER_HPP
...@@ -131,6 +131,9 @@ spawn_io_client_typed(F fun, const std::string& host, uint16_t port, ...@@ -131,6 +131,9 @@ spawn_io_client_typed(F fun, const std::string& host, uint16_t port,
using arg_types = typename trait::arg_types; using arg_types = typename trait::arg_types;
using first_arg = typename detail::tl_head<arg_types>::type; using first_arg = typename detail::tl_head<arg_types>::type;
using impl_class = typename std::remove_pointer<first_arg>::type; using impl_class = typename std::remove_pointer<first_arg>::type;
static_assert(std::is_convertible<typename impl_class::actor_hdl,
minimal_client>::value,
"Cannot spawn io client: broker misses required handlers");
return spawn_io_client_impl<Os, impl_class>(std::move(fun), host, port, return spawn_io_client_impl<Os, impl_class>(std::move(fun), host, port,
std::forward<Ts>(xs)...); std::forward<Ts>(xs)...);
} }
...@@ -148,6 +151,9 @@ spawn_io_server_typed(F fun, uint16_t port, Ts&&... xs) { ...@@ -148,6 +151,9 @@ spawn_io_server_typed(F fun, uint16_t port, Ts&&... xs) {
using arg_types = typename trait::arg_types; using arg_types = typename trait::arg_types;
using first_arg = typename detail::tl_head<arg_types>::type; using first_arg = typename detail::tl_head<arg_types>::type;
using impl_class = typename std::remove_pointer<first_arg>::type; using impl_class = typename std::remove_pointer<first_arg>::type;
static_assert(std::is_convertible<typename impl_class::actor_hdl,
minimal_server>::value,
"Cannot spawn io server: broker misses required handlers");
return spawn_io_server_impl<Os, impl_class>(std::move(fun), port, return spawn_io_server_impl<Os, impl_class>(std::move(fun), port,
std::forward<Ts>(xs)...); std::forward<Ts>(xs)...);
} }
......
...@@ -48,13 +48,11 @@ using ping_atom = caf::atom_constant<atom("ping")>; ...@@ -48,13 +48,11 @@ using ping_atom = caf::atom_constant<atom("ping")>;
using pong_atom = caf::atom_constant<atom("pong")>; using pong_atom = caf::atom_constant<atom("pong")>;
using kickoff_atom = caf::atom_constant<atom("kickoff")>; using kickoff_atom = caf::atom_constant<atom("kickoff")>;
using peer = typed_actor<replies_to<connection_closed_msg>::with<void>, using peer = minimal_client::extend<reacts_to<ping_atom, int>,
replies_to<new_data_msg>::with<void>, reacts_to<pong_atom, int>>;
replies_to<ping_atom, int>::with<void>,
replies_to<pong_atom, int>::with<void>>;
using acceptor = typed_actor<replies_to<new_connection_msg>::with<void>, using acceptor =
replies_to<publish_atom>::with<uint16_t>>; minimal_server::extend<replies_to<publish_atom>::with<uint16_t>>;
behavior ping(event_based_actor* self, size_t num_pings) { behavior ping(event_based_actor* self, size_t num_pings) {
CAF_MESSAGE("num_pings: " << num_pings); CAF_MESSAGE("num_pings: " << num_pings);
...@@ -175,6 +173,9 @@ acceptor::behavior_type acceptor_fun(acceptor::broker_pointer self, ...@@ -175,6 +173,9 @@ acceptor::behavior_type acceptor_fun(acceptor::broker_pointer self,
self->fork(peer_fun, msg.handle, buddy); self->fork(peer_fun, msg.handle, buddy);
self->quit(); self->quit();
}, },
[](const new_data_msg&) {},
[](const connection_closed_msg&) {},
[](const acceptor_closed_msg&) {},
[=](publish_atom) { [=](publish_atom) {
return self->add_tcp_doorman(0, "127.0.0.1").second; return self->add_tcp_doorman(0, "127.0.0.1").second;
} }
......
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