PLCnext API Documentation  21.0.0.35466
Future.hpp
1 //
3 // Copyright PHOENIX CONTACT Electronics GmbH
4 //
6 
7 #pragma once
8 
9 #include "Arp/System/Core/Exception.hpp"
10 #include "Arp/System/Core/TypeName.hxx"
11 #include <atomic>
12 #include <memory>
13 
14 
15 namespace Arp { namespace System { namespace Nm { namespace Internal
16 {
17 template<typename T>
20 class Promise;
21 } // namespace Internal
22 
23 
24 // <summary>Proxy for the result of an asynchronous function call</summary>
27 {
28 protected:
31  class IExceptionWrapper
32  {
33  public:
34  virtual ~IExceptionWrapper() = default;
35  virtual void ReThrowException() = 0;
36  };
37 
38 
41  template<typename ExceptionType>
42  class ExceptionWrapper : public IExceptionWrapper
43  {
44  public:
45  explicit ExceptionWrapper(const ExceptionType& e) : exception(e)
46  {
47  }
48 
49  ~ExceptionWrapper() override = default;
50 
51  void ReThrowException() override
52  {
53  throw this->exception;
54  }
55 
56  private:
57  ExceptionType exception;
58  };
59 
60 
63  struct ImplBase
64  {
65  bool isCreatedByPromise = false;
66  std::atomic<bool> valueHasBeenSet;
67  std::unique_ptr<IExceptionWrapper> exception;
68  };
69 
70 public:
71  FutureBase() = default;
72  FutureBase(const FutureBase& other) = default;
73  FutureBase(FutureBase&& other) noexcept = default;
74  virtual ~FutureBase();
75 
76  FutureBase& operator=(const FutureBase& other) = default;
77  FutureBase& operator=(FutureBase&& other) noexcept = default;
78 
80  const bool IsValid() const;
81 
83  const bool HasValue() const;
84 
86  const bool HasException() const;
87 
88 protected:
89  virtual ImplBase& GetPImpl() = 0;
90  virtual const ImplBase& GetPImpl() const = 0;
91  void CheckForValueAndException() const;
92 
93  template<typename ExceptionType>
94  void SetException(const ExceptionType& e);
95 
96  void Clear(bool isValid);
97 };
98 
99 
100 template<typename ExceptionType>
101 void FutureBase::SetException(const ExceptionType& e)
102 {
103  this->GetPImpl().exception =
104  std::unique_ptr<IExceptionWrapper>(new ExceptionWrapper<ExceptionType>(e));
105  this->GetPImpl().valueHasBeenSet.store(true);
106 }
107 
108 
109 // -----------------------------------------------------------------------------
110 
111 
113 template<typename T>
114 class Future : public FutureBase
115 {
116 private:
117  friend Internal::Promise<T>;
118 
119  struct Impl : public ImplBase
120  {
121  T value = T{};
122  };
123 
124  static Future CreateByPromise();
125 
126 public:
130  Future() = default;
131  Future(const Future& other) = default;
132  Future(Future&& other) noexcept = default;
133  ~Future() override = default;
134 
135  Future& operator=(const Future& other) = default;
136  Future& operator=(Future&& other) noexcept = default;
137 
141  const T GetValue() const;
142 
143 private:
144  void SetValue(const T& value);
145 
146  Impl& GetPImpl() override
147  {
148  return *(this->pImpl);
149  }
150 
151  const Impl& GetPImpl() const override
152  {
153  return *(this->pImpl);
154  }
155 
156 private:
157  std::shared_ptr<Impl> pImpl{std::make_shared<Impl>()};
158 };
159 
160 
161 template<typename T>
163 {
164  Future result;
165  result.pImpl->isCreatedByPromise = true;
166  return result;
167 }
168 
169 
170 template<typename T>
171 const T Future<T>::GetValue() const
172 {
173  this->CheckForValueAndException();
174  return this->GetPImpl().value;
175 }
176 
177 
178 template<typename T>
179 void Future<T>::SetValue(const T& value)
180 {
181  this->GetPImpl().value = value;
182  this->GetPImpl().valueHasBeenSet.store(true);
183 }
184 
185 
186 // -----------------------------------------------------------------------------
187 
188 
190 template<>
191 class Future<void> : public FutureBase
192 {
193 private:
194  friend Internal::Promise<void>;
195  using Impl = ImplBase;
196 
197  static Future CreateByPromise();
198 
199 public:
203  Future();
204 
205  Future(const Future& other) = default;
206  Future(Future&& other) = default;
207  ~Future() override = default;
208 
209  Future& operator=(const Future& other) = default;
210  Future& operator=(Future&& other) = default;
211 
216  void GetValue() const;
217 
218 private:
219  void SetValue();
220 
221  Impl& GetPImpl() override;
222  const Impl& GetPImpl() const override;
223 
224 private:
225  std::shared_ptr<Impl> pImpl;
226 };
227 
228 
229 }}} // end of namespace Arp::System::Nm
const T GetValue() const
Returns the value set by the associated Promise
Definition: Future.hpp:171
Root namespace for the PLCnext API
Future object as proxy for return value an asynchronous function call
Definition: Future.hpp:114
System components used by the System, Device, Plc or Io domains.
Base class with common behavior for Future<T> and Future<void>
Definition: Future.hpp:26