1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include <functional>
#include <type_traits>
#include "caf/detail/behavior_impl.hpp"
#include "caf/detail/core_export.hpp"
#include "caf/detail/type_list.hpp"
#include "caf/detail/type_traits.hpp"
#include "caf/none.hpp"
#include "caf/timeout_definition.hpp"
#include "caf/timespan.hpp"
#include "caf/unsafe_behavior_init.hpp"
namespace caf {
class message_handler;
/// Describes the behavior of an actor, i.e., provides a message
/// handler and an optional timeout.
class CAF_CORE_EXPORT behavior {
public:
friend class message_handler;
behavior() = default;
behavior(behavior&&) = default;
behavior(const behavior&) = default;
behavior& operator=(behavior&&) = default;
behavior& operator=(const behavior&) = default;
// Convenience overload to allow "unsafe" initialization of any behavior_type.
behavior(unsafe_behavior_init_t, behavior from) : behavior(std::move(from)) {
// nop
}
/// Creates a behavior from `fun` without timeout.
behavior(const message_handler& mh);
/// The list of arguments can contain match expressions, message handlers,
/// and up to one timeout (if set, the timeout has to be the last argument).
template <class T, class... Ts>
behavior(T x, Ts&&... xs) {
assign(std::move(x), std::forward<Ts>(xs)...);
}
/// Creates a behavior from `tdef` without message handler.
template <class F>
behavior(timeout_definition<F> tdef) : impl_(detail::make_behavior(tdef)) {
// nop
}
/// Assigns new handlers.
template <class... Ts>
void assign(Ts&&... xs) {
static_assert(sizeof...(Ts) > 0, "assign() called without arguments");
impl_ = detail::make_behavior(std::forward<Ts>(xs)...);
}
void swap(behavior& other) {
impl_.swap(other.impl_);
}
void assign(intrusive_ptr<detail::behavior_impl> ptr) {
impl_.swap(ptr);
}
/// Equal to `*this = other`.
void assign(message_handler other);
/// Equal to `*this = other`.
void assign(behavior other);
/// Invokes the timeout callback if set.
void handle_timeout() {
impl_->handle_timeout();
}
/// Returns the timespan after which receive operations
/// using this behavior should time out.
timespan timeout() const noexcept {
return impl_->timeout();
}
/// Runs this handler and returns its (optional) result.
optional<message> operator()(message& xs) {
return impl_ ? impl_->invoke(xs) : none;
}
/// Runs this handler with callback.
bool operator()(detail::invoke_result_visitor& f, message& xs) {
return impl_ ? impl_->invoke(f, xs) : false;
}
/// Checks whether this behavior is not empty.
operator bool() const {
return static_cast<bool>(impl_);
}
/// @cond PRIVATE
using impl_ptr = intrusive_ptr<detail::behavior_impl>;
const impl_ptr& as_behavior_impl() const {
return impl_;
}
behavior(impl_ptr ptr) : impl_(std::move(ptr)) {
// nop
}
behavior& unbox() {
return *this;
}
/// @endcond
private:
impl_ptr impl_;
};
} // namespace caf
|