actor-framework
response_promise.hpp
1 // This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
2 // the main distribution directory for license terms and copyright or visit
3 // https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
4 
5 #pragma once
6 
7 #include "caf/actor.hpp"
8 #include "caf/actor_addr.hpp"
9 #include "caf/actor_cast.hpp"
10 #include "caf/detail/core_export.hpp"
11 #include "caf/detail/send_type_check.hpp"
12 #include "caf/intrusive_ptr.hpp"
13 #include "caf/message.hpp"
14 #include "caf/message_id.hpp"
15 #include "caf/response_type.hpp"
16 
17 #include <vector>
18 
19 namespace caf {
20 
24 class CAF_CORE_EXPORT response_promise {
25 public:
26  // -- friends ----------------------------------------------------------------
27 
28  friend class local_actor;
29 
30  friend class stream_manager;
31 
32  template <class...>
33  friend class typed_response_promise;
34 
35  // -- constructors, destructors, and assignment operators --------------------
36 
37  response_promise() = default;
38 
40 
41  response_promise(const response_promise&) = default;
42 
43  response_promise& operator=(response_promise&&) = default;
44 
45  response_promise& operator=(const response_promise&) = default;
46 
47  // -- properties -------------------------------------------------------------
48 
50  bool async() const noexcept;
51 
53  bool pending() const noexcept;
54 
56  strong_actor_ptr source() const noexcept;
57 
59  message_id id() const noexcept;
60 
61  // -- delivery ---------------------------------------------------------------
62 
67  void deliver(message msg);
68 
71  void deliver(error x);
72 
77  void deliver();
78 
83  void deliver(unit_t) {
84  deliver();
85  }
86 
89  template <class... Ts>
90  void deliver(Ts... xs) {
91  using arg_types = type_list<Ts...>;
92  static_assert(!detail::tl_exists_v<arg_types, detail::is_result>,
93  "delivering a result<T> is not supported");
94  static_assert(!detail::tl_exists_v<arg_types, detail::is_expected>,
95  "mixing expected<T> with regular values is not supported");
96  if (pending()) {
97  state_->deliver_impl(make_message(std::move(xs)...));
98  state_.reset();
99  }
100  }
101 
105  template <class T>
107  if (pending()) {
108  if (x) {
109  if constexpr (std::is_same_v<T, void> || std::is_same_v<T, unit_t>)
110  state_->deliver_impl(make_message());
111  else
112  state_->deliver_impl(make_message(std::move(*x)));
113  } else {
114  state_->deliver_impl(make_message(std::move(x.error())));
115  }
116  state_.reset();
117  }
118  }
119 
120  // -- delegation -------------------------------------------------------------
121 
124  template <message_priority P = message_priority::normal, class Handle,
125  class... Ts>
127  detail::implicit_conversions_t<std::decay_t<Ts>>...>
128  delegate(const Handle& receiver, Ts&&... args) {
129  static_assert(sizeof...(Ts) > 0, "no message to send");
130  detail::send_type_check<none_t, Handle, Ts...>();
131  if (pending()) {
132  if constexpr (P == message_priority::high)
133  state_->id = state_->id.with_high_priority();
134  if constexpr (std::is_same_v<type_list<message>,
135  type_list<std::decay_t<Ts>...>>)
136  state_->delegate_impl(actor_cast<abstract_actor*>(receiver),
137  std::forward<Ts>(args)...);
138  else
139  state_->delegate_impl(actor_cast<abstract_actor*>(receiver),
140  make_message(std::forward<Ts>(args)...));
141  state_.reset();
142  }
143  return {};
144  }
145 
146 private:
147  // -- constructors that are visible only to friends --------------------------
148 
150 
152 
153  // -- utility functions that are visible only to friends ---------------------
154 
158  static void respond_to(local_actor* self, mailbox_element* request,
159  message& response);
160 
162  static void respond_to(local_actor* self, mailbox_element* request,
163  error& response);
164 
165  // -- nested types -----------------------------------------------------------
166 
167  // Note: response promises must remain local to their owner. Hence, we don't
168  // need a thread-safe reference count for the state.
169  class CAF_CORE_EXPORT state {
170  public:
171  state() = default;
172  state(const state&) = delete;
173  state& operator=(const state&) = delete;
174  ~state();
175 
176  void cancel();
177 
178  void deliver_impl(message msg);
179 
180  void delegate_impl(abstract_actor* receiver, message msg);
181 
182  mutable size_t ref_count = 1;
183  strong_actor_ptr self;
184  strong_actor_ptr source;
185  message_id id;
186 
187  friend void intrusive_ptr_add_ref(const state* ptr) {
188  ++ptr->ref_count;
189  }
190 
191  friend void intrusive_ptr_release(const state* ptr) {
192  if (--ptr->ref_count == 0)
193  delete ptr;
194  }
195  };
196 
197  // -- member variables -------------------------------------------------------
198 
199  intrusive_ptr<state> state_;
200 };
201 
202 } // namespace caf
Base class for actors running on this node, either living in an own thread or cooperatively scheduled...
Definition: local_actor.hpp:41
typename response_type< typename Handle::signatures, In... >::delegated_type delegated_response_type_t
Computes the response message type for input In... from the list of message passing interfaces Fs and...
Definition: response_type.hpp:61
A list of types.
Definition: type_list.hpp:11
Describes a fixed-length, copy-on-write, type-erased tuple with elements of any type.
Definition: message.hpp:32
A serializable type for storing error codes with category and optional, human-readable context inform...
Definition: error.hpp:50
void deliver(expected< T > x)
Satisfies the promise by sending the content of x, i.e., either a value of type T or an error...
Definition: response_promise.hpp:106
void deliver(Ts... xs)
Satisfies the promise by sending make_message(xs...).
Definition: response_promise.hpp:90
caf::error & error() &noexcept
Definition: expected.hpp:290
void deliver(unit_t)
Satisfies the promise by sending an empty message.
Definition: response_promise.hpp:83
Represents "nothing", e.g., for clearing an optional by assigning none.
Definition: none.hpp:14
Definition: mailbox_element.hpp:19
Represents the result of a computation which can either complete successfully with an instance of typ...
Definition: expected.hpp:45
delegated_response_type_t< Handle, detail::implicit_conversions_t< std::decay_t< Ts > >... > delegate(const Handle &receiver, Ts &&... args)
Satisfies the promise by delegating to another actor.
Definition: response_promise.hpp:128
Bundles various flags along with an optional request ID.
Definition: message_id.hpp:21
Base class for all actor implementations.
Definition: abstract_actor.hpp:48
Unit is analogous to void, but can be safely returned, stored, etc.
Definition: unit.hpp:16
Root namespace of libcaf.
Definition: custom_types_4.cpp:139
Enables actors to delay a response message by capturing the context of a request message.
Definition: response_promise.hpp:24
Enables statically typed actors to delay a response message by capturing the context of a request mes...
Definition: fwd.hpp:71