12 #include <core/CallbackSubscriptor.h>
16 #include <mpl/ReturnAdaptor.h>
44 template <
class T>
struct is_ref_wrap
51 template <
class T>
struct is_ref_wrap<std::reference_wrapper<T>>
58 template <
class T>
struct return_type
62 template <
class T>
struct return_type<std::reference_wrapper<T>>
64 using type =
typename std::reference_wrapper<T>::type&;
66 template <
class T>
struct creturn_type
68 using type =
const T&;
70 template <
class T>
struct creturn_type<std::reference_wrapper<T>>
72 using type =
const typename std::reference_wrapper<T>::type&;
82 :
public std::variant<_private::NotAvailable, T, std::exception_ptr>
84 static constexpr
size_t ValidIdx = 1;
85 typedef std::variant<_private::NotAvailable, T, std::exception_ptr>
90 typedef typename _private::return_type<T>::type ReturnType;
91 typedef typename _private::creturn_type<T>::type CReturnType;
96 FutureValue( std::exception_ptr err ) : Base( err ) {}
102 bool isValid()
const {
return Base::index() == ValidIdx; }
103 bool isAvailable()
const {
return Base::index() != 0; }
106 ReturnType value() {
return std::get<T>( *
this ); }
107 CReturnType value()
const {
return std::get<T>( *
this ); }
108 std::exception_ptr error()
const
110 return std::get<std::exception_ptr>( *
this );
112 auto& operator=(
const T& v )
114 Base::operator=( v );
117 auto& operator=( T&& v )
119 Base::operator=( std::move( v ) );
122 auto& operator=( std::exception_ptr v )
124 Base::operator=( v );
128 auto& operator=(
const FutureValue& v )
130 Base::operator=( v );
133 auto& operator=( FutureValue& v )
135 Base::operator=( v );
138 auto& operator=( FutureValue&& v )
140 Base::operator=( std::move( v ) );
150 class FutureValue<void>
151 :
public std::variant<_private::NotAvailable, VoidType,
154 static constexpr
size_t ValidIdx = 1;
155 typedef std::variant<_private::NotAvailable, VoidType,
161 typedef void ReturnType;
162 typedef void CReturnType;
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() ); }
176 std::exception_ptr error()
const
178 return std::get<std::exception_ptr>( *
this );
180 auto& operator=( std::exception_ptr v )
182 Base::operator=( v );
200 class FutureData_Base
203 FutureData_Base() : mState( NOTAVAILABLE ) {}
205 virtual ~FutureData_Base()
209 inline bool getValid()
const {
return mState == VALID; }
210 inline EFutureState getState()
const {
return mState; }
212 std::recursive_mutex& getMutex() {
return mSC; }
215 mutable std::recursive_mutex mSC;
218 template <
typename T>
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>,
228 public std::enable_shared_from_this<FutureData<T>>
231 typedef FutureValue<
typename std::conditional<
232 std::is_lvalue_reference<T>::value,
233 std::reference_wrapper<
234 typename std::remove_reference<T>::type>,
250 FutureData( U&& value ) : mValue( std::forward<U>( value ) )
252 FutureData_Base::mState = VALID;
254 ValueType& getValue() {
return mValue; }
255 const ValueType& getValue()
const {
return mValue; }
257 template <
class U>
void setValue( U&& value )
259 volatile auto protectMe = FutureData<T>::shared_from_this();
260 FutureData_Base::mSC.lock();
261 if ( mState == NOTAVAILABLE )
263 mValue = std::forward<U>( value );
264 FutureData_Base::mState = VALID;
265 FutureData_Base::mSC.unlock();
266 Subscriptor::triggerCallbacks( mValue );
269 FutureData_Base::mSC.unlock();
271 void setError( std::exception_ptr ei )
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 )
280 Subscriptor::triggerCallbacks( mValue );
283 template <
class ET>
void setError( ET&& ei )
285 volatile auto protectMe = FutureData<T>::shared_from_this();
286 std::scoped_lock<std::recursive_mutex> lck(
287 FutureData_Base::mSC );
289 if ( mState == NOTAVAILABLE )
292 std::make_exception_ptr( std::forward<ET>( ei ) );
294 Subscriptor::triggerCallbacks( mValue );
297 void assign(
const ValueType& val )
299 std::scoped_lock<std::recursive_mutex> lck(
300 FutureData_Base::mSC );
302 if ( mValue.isAvailable() )
304 mState = val.isValid() ? VALID : INVALID;
305 Subscriptor::triggerCallbacks( mValue );
308 mState = NOTAVAILABLE;
310 void assign( ValueType&& val )
312 std::scoped_lock<std::recursive_mutex> lck(
313 FutureData_Base::mSC );
314 mValue = std::move( val );
315 if ( mValue.isAvailable() )
317 mState = val.isValid() ? VALID : INVALID;
318 Subscriptor::triggerCallbacks( mValue );
321 mState = NOTAVAILABLE;
336 template <
class F>
int subscribeCallback( F&& f )
338 std::scoped_lock<std::recursive_mutex> lck(
339 FutureData_Base::mSC );
341 if ( mState != NOTAVAILABLE )
347 result = Subscriptor::subscribeCallback(
350 [f = std::forward<F>( f )](
351 ValueType& vt )
mutable
354 return ::mel::core::ECallbackResult::
363 auto unsubscribeCallback(
int id )
365 std::scoped_lock<std::recursive_mutex> lck(
366 FutureData_Base::mSC );
367 return Subscriptor::unsubscribeCallback(
id );
378 class FutureData<void>
379 :
public FutureData_Base,
380 public CallbackSubscriptor<::mel::core::CSMultithreadPolicy,
382 public std::enable_shared_from_this<FutureData<void>>
389 typedef FutureValue<void> ValueType;
397 FutureData_Base::mState = VALID;
401 template <
class F>
auto subscribeCallback( F&& f )
403 std::scoped_lock<std::recursive_mutex> lck(
404 FutureData_Base::mSC );
405 bool continueSubscription =
true;
407 if ( mState != NOTAVAILABLE )
413 result = Subscriptor::subscribeCallback(
416 [f = std::forward<F>( f )](
417 ValueType& vt )
mutable
420 return ::mel::core::ECallbackResult::
428 auto unsubscribeCallback(
int id )
430 std::scoped_lock<std::recursive_mutex> lck(
431 FutureData_Base::mSC );
432 return Subscriptor::unsubscribeCallback(
id );
434 ValueType& getValue() {
return mValue; }
435 const ValueType& getValue()
const {
return mValue; }
436 inline void setValue(
void )
438 volatile auto protectMe =
439 FutureData<void>::shared_from_this();
440 FutureData_Base::mSC.lock();
441 if ( mState == NOTAVAILABLE )
444 FutureData_Base::mState = VALID;
445 FutureData_Base::mSC.unlock();
446 Subscriptor::triggerCallbacks( mValue );
449 FutureData_Base::mSC.unlock();
454 void setError( std::exception_ptr ei )
456 volatile auto protectMe =
457 FutureData<void>::shared_from_this();
458 FutureData_Base::mSC.lock();
459 if ( mState == NOTAVAILABLE )
463 Subscriptor::triggerCallbacks( mValue );
465 FutureData_Base::mSC.unlock();
467 template <
class ET>
void setError( ET&& ei )
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 )
476 std::make_exception_ptr( std::forward<ET>( ei ) );
478 Subscriptor::triggerCallbacks( mValue );
481 void assign(
const ValueType& val )
483 volatile auto protectMe =
484 FutureData<void>::shared_from_this();
485 std::scoped_lock<std::recursive_mutex> lck(
486 FutureData_Base::mSC );
488 if ( mValue.isAvailable() )
490 mState = val.isValid() ? VALID : INVALID;
491 Subscriptor::triggerCallbacks( mValue );
494 mState = NOTAVAILABLE;
496 void assign( ValueType&& val )
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() )
505 mState = val.isValid() ? VALID : INVALID;
506 Subscriptor::triggerCallbacks( mValue );
509 mState = NOTAVAILABLE;
516 class FutureDataContainer
519 FutureDataContainer( std::shared_ptr<FutureData_Base> ptr )
523 inline const std::shared_ptr<FutureData_Base>& getPtr()
const
527 inline std::shared_ptr<FutureData_Base>& getPtr()
532 setPtr(
const std::shared_ptr<FutureData_Base>& ptr )
538 std::shared_ptr<FutureData_Base> mPtr;
546 std::shared_ptr<FutureDataContainer> mData;
547 Future_Base() noexcept : mData(
nullptr ){};
550 Future_Base(
const Future_Base& f ) noexcept
554 Future_Base( Future_Base&& f ) noexcept
556 mData = std::move( f.mData );
559 Future_Base& operator=(
const Future_Base& f ) noexcept
564 Future_Base& operator=( Future_Base&& f ) noexcept
566 mData = std::move( f.mData );
572 inline bool getValid() const noexcept
574 return mData->getPtr()->getValid();
576 inline EFutureState getState() const noexcept
578 return mData->getPtr()->getState();
581 inline bool operator==(
const Future_Base& f )
const noexcept
583 return mData == f.mData;
594 template <
typename T>
597 :
public _private::Future_Base
603 mData = std::make_shared<_private::FutureDataContainer>(
604 std::make_shared<_private::FutureData<T>>() );
612 inline const typename _private::FutureData<T>::ValueType&
615 return static_cast<_private::FutureData<T>*
>(
616 mData->getPtr().get() )
623 inline typename _private::FutureData<T>::ValueType&
getValue()
625 return static_cast<_private::FutureData<T>*
>(
626 mData->getPtr().get() )
630 assign(
const typename _private::FutureData<T>::ValueType& val )
632 getData().assign( val );
634 void assign(
typename _private::FutureData<T>::ValueType&& val )
636 getData().assign( std::move( val ) );
650 std::scoped_lock<std::recursive_mutex, std::recursive_mutex>
651 lck( val.getData().getMutex(), getData().getMutex() );
654 auto old = mData->getPtr();
655 setData( val.mData->getPtr() );
658 static_cast<_private::FutureData<T>*
>( old.get() )
659 ->triggerCallbacks( getData().getValue() );
663 val.getData().append(
664 std::move( getData() ) );
665 setData( val.mData->getPtr() );
688 .subscribeCallback( std::forward<F>( f ) );
699 .unsubscribeCallback(
id );
702 : _private::Future_Base( f )
705 Future_Common( Future_Common&& f ) noexcept
706 : _private::Future_Base( std::move( f ) )
709 Future_Common& operator=(
const Future_Common& f ) noexcept
711 _private::Future_Base::operator=( f );
714 Future_Common& operator=( Future_Common&& f ) noexcept
716 _private::Future_Base::operator=( std::move( f ) );
721 inline const _private::FutureData<T>& getData()
const
723 return *
static_cast<_private::FutureData<T>*
>(
724 mData->getPtr().get() );
726 inline _private::FutureData<T>& getData()
728 return *
static_cast<_private::FutureData<T>*
>(
729 mData->getPtr().get() );
732 setData(
const std::shared_ptr<_private::FutureData_Base>& ptr )
734 mData->setPtr( ptr );
752 typedef typename _private::FutureData<T>::ValueType ValueType;
759 _private::Future_Base::mData =
760 std::make_shared<_private::FutureDataContainer>(
761 std::make_shared<_private::FutureData<T>>( val ) );
765 _private::Future_Base::mData =
766 std::make_shared<_private::FutureDataContainer>(
767 std::make_shared<_private::FutureData<T>>(
768 std::move( val ) ) );
780 template <
class F>
void setValue( F&& value )
782 static_cast<_private::FutureData<T>*
>(
784 ->setValue( std::forward<F>( value ) );
786 template <
class F>
void setError( F&& ei )
788 static_cast<_private::FutureData<T>*
>(
790 ->setError( std::forward<F>( ei ) );
797 typedef typename _private::FutureData<T&>::ValueType ValueType;
799 Future(
const Future& f ) noexcept : Future_Common<T&>( f ){};
800 Future( Future&& f ) noexcept
801 : Future_Common<T&>( std::move( f ) ){};
804 _private::Future_Base::mData =
805 std::make_shared<_private::FutureDataContainer>(
806 std::make_shared<_private::FutureData<T&>>( val ) );
808 Future& operator=(
const Future& f ) noexcept
810 Future_Common<T&>::operator=( f );
813 Future& operator=( Future&& f ) noexcept
815 Future_Common<T&>::operator=( std::move( f ) );
818 template <
class F>
void setValue( F&& value )
820 static_cast<_private::FutureData<T&>*
>(
821 Future_Common<T&>::mData->getPtr().get() )
822 ->setValue( std::forward<F>( value ) );
824 template <
class F>
void setError( F&& ei )
826 static_cast<_private::FutureData<T&>*
>(
827 Future_Common<T&>::mData->getPtr().get() )
828 ->setError( std::forward<F>( ei ) );
833 template <>
class Future<void> :
public Future_Common<void>
836 typedef typename _private::FutureData<void>::ValueType ValueType;
837 Future() noexcept {};
839 Future(
int a ) noexcept
843 _private::Future_Base::mData =
844 std::make_shared<_private::FutureDataContainer>(
845 std::make_shared<_private::FutureData<void>>( a ) );
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
852 Future_Common<void>::operator=( f );
855 Future& operator=( Future&& f ) noexcept
857 Future_Common<void>::operator=( std::move( f ) );
861 inline void setValue(
void )
863 static_cast<_private::FutureData<void>*
>(
864 Future_Common<void>::mData->getPtr().get() )
867 template <
class F>
void setError( F&& ei )
869 static_cast<_private::FutureData<void>*
>(
870 Future_Common<void>::mData->getPtr().get() )
871 ->setError( std::forward<F>( ei ) );
885 : mCode( code ), std::runtime_error( msg )
889 : mCode( code ), std::runtime_error( std::move( msg ) )
905 bool isValid()
const {
return mFut.getValue().isValid(); }
908 return mFut.getValue().value();
912 return mFut.getValue().value();
914 std::exception_ptr error()
const
917 return mFut.getValue().error();
921 void setError( std::exception_ptr err ) { mErr = err; }
931 std::exception_ptr mErr{
nullptr };
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_RECEIVED_KILL_SIGNAL
@ 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