MEL
Microthread & Execution library
Future.h
1 #pragma once
2 /*
3  * SPDX-FileCopyrightText: 2005,2022 Daniel Barrientos
4  * <danivillamanin@gmail.com>
5  *
6  * SPDX-License-Identifier: MIT
7  */
8 #include <memory>
9 #include <mpl/TypeTraits.h>
10 #include <mutex>
11 
12 #include <core/CallbackSubscriptor.h>
13 #include <exception>
14 #include <functional>
15 #include <memory>
16 #include <mpl/ReturnAdaptor.h>
17 #include <string>
18 #include <variant>
19 namespace mel
20 {
21  namespace core
22  {
24 
28  enum class EWaitError : int
29  {
30  FUTURE_WAIT_OK = 0,
32  -1,
35  -2,
37  };
39  namespace _private
40  {
41  struct NotAvailable
42  {
43  };
44  template <class T> struct is_ref_wrap
45  {
46  enum
47  {
48  value = false
49  };
50  };
51  template <class T> struct is_ref_wrap<std::reference_wrapper<T>>
52  {
53  enum
54  {
55  value = true
56  };
57  };
58  template <class T> struct return_type
59  {
60  using type = T&;
61  };
62  template <class T> struct return_type<std::reference_wrapper<T>>
63  {
64  using type = typename std::reference_wrapper<T>::type&;
65  };
66  template <class T> struct creturn_type
67  {
68  using type = const T&;
69  };
70  template <class T> struct creturn_type<std::reference_wrapper<T>>
71  {
72  using type = const typename std::reference_wrapper<T>::type&;
73  };
74 
75  } // namespace _private
77 
80  template <class T>
82  : public std::variant<_private::NotAvailable, T, std::exception_ptr>
83  {
84  static constexpr size_t ValidIdx = 1;
85  typedef std::variant<_private::NotAvailable, T, std::exception_ptr>
86  Base;
87 
88  public:
89  typedef T Type;
90  typedef typename _private::return_type<T>::type ReturnType;
91  typedef typename _private::creturn_type<T>::type CReturnType;
92 
93  FutureValue() {}
94  FutureValue( const T& v ) : Base( v ) {}
95  FutureValue( T&& v ) : Base( std::move( v ) ) {}
96  FutureValue( std::exception_ptr err ) : Base( err ) {}
97  FutureValue( const FutureValue& v ) : Base( v ) {}
98  FutureValue( FutureValue&& v ) : Base( std::move( v ) ) {}
102  bool isValid() const { return Base::index() == ValidIdx; }
103  bool isAvailable() const { return Base::index() != 0; }
104  // wrapper for std::get. Same rules as std::Get, so
105  // bad_variant_access is thrown if not a valid value
106  ReturnType value() { return std::get<T>( *this ); }
107  CReturnType value() const { return std::get<T>( *this ); }
108  std::exception_ptr error() const
109  {
110  return std::get<std::exception_ptr>( *this );
111  }
112  auto& operator=( const T& v )
113  {
114  Base::operator=( v );
115  return *this;
116  }
117  auto& operator=( T&& v )
118  {
119  Base::operator=( std::move( v ) );
120  return *this;
121  }
122  auto& operator=( std::exception_ptr v )
123  {
124  Base::operator=( v );
125  return *this;
126  }
127 
128  auto& operator=( const FutureValue& v )
129  {
130  Base::operator=( v );
131  return *this;
132  }
133  auto& operator=( FutureValue& v )
134  {
135  Base::operator=( v );
136  return *this;
137  }
138  auto& operator=( FutureValue&& v )
139  {
140  Base::operator=( std::move( v ) );
141  return *this;
142  }
143  };
145  // specialization for void
146  struct VoidType
147  {
148  };
149  template <>
150  class FutureValue<void>
151  : public std::variant<_private::NotAvailable, VoidType,
152  std::exception_ptr>
153  {
154  static constexpr size_t ValidIdx = 1;
155  typedef std::variant<_private::NotAvailable, VoidType,
156  std::exception_ptr>
157  Base;
158 
159  public:
160  typedef void Type;
161  typedef void ReturnType;
162  typedef void CReturnType;
163  FutureValue() {}
164  FutureValue( std::exception_ptr err ) : Base( err ) {}
168  bool isValid() const { return Base::index() == ValidIdx; }
172  bool isAvailable() const { return Base::index() != 0; }
173  void setValid() { Base::operator=( VoidType() ); }
174  // wrapper for optional::value(). Same rules as std::Get, so
175  // bad_optional_access is thrown if not a valid value
176  std::exception_ptr error() const
177  {
178  return std::get<std::exception_ptr>( *this );
179  }
180  auto& operator=( std::exception_ptr v )
181  {
182  Base::operator=( v );
183  return *this;
184  }
185  };
187  enum EFutureState
188  {
189  NOTAVAILABLE,
190  VALID,
191  INVALID
192  };
193 
195  namespace _private
196  {
200  class FutureData_Base
201  {
202  public:
203  FutureData_Base() : mState( NOTAVAILABLE ) {}
204 
205  virtual ~FutureData_Base() // no me gusta nada que sea virtual.
206  // Intentarlo sin ello
207  {
208  }
209  inline bool getValid() const { return mState == VALID; }
210  inline EFutureState getState() const { return mState; }
212  std::recursive_mutex& getMutex() { return mSC; }
213 
214  protected:
215  mutable std::recursive_mutex mSC;
216  EFutureState mState;
217  };
218  template <typename T>
219  class FutureData
220  : public FutureData_Base,
221  public CallbackSubscriptor<
222  ::mel::core::CSMultithreadPolicy,
223  FutureValue<typename std::conditional<
224  std::is_lvalue_reference<T>::value,
225  std::reference_wrapper<
226  typename std::remove_reference<T>::type>,
227  T>::type>&>,
228  public std::enable_shared_from_this<FutureData<T>>
229  {
230  public:
231  typedef FutureValue<typename std::conditional<
232  std::is_lvalue_reference<T>::value,
233  std::reference_wrapper<
234  typename std::remove_reference<T>::type>,
235  T>::type>
236  ValueType;
237  typedef CallbackSubscriptor<::mel::core::CSMultithreadPolicy,
238  ValueType&>
239  Subscriptor;
243  FutureData(){};
244  ~FutureData(){};
249  template <class U>
250  FutureData( U&& value ) : mValue( std::forward<U>( value ) )
251  {
252  FutureData_Base::mState = VALID;
253  }
254  ValueType& getValue() { return mValue; }
255  const ValueType& getValue() const { return mValue; }
256  //@todo I should improve this function to avoid code bloat.
257  template <class U> void setValue( U&& value )
258  {
259  volatile auto protectMe = FutureData<T>::shared_from_this();
260  FutureData_Base::mSC.lock();
261  if ( mState == NOTAVAILABLE )
262  {
263  mValue = std::forward<U>( value );
264  FutureData_Base::mState = VALID;
265  FutureData_Base::mSC.unlock();
266  Subscriptor::triggerCallbacks( mValue );
267  }
268  else
269  FutureData_Base::mSC.unlock();
270  }
271  void setError( std::exception_ptr ei )
272  {
273  volatile auto protectMe = FutureData<T>::shared_from_this();
274  std::scoped_lock<std::recursive_mutex> lck(
275  FutureData_Base::mSC );
276  if ( mState == NOTAVAILABLE )
277  {
278  mValue = ei;
279  mState = INVALID;
280  Subscriptor::triggerCallbacks( mValue );
281  }
282  };
283  template <class ET> void setError( ET&& ei )
284  {
285  volatile auto protectMe = FutureData<T>::shared_from_this();
286  std::scoped_lock<std::recursive_mutex> lck(
287  FutureData_Base::mSC );
288 
289  if ( mState == NOTAVAILABLE )
290  {
291  mValue =
292  std::make_exception_ptr( std::forward<ET>( ei ) );
293  mState = INVALID;
294  Subscriptor::triggerCallbacks( mValue );
295  }
296  };
297  void assign( const ValueType& val )
298  {
299  std::scoped_lock<std::recursive_mutex> lck(
300  FutureData_Base::mSC );
301  mValue = val;
302  if ( mValue.isAvailable() )
303  {
304  mState = val.isValid() ? VALID : INVALID;
305  Subscriptor::triggerCallbacks( mValue );
306  }
307  else
308  mState = NOTAVAILABLE;
309  }
310  void assign( ValueType&& val )
311  {
312  std::scoped_lock<std::recursive_mutex> lck(
313  FutureData_Base::mSC );
314  mValue = std::move( val );
315  if ( mValue.isAvailable() )
316  {
317  mState = val.isValid() ? VALID : INVALID;
318  Subscriptor::triggerCallbacks( mValue );
319  }
320  else
321  mState = NOTAVAILABLE;
322  }
323 
336  template <class F> int subscribeCallback( F&& f )
337  {
338  std::scoped_lock<std::recursive_mutex> lck(
339  FutureData_Base::mSC );
340  int result = -1;
341  if ( mState != NOTAVAILABLE )
342  {
343  f( mValue );
344  }
345  else
346  {
347  result = Subscriptor::subscribeCallback(
348  std::function<::mel::core::ECallbackResult(
349  ValueType& )>(
350  [f = std::forward<F>( f )](
351  ValueType& vt ) mutable
352  {
353  f( vt );
354  return ::mel::core::ECallbackResult::
355  UNSUBSCRIBE;
356  } ) );
357  }
358  return result;
359  }
360 
361  // because use of lambda, unsubscription can only be done by id
362  // (returned by subscribeCallback)
363  auto unsubscribeCallback( int id )
364  {
365  std::scoped_lock<std::recursive_mutex> lck(
366  FutureData_Base::mSC );
367  return Subscriptor::unsubscribeCallback( id );
368  }
369 
370  private:
371  ValueType mValue;
372  };
373 
374  // specialization for void type. It's intented for functions
375  // returning void but working in a different thread so user need to
376  // know when it finish
377  template <>
378  class FutureData<void>
379  : public FutureData_Base,
380  public CallbackSubscriptor<::mel::core::CSMultithreadPolicy,
381  FutureValue<void>&>,
382  public std::enable_shared_from_this<FutureData<void>>
383  {
384  typedef CallbackSubscriptor<::mel::core::CSMultithreadPolicy,
385  FutureValue<void>&>
386  Subscriptor;
387 
388  public:
389  typedef FutureValue<void> ValueType;
390 
391  FutureData(){};
392 
393  // overload to inicializce as valid
394  FutureData( int )
395  {
396  mValue.setValid();
397  FutureData_Base::mState = VALID;
398  };
399  ~FutureData(){};
400 
401  template <class F> auto subscribeCallback( F&& f )
402  {
403  std::scoped_lock<std::recursive_mutex> lck(
404  FutureData_Base::mSC );
405  bool continueSubscription = true;
406  int result = -1;
407  if ( mState != NOTAVAILABLE )
408  {
409  f( mValue );
410  }
411  else
412  {
413  result = Subscriptor::subscribeCallback(
414  std::function<::mel::core::ECallbackResult(
415  ValueType& )>(
416  [f = std::forward<F>( f )](
417  ValueType& vt ) mutable
418  {
419  f( vt );
420  return ::mel::core::ECallbackResult::
421  UNSUBSCRIBE;
422  } ) );
423  }
424  return result;
425  }
426  // because use of lambda, unsubscription can only be done by id
427  // (returned by subscribeCallback)
428  auto unsubscribeCallback( int id )
429  {
430  std::scoped_lock<std::recursive_mutex> lck(
431  FutureData_Base::mSC );
432  return Subscriptor::unsubscribeCallback( id );
433  }
434  ValueType& getValue() { return mValue; }
435  const ValueType& getValue() const { return mValue; }
436  inline void setValue( void )
437  {
438  volatile auto protectMe =
439  FutureData<void>::shared_from_this();
440  FutureData_Base::mSC.lock();
441  if ( mState == NOTAVAILABLE )
442  {
443  mValue.setValid();
444  FutureData_Base::mState = VALID;
445  FutureData_Base::mSC.unlock();
446  Subscriptor::triggerCallbacks( mValue );
447  }
448  else
449  FutureData_Base::mSC.unlock();
450  }
454  void setError( std::exception_ptr ei )
455  {
456  volatile auto protectMe =
457  FutureData<void>::shared_from_this();
458  FutureData_Base::mSC.lock();
459  if ( mState == NOTAVAILABLE )
460  {
461  mValue = ei;
462  mState = INVALID;
463  Subscriptor::triggerCallbacks( mValue );
464  }
465  FutureData_Base::mSC.unlock();
466  };
467  template <class ET> void setError( ET&& ei )
468  {
469  volatile auto protectMe =
470  FutureData<void>::shared_from_this();
471  std::scoped_lock<std::recursive_mutex> lck(
472  FutureData_Base::mSC );
473  if ( mState == NOTAVAILABLE )
474  {
475  mValue =
476  std::make_exception_ptr( std::forward<ET>( ei ) );
477  mState = INVALID;
478  Subscriptor::triggerCallbacks( mValue );
479  }
480  };
481  void assign( const ValueType& val )
482  {
483  volatile auto protectMe =
484  FutureData<void>::shared_from_this();
485  std::scoped_lock<std::recursive_mutex> lck(
486  FutureData_Base::mSC );
487  mValue = val;
488  if ( mValue.isAvailable() )
489  {
490  mState = val.isValid() ? VALID : INVALID;
491  Subscriptor::triggerCallbacks( mValue );
492  }
493  else
494  mState = NOTAVAILABLE;
495  }
496  void assign( ValueType&& val )
497  {
498  volatile auto protectMe =
499  FutureData<void>::shared_from_this();
500  std::scoped_lock<std::recursive_mutex> lck(
501  FutureData_Base::mSC );
502  mValue = std::move( val );
503  if ( mValue.isAvailable() )
504  {
505  mState = val.isValid() ? VALID : INVALID;
506  Subscriptor::triggerCallbacks( mValue );
507  }
508  else
509  mState = NOTAVAILABLE;
510  }
511 
512  private:
513  ValueType mValue;
514  };
515 
516  class FutureDataContainer
517  {
518  public:
519  FutureDataContainer( std::shared_ptr<FutureData_Base> ptr )
520  : mPtr( ptr )
521  {
522  }
523  inline const std::shared_ptr<FutureData_Base>& getPtr() const
524  {
525  return mPtr;
526  }
527  inline std::shared_ptr<FutureData_Base>& getPtr()
528  {
529  return mPtr;
530  }
531  inline void
532  setPtr( const std::shared_ptr<FutureData_Base>& ptr )
533  {
534  mPtr = ptr;
535  }
536 
537  private:
538  std::shared_ptr<FutureData_Base> mPtr;
539  };
543  class Future_Base
544  {
545  protected:
546  std::shared_ptr<FutureDataContainer> mData;
547  Future_Base() noexcept : mData( nullptr ){};
548 
549  public:
550  Future_Base( const Future_Base& f ) noexcept
551  {
552  mData = f.mData;
553  };
554  Future_Base( Future_Base&& f ) noexcept
555  {
556  mData = std::move( f.mData );
557  };
558 
559  Future_Base& operator=( const Future_Base& f ) noexcept
560  {
561  mData = f.mData;
562  return *this;
563  };
564  Future_Base& operator=( Future_Base&& f ) noexcept
565  {
566  mData = std::move( f.mData );
567  return *this;
568  };
572  inline bool getValid() const noexcept
573  {
574  return mData->getPtr()->getValid();
575  }
576  inline EFutureState getState() const noexcept
577  {
578  return mData->getPtr()->getState();
579  }
580  // Check if given future points to same data
581  inline bool operator==( const Future_Base& f ) const noexcept
582  {
583  return mData == f.mData;
584  };
585  };
586 
587  } // namespace _private
589 
594  template <typename T>
597  : public _private::Future_Base
599  {
600  protected:
601  Future_Common()
602  {
603  mData = std::make_shared<_private::FutureDataContainer>(
604  std::make_shared<_private::FutureData<T>>() );
605  };
606 
607  public:
612  inline const typename _private::FutureData<T>::ValueType&
613  getValue() const
614  {
615  return static_cast<_private::FutureData<T>*>(
616  mData->getPtr().get() )
617  ->getValue();
618  }
623  inline typename _private::FutureData<T>::ValueType& getValue()
624  {
625  return static_cast<_private::FutureData<T>*>(
626  mData->getPtr().get() )
627  ->getValue();
628  }
629  void
630  assign( const typename _private::FutureData<T>::ValueType& val )
631  {
632  getData().assign( val );
633  }
634  void assign( typename _private::FutureData<T>::ValueType&& val )
635  {
636  getData().assign( std::move( val ) );
637  }
647  {
648  auto ptr =
649  mData->getPtr(); // to avoid destruction before unlock
650  std::scoped_lock<std::recursive_mutex, std::recursive_mutex>
651  lck( val.getData().getMutex(), getData().getMutex() );
652  if ( val.getValue().isAvailable() )
653  {
654  auto old = mData->getPtr();
655  setData( val.mData->getPtr() );
656  // if value is already available, tigger callbacks now. It's
657  // more efficient and avoid recursive calls
658  static_cast<_private::FutureData<T>*>( old.get() )
659  ->triggerCallbacks( getData().getValue() );
660  }
661  else
662  {
663  val.getData().append(
664  std::move( getData() ) ); // append callbacks
665  setData( val.mData->getPtr() );
666  }
667  }
681  template <class F> int subscribeCallback( F&& f ) const
682  {
683  //@todo no me gusta un pijo este cast, pero necesito que el
684  // subscribe
685  // actĂșa como mutable
686  return const_cast<Future_Common<T>*>( this )
687  ->getData()
688  .subscribeCallback( std::forward<F>( f ) );
689  }
695  int unsubscribeCallback( int id ) const
696  {
697  return const_cast<Future_Common<T>*>( this )
698  ->getData()
699  .unsubscribeCallback( id );
700  }
701  Future_Common( const Future_Common& f ) noexcept
702  : _private::Future_Base( f )
703  {
704  }
705  Future_Common( Future_Common&& f ) noexcept
706  : _private::Future_Base( std::move( f ) )
707  {
708  }
709  Future_Common& operator=( const Future_Common& f ) noexcept
710  {
711  _private::Future_Base::operator=( f );
712  return *this;
713  };
714  Future_Common& operator=( Future_Common&& f ) noexcept
715  {
716  _private::Future_Base::operator=( std::move( f ) );
717  return *this;
718  };
719 
720  private:
721  inline const _private::FutureData<T>& getData() const
722  {
723  return *static_cast<_private::FutureData<T>*>(
724  mData->getPtr().get() );
725  }
726  inline _private::FutureData<T>& getData()
727  {
728  return *static_cast<_private::FutureData<T>*>(
729  mData->getPtr().get() );
730  }
731  inline void
732  setData( const std::shared_ptr<_private::FutureData_Base>& ptr )
733  {
734  mData->setPtr( ptr );
735  }
736  };
749  template <typename T> class Future : public Future_Common<T>
750  {
751  public:
752  typedef typename _private::FutureData<T>::ValueType ValueType;
753  Future() noexcept {};
754  Future( const Future& f ) noexcept : Future_Common<T>( f ){};
755  Future( Future&& f ) noexcept
756  : Future_Common<T>( std::move( f ) ){};
757  Future( const T& val )
758  {
759  _private::Future_Base::mData =
760  std::make_shared<_private::FutureDataContainer>(
761  std::make_shared<_private::FutureData<T>>( val ) );
762  }
763  Future( T&& val )
764  {
765  _private::Future_Base::mData =
766  std::make_shared<_private::FutureDataContainer>(
767  std::make_shared<_private::FutureData<T>>(
768  std::move( val ) ) );
769  }
770  Future& operator=( const Future& f ) noexcept
771  {
773  return *this;
774  };
775  Future& operator=( Future&& f ) noexcept
776  {
778  return *this;
779  };
780  template <class F> void setValue( F&& value )
781  {
782  static_cast<_private::FutureData<T>*>(
783  Future_Common<T>::mData->getPtr().get() )
784  ->setValue( std::forward<F>( value ) );
785  }
786  template <class F> void setError( F&& ei )
787  {
788  static_cast<_private::FutureData<T>*>(
789  Future_Common<T>::mData->getPtr().get() )
790  ->setError( std::forward<F>( ei ) );
791  }
792  };
794  template <typename T> class Future<T&> : public Future_Common<T&>
795  {
796  public:
797  typedef typename _private::FutureData<T&>::ValueType ValueType;
798  Future() noexcept {};
799  Future( const Future& f ) noexcept : Future_Common<T&>( f ){};
800  Future( Future&& f ) noexcept
801  : Future_Common<T&>( std::move( f ) ){};
802  Future( T& val )
803  {
804  _private::Future_Base::mData =
805  std::make_shared<_private::FutureDataContainer>(
806  std::make_shared<_private::FutureData<T&>>( val ) );
807  }
808  Future& operator=( const Future& f ) noexcept
809  {
810  Future_Common<T&>::operator=( f );
811  return *this;
812  };
813  Future& operator=( Future&& f ) noexcept
814  {
815  Future_Common<T&>::operator=( std::move( f ) );
816  return *this;
817  };
818  template <class F> void setValue( F&& value )
819  {
820  static_cast<_private::FutureData<T&>*>(
821  Future_Common<T&>::mData->getPtr().get() )
822  ->setValue( std::forward<F>( value ) );
823  }
824  template <class F> void setError( F&& ei )
825  {
826  static_cast<_private::FutureData<T&>*>(
827  Future_Common<T&>::mData->getPtr().get() )
828  ->setError( std::forward<F>( ei ) );
829  }
830  };
831 
832  // specialization for void
833  template <> class Future<void> : public Future_Common<void>
834  {
835  public:
836  typedef typename _private::FutureData<void>::ValueType ValueType;
837  Future() noexcept {};
838  // fake initializacion to indicate we want to initialize as valid
839  Future( int a ) noexcept
840  {
841  // _private::Future_Base::mData =
842  // std::make_shared<_private::FutureData<void>>(a);
843  _private::Future_Base::mData =
844  std::make_shared<_private::FutureDataContainer>(
845  std::make_shared<_private::FutureData<void>>( a ) );
846  };
847  Future( const Future& f ) noexcept : Future_Common<void>( f ){};
848  Future( Future&& f ) noexcept
849  : Future_Common<void>( std::move( f ) ){};
850  Future& operator=( const Future& f ) noexcept
851  {
852  Future_Common<void>::operator=( f );
853  return *this;
854  };
855  Future& operator=( Future&& f ) noexcept
856  {
857  Future_Common<void>::operator=( std::move( f ) );
858  return *this;
859  };
860 
861  inline void setValue( void )
862  {
863  static_cast<_private::FutureData<void>*>(
864  Future_Common<void>::mData->getPtr().get() )
865  ->setValue();
866  }
867  template <class F> void setError( F&& ei )
868  {
869  static_cast<_private::FutureData<void>*>(
870  Future_Common<void>::mData->getPtr().get() )
871  ->setError( std::forward<F>( ei ) );
872  }
873  };
875 
881  class WaitException : public std::runtime_error
882  {
883  public:
884  WaitException( EWaitError code, const std::string& msg )
885  : mCode( code ), std::runtime_error( msg )
886  {
887  }
888  WaitException( EWaitError code, std::string&& msg )
889  : mCode( code ), std::runtime_error( std::move( msg ) )
890  {
891  }
892  EWaitError getCode() const { return mCode; }
893 
894  private:
895  EWaitError mCode;
896  };
897 
901  template <class T> class WaitResult
902  {
903  public:
904  WaitResult( const mel::core::Future<T>& f ) : mFut( f ) {}
905  bool isValid() const { return mFut.getValue().isValid(); }
906  typename mel::core::Future<T>::ValueType::CReturnType value() const
907  {
908  return mFut.getValue().value();
909  }
911  {
912  return mFut.getValue().value();
913  }
914  std::exception_ptr error() const
915  {
916  if ( !mErr )
917  return mFut.getValue().error();
918  else
919  return mErr;
920  }
921  void setError( std::exception_ptr err ) { mErr = err; }
923  const mel::core::Future<T>& getFuture() const noexcept
924  {
925  return mFut;
926  }
927  core::Future<T>& getFuture() noexcept { return mFut; }
928 
929  private:
930  core::Future<T> mFut;
931  std::exception_ptr mErr{ nullptr };
932  };
936  {
937  };
941  {
942  };
943 
944  } // namespace core
945 } // namespace mel
Typical Traits for types.
Common code for Futures that doesn't need to be templated.
Definition: Future.h:599
int unsubscribeCallback(int id) const
Unsubscribe given callback.
Definition: Future.h:695
int subscribeCallback(F &&f) const
Subscribe callback to be executed when future is ready (valid or error)
Definition: Future.h:681
const _private::FutureData< T >::ValueType & getValue() const
Get the Value object.
Definition: Future.h:613
_private::FutureData< T >::ValueType & getValue()
Get the Value object.
Definition: Future.h:623
void assign(Future_Common< T > val)
Makes this Future to point to the same value as the given Future.
Definition: Future.h:646
Represents a value that maybe is not present at the current moment.
Definition: Future.h:750
Wrapper for value holded by a Future.
Definition: Future.h:83
bool isValid() const
get if has valid value
Definition: Future.h:102
Exception class generated by WaitResult when wait for future gets an error.
Definition: Future.h:882
Wrapper for future value after wait.
Definition: Future.h:902
const mel::core::Future< T > & getFuture() const noexcept
access internal just if needed to do excepctional things
Definition: Future.h:923
Definition: TypeTraits.h:296
ECallbackResult
Type resturned by callbacks subscribed to CallbackSubscriptors.
Definition: CallbackSubscriptor.h:32
EWaitError
Generic result error codes for future waiting.
Definition: Future.h:29
@ FUTURE_WAIT_TIMEOUT
Time out expired while waiting for Future.
@ FUTURE_UNKNOWN_ERROR
Unknow error while waiting for Future.
@ FUTURE_WAIT_OK
No error.
Small operator==(const AnyType &, const AnyType &)
Definition: Callback_Impl.h:11
Definition: CallbackSubscriptor.h:37
Policy for treating error as exception in future wait functions.
Definition: Future.h:936
Policy for not treating error as exception in future wait functions.
Definition: Future.h:941