LibQuicR
reply.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) 2024 Cisco Systems
2 // SPDX-License-Identifier: BSD-2-Clause
3 
4 #pragma once
5 
6 #include "quicr/errors.h"
7 #include "quicr/transport.h"
9 
10 #include <concepts>
11 #include <functional>
12 #include <thread>
13 #include <type_traits>
14 #include <utility>
15 #include <variant>
16 
17 namespace quicr {
18 
29  template<typename T, typename E>
30  class Reply
31  {
32  public:
35 
37  using CompletionType = std::function<void(ResultType)>;
38 
40  using DeferType = std::function<void(CompletionType&&)>;
41 
42  private:
43  Reply(DeferType&& action)
44  : result_(std::in_place_type<DeferType>, std::move(action))
45  {
46  }
47 
48  bool IsDeferred() const noexcept { return std::holds_alternative<DeferType>(result_); }
49 
50  public:
52  Reply() = default;
53 
56  Reply(const Reply& other) = delete;
57 
60  Reply(Reply&& other) noexcept = default;
61 
64  Reply& operator=(const Reply& other) = delete;
65 
69  Reply& operator=(Reply&& other) noexcept = default;
70 
78  template<typename U>
79  requires(!std::same_as<std::remove_cvref_t<U>, Reply> && std::is_constructible_v<ResultType, U &&>)
80  Reply(U&& value)
81  : result_(std::in_place_type<ResultType>, std::forward<U>(value))
82  {
83  }
84 
95  static Reply Defer(DeferType&& action) { return Reply(std::move(action)); }
96 
111  template<typename F>
112  void Resolve(const std::shared_ptr<Transport>& transport, F&& f)
113  {
114  if (IsDeferred()) {
115  auto action = std::move(std::get<DeferType>(result_));
116  action([transport, f = std::forward<F>(f)](ResultType reply) mutable {
117  transport->QueueDeferredReply(
118  [result = std::move(reply), f = std::forward<F>(f)]() mutable { f(result); });
119  });
120  return;
121  }
122 
123  f(std::move(std::get<ResultType>(result_)));
124  }
125 
126  private:
127  std::variant<ResultType, DeferType> result_;
128  };
129 }
Holds either a success value or an error value.
Definition: expected.h:65
The reply to a callback, which may be answered immediately or deferred.
Definition: reply.h:31
static Reply Defer(DeferType &&action)
Construct a reply whose producer may complete asynchronously.
Definition: reply.h:95
void Resolve(const std::shared_ptr< Transport > &transport, F &&f)
Hand the result to the given continuation, either now or once the deferred action completes.
Definition: reply.h:112
Reply(Reply &&other) noexcept=default
Move a reply, transferring its unresolved result or deferred action.
Reply & operator=(Reply &&other) noexcept=default
Move-assign a reply, transferring its unresolved state.
Reply()=default
Construct an immediate default result.
std::function< void(ResultType)> CompletionType
Continuation invoked with the completed result.
Definition: reply.h:37
Reply & operator=(const Reply &other)=delete
Replies cannot be copy-assigned.
requires(!std::same_as< std::remove_cvref_t< U >, Reply > &&std::is_constructible_v< ResultType, U && >) Reply(U &&value)
Construct an immediate reply from anything the result is constructible from, such as a value,...
Definition: reply.h:79
std::function< void(CompletionType &&)> DeferType
Deferred producer that must invoke its completion exactly once.
Definition: reply.h:40
Reply(const Reply &other)=delete
Replies are move-only because resolving consumes their state.
Definition: attributes.h:13