PLCnext API Documentation  20.0.0.24462
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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) = default;
74  virtual ~FutureBase();
75 
76  FutureBase& operator=(const FutureBase& other) = default;
77  FutureBase& operator=(FutureBase&& other) = 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();
131 
132  Future(const Future& other) = default;
133  Future(Future&& other) = default;
134  ~Future() override = default;
135 
136  Future& operator=(const Future& other) = default;
137  Future& operator=(Future&& other) = default;
138 
142  const T GetValue() const;
143 
144 private:
145  void SetValue(const T& value);
146 
147  Impl& GetPImpl() override
148  {
149  return *(this->pImpl);
150  }
151 
152  const Impl& GetPImpl() const override
153  {
154  return *(this->pImpl);
155  }
156 
157 private:
158  std::shared_ptr<Impl> pImpl;
159 };
160 
161 
162 template<typename T>
164 {
165  Future result;
166  result.pImpl->isCreatedByPromise = true;
167  return result;
168 }
169 
170 
171 template<typename T>
172 Future<T>::Future() : pImpl(std::make_shared<Impl>())
173 {
174 }
175 
176 
177 template<typename T>
178 const T Future<T>::GetValue() const
179 {
180  this->CheckForValueAndException();
181  return this->GetPImpl().value;
182 }
183 
184 
185 template<typename T>
186 void Future<T>::SetValue(const T& value)
187 {
188  this->GetPImpl().value = value;
189  this->GetPImpl().valueHasBeenSet.store(true);
190 }
191 
192 
193 // -----------------------------------------------------------------------------
194 
195 
197 template<>
198 class Future<void> : public FutureBase
199 {
200 private:
201  friend Internal::Promise<void>;
202  using Impl = ImplBase;
203 
204  static Future CreateByPromise();
205 
206 public:
210  Future();
211 
212  Future(const Future& other) = default;
213  Future(Future&& other) = default;
214  ~Future() override = default;
215 
216  Future& operator=(const Future& other) = default;
217  Future& operator=(Future&& other) = default;
218 
223  void GetValue() const;
224 
225 private:
226  void SetValue();
227 
228  Impl& GetPImpl() override;
229  const Impl& GetPImpl() const override;
230 
231 private:
232  std::shared_ptr<Impl> pImpl;
233 };
234 
235 
236 }}} // end of namespace Arp::System::Nm
Future()
Constructs an invalid Future
Definition: Future.hpp:172
Namespace of the C++ standard library
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