OnixS C++ FIX Engine  4.12.0
API Documentation
Future.h
Go to the documentation of this file.
1 /*
2 * Copyright Onix Solutions Limited [OnixS]. All rights reserved.
3 *
4 * This software owned by Onix Solutions Limited [OnixS] and is protected by copyright law
5 * and international copyright treaties.
6 *
7 * Access to and use of the software is governed by the terms of the applicable OnixS Software
8 * Services Agreement (the Agreement) and Customer end user license agreements granting
9 * a non-assignable, non-transferable and non-exclusive license to use the software
10 * for it's own data processing purposes under the terms defined in the Agreement.
11 *
12 * Except as otherwise granted within the terms of the Agreement, copying or reproduction of any part
13 * of this source code or associated reference material to any other location for further reproduction
14 * or redistribution, and any amendments to this copyright notice, are expressly prohibited.
15 *
16 * Any reproduction or redistribution for sale or hiring of the Software not in accordance with
17 * the terms of the Agreement is a violation of copyright law.
18 */
19 
20 #pragma once
21 
22 #include <OnixS/FIXEngine/ABI.h>
25 
26 #ifdef ONIXS_FIXENGINE_CXX11
27 #include <exception>
28 #endif
29 
30 namespace OnixS {
31 
32 namespace System
33 {
34  class FutureSharedState;
35 }
36 
37 namespace Threading {
38 
39 /// The state of a \c SharedFuture object (similar to std::future_status, @see http://en.cppreference.com/w/cpp/thread/future_status ).
41 {
42  enum Enum
43  {
44  /// The shared state is ready.
46  /// The shared state did not become ready before the specified timeout duration has passed.
48  /// The shared state contains a deferred function, so the result will be computed only when explicitly requested.
49  deferred
50  };
51 };
52 
53 namespace Implementation {
54 
55 class FutureHelper;
56 class PromiseBase;
57 
58 // Implementation details.
59 class ValueBase
60 {
61 public:
62 
64  virtual ValueBase * clone() const = 0;
65 };
66 
67 /// Implementation details.
69 {
70 public:
71 
72  FutureValue(ValueBase * value);
73  FutureValue();
74  FutureValue(const FutureValue & other);
75  ~FutureValue();
76 
77  ValueBase * value() const { return value_; }
78 
79 private:
80 
81  ValueBase * value_;
82 };
83 
84 /// Implementation details.
85 template<typename ValueType>
86 class Value : public ValueBase
87 {
88  typedef Value<ValueType> Type;
89 
90 public:
91 
92  static const ValueType & value(const ValueBase * value)
93  {
94  return static_cast<const Type*>(value)->value();
95  }
96 
97  static ValueBase * create(const ValueType & value)
98  {
99  return new Type(value);
100  }
101 
102  ValueBase * clone() const ONIXS_FIXENGINE_OVERRIDE
103  {
104  return create(value_);
105  }
106 
107 private:
108 
109  explicit Value(const ValueType & value) : value_(value) {}
110 
111  const ValueType & value() const { return value_; }
112 
113  const ValueType value_;
114 };
115 
116 /// The base implementation of the SharedFuture<T>.
118 {
119 public:
120  /// Check if a future instance is associated with an asynchronous result.
121  ///
122  /// Returns \c true if the *this has an associated asynchronous result, false otherwise.
124  {
125  return state_ != ONIXS_FIXENGINE_NULLPTR;
126  }
127 
128  /// Returns \c true if the asynchronous result associated with this Future is ready
129  /// (has a value or an exception stored in the shared state), \c false otherwise.
130  ///
131  /// There are often situations where a \c get() call on a Future may not be a blocking call,
132  /// or is only a blocking call under certain circumstances.
133  /// This method gives the ability to test for early completion and allows us to avoid
134  /// associating a continuation, which needs to be scheduled with some non-trivial overhead
135  /// and near-certain loss of the cache efficiency.
136  ///
137  /// @throw The std::logic_error if this instance does not refer to a shared state.
138  ONIXS_FIXENGINE_API bool isReady() const;
139 
140  /// Returns \c true if the asynchronous result associated with this Future has a stored value,
141  /// \c false otherwise.
142  ///
143  /// @throw The std::logic_error if this instance does not refer to a shared state.
144  ONIXS_FIXENGINE_API bool hasValue() const;
145 
146  /// Returns \c true if the asynchronous result associated with this Future has a stored exception,
147  /// \c false otherwise.
148  ///
149  /// @throw The std::logic_error if this instance does not refer to a shared state.
150  ONIXS_FIXENGINE_API bool hasException() const;
151 
152 #ifdef ONIXS_FIXENGINE_CXX11
153 
154  /// Returns the stored exception.
155  ///
156  /// @throw The std::logic_error if this instance does not refer to a shared state.
157  /// @throw The std::logic_error if the operation has *not* finished with an error.
158  ONIXS_FIXENGINE_API std::exception_ptr getExceptionPtr() const;
159 
160 #endif
161 
162  enum { InfiniteTimeout = -1 };
163 
164  /// Waits for the result to become available during the timeout.
165  ///
166  /// \note Calling \c wait on the same Future from multiple threads is \e not safe;
167  /// the intended use is for each thread that waits on the same shared state to have a \e copy of a Future.
168  ///
169  /// \throw The std::logic_error if this instance does not refer to a shared state.
170  ONIXS_FIXENGINE_API FutureStatus::Enum wait(int timeoutInMs = InfiniteTimeout) const;
171 
172 protected:
174  : state_() {}
175 
177 
179 
180 #ifdef ONIXS_FIXENGINE_CXX11
181 
183 
185 
186 #endif
187 
188  struct moving_init_t {};
189 
190  /// Initializes the instance with shared state.
191  ONIXS_FIXENGINE_API FutureBase(const System::FutureSharedState * state) ONIXS_FIXENGINE_NOTHROW;
192 
193  /// Initializes the instance with shared state.
194  ONIXS_FIXENGINE_API FutureBase(const System::FutureSharedState * state, moving_init_t) ONIXS_FIXENGINE_NOTHROW;
195 
196  /// Destroys a future object.
197  ///
198  /// If this is the last reference to the asynchronous result associated with *this (if any), then destroy that asynchronous result.
200 
202 
203  ONIXS_FIXENGINE_API const FutureValue & getValue() const;
204 
205  ONIXS_FIXENGINE_API void getVoid() const;
206 
207 private:
208  const System::FutureSharedState * state_;
209 
210  friend class FutureHelper;
211  friend class PromiseBase;
212 };
213 
214 template<typename T>
216 {
217  typedef const T & Type;
218 };
219 
220 template<>
221 struct FutureGetReturn<void>
222 {
223  typedef void Type;
224 };
225 
226 }
227 
228 /// Represents a future result of an asynchronous operation - a result that will eventually appear in the Future after
229 /// the processing is complete.
230 ///
231 /// The class template Future provides a mechanism to access the result of \e asynchronous operations :
232 /// \li An asynchronous operation (e.g. created via Promise) can provide a Future object to the creator of that asynchronous
233 /// operation (e.g. via the Promise::getFuture).
234 /// \li The creator of the asynchronous operation can then use a variety of methods to query, wait for, or extract a value from Future.
235 /// These methods may block if the asynchronous operation has not yet provided a value.
236 /// \li When the asynchronous operation is ready to send a result to the creator, it can do so by modifying the <em> shared state </em>
237 /// (e.g. via the Promise::setValue) that is linked to the creator's Future.
238 ///
239 /// The Future is the synchronization object constructed around the \e receiving end of the Promise channel. It allows for the separation
240 /// of the initiation of an operation and the act of waiting for its result.
241 ///
242 /// The Future is \e copiable and multiple SharedFuture objects may refer to the same shared state.
243 ///
244 /// Unlike the std::future, this implementation has an extended API, allowing you to query the state of SharedFuture.
245 /// The internal implementation is lock-free; therefore, setting and polling states do not lead to blocking of threads and/or switching
246 /// of an execution context.
247 ///
248 /// \note An access to the same shared state from multiple threads is safe if each thread does it through its own copy of
249 /// a SharedFuture object.
250 ///
251 /// \see http://en.cppreference.com/w/cpp/thread/shared_future .
252 template <typename T>
254 {
255 public:
257  : FutureBase() {}
258 
259  /// The copy constructor.
261  : FutureBase(other) {}
262 
263  /// The copy assignment.
265  {
266  FutureBase::operator=(other);
267  return *this;
268  }
269 
270 #ifdef ONIXS_FIXENGINE_CXX11
271 
273  : FutureBase(std::move(other)) {}
274 
275  FutureBase & operator=(SharedFuture<T> && other) ONIXS_FIXENGINE_NOTHROW
276  {
277  FutureBase::operator=(std::move(other));
278  return *this;
279  }
280 
281 #endif
282 
283  /// Returns the result. If the result is not ready, the method will block. When completes, it either returns a value or throws an exception.
284  ///
285  /// This method waits until the Future has a valid result and retrieves it. It effectively calls the wait() in order to wait for the result.
286  ///
287  /// \exception If an exception was stored in the shared state referenced by this Future (e.g. via a call to the Promise::setException()) then that exception will be thrown.
289  {
290  return Implementation::Value<T>::value(getValue().value());
291  }
292 
293  /// swaps two SharedFuture objects
295  {
296  FutureBase::swap(other);
297  }
298 
299 private:
300  /// Initializes the instance with shared state.
301  SharedFuture(const System::FutureSharedState * state)
302  : FutureBase(state) {}
303 
304  /// Initializes the instance with shared state.
305  SharedFuture(const System::FutureSharedState * state, moving_init_t t) ONIXS_FIXENGINE_NOTHROW
306  : FutureBase(state, t) {}
307 
308  friend class Implementation::FutureHelper;
310 };
311 
312 template<>
313 inline void SharedFuture<void>::get() const
314 {
315  getVoid();
316 }
317 
318 namespace Implementation {
319 
320 /// The base implementation of the PromiseFuture<T>.
322 {
323 public:
324  /// Check if a future instance is associated with an asynchronous result.
325  ///
326  /// Returns \c true if the *this has an associated asynchronous result, false otherwise.
327  bool valid();
328 
329  ONIXS_FIXENGINE_API void setExceptionImpl();
330 
331 protected:
333 
335 
337 
338 #ifdef ONIXS_FIXENGINE_CXX11
339 
341 
343 
344 #endif
345 
346  /// Destroys a future object.
347  ///
348  /// If this is the last reference to the asynchronous result associated with *this (if any), then destroy that asynchronous result.
350 
352 
353  ONIXS_FIXENGINE_API void setValue(ValueBase * value);
354 
355  ONIXS_FIXENGINE_API void setVoid();
356 
357 
358  ONIXS_FIXENGINE_API SharedFuture<FutureValue> getFutureImpl() const;
359 
360  template<typename T>
362  {
363  return SharedFuture<T>(getFutureImpl().state_);
364  }
365 
366 private:
367 
368  /// Implementation details.
369  struct Impl;
370  Impl * impl_;
371 };
372 
373 }
374 
375 /// Provides a facility to store a value or an exception that can be acquired asynchronously via a `SharedFuture` object created by the `Promise` object.
376 /// Each `Promise` object is associated with a shared state, which contains a some state information and a result which may be not yet evaluated, evaluated to a value or evaluated to an exception.
377 /// The promise stores the result or the exception in the shared state. Marks the state ready and unblocks any thread waiting on a future associated with the shared state.
378 template <typename T>
380 {
381 public:
382 
384  : PromiseBase() {}
385 
386  /// The copy constructor.
388  : PromiseBase(other) {}
389 
390  /// The copy assignment.
392  {
393  PromiseBase::operator=(other);
394  return *this;
395  }
396 
397 #ifdef ONIXS_FIXENGINE_CXX11
398 
400  : PromiseBase(std::move(other)) {}
401 
402  Promise & operator=(Promise<T> && other) ONIXS_FIXENGINE_NOTHROW
403  {
404  PromiseBase::operator=(std::move(other));
405  return *this;
406  }
407 
408 #endif
409 
410  /// Swaps two Promise objects
412  {
413  PromiseBase::swap(other);
414  }
415 
417  {
418  return getTypedFuture<T>();
419  }
420 
421  /// Sets the successful result value to the given shared state.
422  void set(const T & value)
423  {
424  setValue(Implementation::Value<T>::create(value));
425  }
426 
427  /// Sets the result to indicate an exception.
428  ///
429  /// @note Does nothing if the shared state already stores a value or exception.
430  template<typename ExceptionType>
431  void setException(const ExceptionType & exception)
432  {
433  try
434  {
435  throw exception;
436  }
437  catch(...)
438  {
439  setExceptionImpl();
440  }
441  }
442 };
443 
444 template<>
446 {
447 public:
448 
450  : PromiseBase() {}
451 
452  /// The copy constructor.
454  : PromiseBase(other) {}
455 
456  /// The copy assignment.
458  {
459  PromiseBase::operator=(other);
460  return *this;
461  }
462 
463 #ifdef ONIXS_FIXENGINE_CXX11
464 
466  : PromiseBase(std::move(other)) {}
467 
468  Promise & operator=(Promise<void> && other) ONIXS_FIXENGINE_NOTHROW
469  {
470  PromiseBase::operator=(std::move(other));
471  return *this;
472  }
473 
474 #endif
475 
476  /// Swaps two Promise objects
478  {
479  PromiseBase::swap(other);
480  }
481 
483  {
484  return getTypedFuture<void>();
485  }
486 
487  /// Sets the successful result to the given shared state.
488  void set()
489  {
490  setVoid();
491  }
492 
493  /// Sets the result to indicate an exception.
494  ///
495  /// @note Does nothing if the shared state already stores a value or exception.
496  template<typename ExceptionType>
497  void setException(const ExceptionType & exception)
498  {
499  try
500  {
501  throw exception;
502  }
503  catch(...)
504  {
505  setExceptionImpl();
506  }
507  }
508 };
509 
510 }
511 }
SharedFuture(const SharedFuture< T > &other) ONIXS_FIXENGINE_NOTHROW
The copy constructor.
Definition: Future.h:260
SharedFuture< T > & operator=(const SharedFuture< T > &other) ONIXS_FIXENGINE_NOTHROW
The copy assignment.
Definition: Future.h:264
void swap(Promise< void > &other) ONIXS_FIXENGINE_NOTHROW
Swaps two Promise objects.
Definition: Future.h:477
#define ONIXS_FIXENGINE_NOTHROW
Definition: Compiler.h:43
#define ONIXS_FIXENGINE_DEFAULT
Definition: Compiler.h:176
SharedFuture< T > getTypedFuture() const
Definition: Future.h:361
Provides a facility to store a value or an exception that can be acquired asynchronously via a Shared...
Definition: Future.h:379
Promise() ONIXS_FIXENGINE_NOTHROW
Definition: Future.h:449
#define ONIXS_FIXENGINE_API
Definition: ABI.h:45
The base implementation of the SharedFuture<T>.
Definition: Future.h:117
SharedFuture() ONIXS_FIXENGINE_NOTHROW
Definition: Future.h:256
void setException(const ExceptionType &exception)
Sets the result to indicate an exception.
Definition: Future.h:431
Promise< T > & operator=(const Promise< T > &other) ONIXS_FIXENGINE_NOTHROW
The copy assignment.
Definition: Future.h:391
SharedFuture< T > getFuture() const
Definition: Future.h:416
Implementation details.
Definition: Future.h:86
SharedFuture< void > getFuture() const
Definition: Future.h:482
The state of a SharedFuture object (similar to std::future_status,.
Definition: Future.h:40
The shared state did not become ready before the specified timeout duration has passed.
Definition: Future.h:47
void swap(Promise< T > &other) ONIXS_FIXENGINE_NOTHROW
Swaps two Promise objects.
Definition: Future.h:411
bool valid() const ONIXS_FIXENGINE_NOTHROW
Check if a future instance is associated with an asynchronous result.
Definition: Future.h:123
static const ValueType & value(const ValueBase *value)
Definition: Future.h:92
The shared state is ready.
Definition: Future.h:45
void swap(SharedFuture< T > &other) ONIXS_FIXENGINE_NOTHROW
swaps two SharedFuture objects
Definition: Future.h:294
Promise() ONIXS_FIXENGINE_NOTHROW
Definition: Future.h:383
The base implementation of the PromiseFuture<T>.
Definition: Future.h:321
Promise(const Promise< void > &other) ONIXS_FIXENGINE_NOTHROW
The copy constructor.
Definition: Future.h:453
Promise(const Promise< T > &other) ONIXS_FIXENGINE_NOTHROW
The copy constructor.
Definition: Future.h:387
Promise< void > & operator=(const Promise< void > &other) ONIXS_FIXENGINE_NOTHROW
The copy assignment.
Definition: Future.h:457
Represents a future result of an asynchronous operation - a result that will eventually appear in the...
Definition: Future.h:253
static ValueBase * create(const ValueType &value)
Definition: Future.h:97
void setException(const ExceptionType &exception)
Sets the result to indicate an exception.
Definition: Future.h:497
ValueBase * clone() const ONIXS_FIXENGINE_OVERRIDE
Definition: Future.h:102