PLCnext API Documentation  22.9.0.33
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 = std::make_unique<ExceptionWrapper<ExceptionType>>(e);
104  this->GetPImpl().valueHasBeenSet.store(true);
105 }
106 
107 
108 // -----------------------------------------------------------------------------
109 
110 
112 template<typename T>
113 class Future : public FutureBase
114 {
115 private:
116  friend Internal::Promise<T>;
117 
118  struct Impl : public ImplBase
119  {
120  T value = T{};
121  };
122 
123  static Future CreateByPromise();
124 
125 public:
129  Future() = default;
130  Future(const Future& other) = default;
131  Future(Future&& other) noexcept = default;
132  ~Future() override = default;
133 
134  Future& operator=(const Future& other) = default;
135  Future& operator=(Future&& other) noexcept = default;
136 
140  const T GetValue() const;
141 
142 private:
143  void SetValue(const T& value);
144 
145  Impl& GetPImpl() override
146  {
147  return *(this->pImpl);
148  }
149 
150  const Impl& GetPImpl() const override
151  {
152  return *(this->pImpl);
153  }
154 
155 private:
156  std::shared_ptr<Impl> pImpl{std::make_shared<Impl>()};
157 };
158 
159 
160 template<typename T>
161 Future<T> Future<T>::CreateByPromise()
162 {
163  Future result;
164  result.pImpl->isCreatedByPromise = true;
165  return result;
166 }
167 
168 
169 template<typename T>
170 const T Future<T>::GetValue() const
171 {
172  this->CheckForValueAndException();
173  return this->GetPImpl().value;
174 }
175 
176 
177 template<typename T>
178 void Future<T>::SetValue(const T& value)
179 {
180  this->GetPImpl().value = value;
181  this->GetPImpl().valueHasBeenSet.store(true);
182 }
183 
184 
185 // -----------------------------------------------------------------------------
186 
187 
189 template<>
190 class Future<void> : public FutureBase
191 {
192 private:
193  friend Internal::Promise<void>;
194  using Impl = ImplBase;
195 
196  static Future CreateByPromise();
197 
198 public:
203 
204  Future(const Future& other) = default;
205  Future(Future&& other) = default;
206  ~Future() override = default;
207 
208  Future& operator=(const Future& other) = default;
209  Future& operator=(Future&& other) = default;
210 
215  void GetValue() const;
216 
217 private:
218  void SetValue();
219 
220  Impl& GetPImpl() override;
221  const Impl& GetPImpl() const override;
222 
223 private:
224  std::shared_ptr<Impl> pImpl;
225 };
226 
227 
228 }}} // end of namespace Arp::System::Nm
Base class with common behavior for Future<T> and Future<void>
Definition: Future.hpp:27
const bool HasValue() const
Returns true, if a value or an exception has been set
const bool HasException() const
Returns true, if an exception has been set
const bool IsValid() const
Returns true, if this Future has an assiciated Promise
Future()
Constructs an invalid Future
void GetValue() const
Gets the void result of the asynchronous function call
Future object as proxy for return value an asynchronous function call
Definition: Future.hpp:114
const T GetValue() const
Returns the value set by the associated Promise
Definition: Future.hpp:170
Future()=default
Constructs an invalid Future
@ System
System components used by the System, Device, Plc or Io domains.
Root namespace for the PLCnext API