File: behavior.hpp

package info (click to toggle)
actor-framework 0.18.7-1~exp1
  • links: PTS
  • area: main
  • in suites: experimental
  • size: 8,740 kB
  • sloc: cpp: 85,162; sh: 491; python: 187; makefile: 11
file content (125 lines) | stat: -rw-r--r-- 3,244 bytes parent folder | download
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