@@ -3093,6 +3093,44 @@ namespace details
3093
3093
template <typename _Ty>
3094
3094
static std::false_type _IsValidCreateAsync (_Ty _Param, ...);
3095
3095
#endif /* defined (__cplusplus_winrt) */
3096
+
3097
+ // / <summary>
3098
+ // / A helper class template that makes only movable functions be able to be passed to std::function
3099
+ // / </summary>
3100
+ template <typename _Ty>
3101
+ struct _NonCopyableFunctorWrapper
3102
+ {
3103
+ _NonCopyableFunctorWrapper (_Ty&& f)
3104
+ : _M_functor{std::make_shared<_Ty>(std::forward<_Ty>(f))}
3105
+ {}
3106
+
3107
+ template <class ... _Args>
3108
+ auto operator ()(_Args&&... args) -> decltype(std::declval<_Ty>()(std::forward<_Args>(args)...))
3109
+ {
3110
+ return _M_functor->operator ()(std::forward<_Args>(args)...);
3111
+ }
3112
+
3113
+ template <class ... _Args>
3114
+ auto operator ()(_Args&&... args) const -> decltype(std::declval<_Ty>()(std::forward<_Args>(args)...))
3115
+ {
3116
+ return _M_functor->operator ()(std::forward<_Args>(args)...);
3117
+ }
3118
+
3119
+ std::shared_ptr<_Ty> _M_functor;
3120
+ };
3121
+
3122
+ template <typename _Ty, typename Enable = void >
3123
+ struct _CopyableFunctor
3124
+ {
3125
+ typedef _Ty _Type;
3126
+ };
3127
+
3128
+ template <typename _Ty>
3129
+ struct _CopyableFunctor <_Ty, typename std::enable_if<
3130
+ std::is_move_constructible<_Ty>::value && !std::is_copy_constructible<_Ty>::value>::type>
3131
+ {
3132
+ typedef _NonCopyableFunctorWrapper<_Ty> _Type;
3133
+ };
3096
3134
}
3097
3135
// / <summary>
3098
3136
// / A helper class template that transforms a continuation lambda that either takes or returns void, or both, into a lambda that takes and returns a
@@ -3160,6 +3198,7 @@ class _Init_func_transformer<void>
3160
3198
}
3161
3199
};
3162
3200
3201
+
3163
3202
// / <summary>
3164
3203
// / The Parallel Patterns Library (PPL) <c>task</c> class. A <c>task</c> object represents work that can be executed asynchronously,
3165
3204
// / and concurrently with other tasks and parallel work produced by parallel algorithms in the Concurrency Runtime. It produces
@@ -3424,11 +3463,11 @@ class task
3424
3463
/* */
3425
3464
template <typename _Function>
3426
3465
__declspec (noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
3427
- auto then (const _Function& _Func) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3466
+ auto then (_Function& & _Func) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3428
3467
{
3429
3468
task_options _TaskOptions;
3430
3469
details::_get_internal_task_options (_TaskOptions)._set_creation_callstack (_CAPTURE_CALLSTACK ());
3431
- return _ThenImpl<_ReturnType, _Function>(_Func, _TaskOptions);
3470
+ return _ThenImpl<_ReturnType, _Function>(std::forward<_Function>( _Func) , _TaskOptions);
3432
3471
}
3433
3472
3434
3473
// / <summary>
@@ -3457,10 +3496,10 @@ class task
3457
3496
/* */
3458
3497
template <typename _Function>
3459
3498
__declspec (noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
3460
- auto then (const _Function& _Func, task_options _TaskOptions) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3499
+ auto then (_Function& & _Func, task_options _TaskOptions) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3461
3500
{
3462
3501
details::_get_internal_task_options (_TaskOptions)._set_creation_callstack (_CAPTURE_CALLSTACK ());
3463
- return _ThenImpl<_ReturnType, _Function>(_Func, _TaskOptions);
3502
+ return _ThenImpl<_ReturnType, _Function>(std::forward<_Function>( _Func) , _TaskOptions);
3464
3503
}
3465
3504
3466
3505
// / <summary>
@@ -3493,11 +3532,11 @@ class task
3493
3532
/* */
3494
3533
template <typename _Function>
3495
3534
__declspec (noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
3496
- auto then (const _Function& _Func, cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3535
+ auto then (_Function& & _Func, cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3497
3536
{
3498
3537
task_options _TaskOptions (_CancellationToken, _ContinuationContext);
3499
3538
details::_get_internal_task_options (_TaskOptions)._set_creation_callstack (_CAPTURE_CALLSTACK ());
3500
- return _ThenImpl<_ReturnType, _Function>(_Func, _TaskOptions);
3539
+ return _ThenImpl<_ReturnType, _Function>(std::forward<_Function>( _Func) , _TaskOptions);
3501
3540
}
3502
3541
3503
3542
// / <summary>
@@ -3682,13 +3721,13 @@ class task
3682
3721
// / This function is Used for runtime internal continuations only.
3683
3722
// / </summary>
3684
3723
template <typename _Function>
3685
- auto _Then (const _Function& _Func, details::_CancellationTokenState *_PTokenState,
3724
+ auto _Then (_Function& & _Func, details::_CancellationTokenState *_PTokenState,
3686
3725
details::_TaskInliningMode_t _InliningMode = details::_ForceInline) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
3687
3726
{
3688
3727
// inherit from antecedent
3689
3728
auto _Scheduler = _GetImpl ()->_GetScheduler ();
3690
3729
3691
- return _ThenImpl<_ReturnType, _Function>(_Func, _PTokenState, task_continuation_context::use_default (), _Scheduler, _CAPTURE_CALLSTACK (), _InliningMode);
3730
+ return _ThenImpl<_ReturnType, _Function>(std::forward<_Function>( _Func) , _PTokenState, task_continuation_context::use_default (), _Scheduler, _CAPTURE_CALLSTACK (), _InliningMode);
3692
3731
}
3693
3732
3694
3733
private:
@@ -3801,16 +3840,17 @@ class task
3801
3840
typedef typename details::_NormalizeVoidToUnitType<_ContinuationReturnType>::_Type _NormalizedContinuationReturnType;
3802
3841
3803
3842
typename details::_Task_ptr<_ReturnType>::_Type _M_ancestorTaskImpl;
3804
- _Function _M_function;
3843
+ typename details::_CopyableFunctor< _Function>::_Type _M_function;
3805
3844
3845
+ template <class _ForwardedFunction >
3806
3846
_ContinuationTaskHandle (const typename details::_Task_ptr<_ReturnType>::_Type & _AncestorImpl,
3807
3847
const typename details::_Task_ptr<_NormalizedContinuationReturnType>::_Type & _ContinuationImpl,
3808
- const _Function & _Func, const task_continuation_context & _Context, details::_TaskInliningMode_t _InliningMode)
3848
+ _ForwardedFunction& & _Func, const task_continuation_context & _Context, details::_TaskInliningMode_t _InliningMode)
3809
3849
: details::_PPLTaskHandle<typename details::_NormalizeVoidToUnitType<_ContinuationReturnType>::_Type,
3810
3850
_ContinuationTaskHandle<_InternalReturnType, _ContinuationReturnType, _Function, _IsTaskBased, _TypeSelection>, details::_ContinuationTaskHandleBase>
3811
3851
::_PPLTaskHandle (_ContinuationImpl)
3812
3852
, _M_ancestorTaskImpl(_AncestorImpl)
3813
- , _M_function(_Func)
3853
+ , _M_function(std::forward<_ForwardedFunction>( _Func) )
3814
3854
{
3815
3855
this ->_M_isTaskBasedContinuation = _IsTaskBased::value;
3816
3856
this ->_M_continuationContext = _Context;
@@ -4095,7 +4135,7 @@ class task
4095
4135
}
4096
4136
4097
4137
template <typename _InternalReturnType, typename _Function>
4098
- auto _ThenImpl (const _Function& _Func, const task_options& _TaskOptions) const -> typename details::_ContinuationTypeTraits<_Function, _InternalReturnType>::_TaskOfType
4138
+ auto _ThenImpl (_Function& & _Func, const task_options& _TaskOptions) const -> typename details::_ContinuationTypeTraits<_Function, _InternalReturnType>::_TaskOfType
4099
4139
{
4100
4140
if (!_M_Impl)
4101
4141
{
@@ -4105,14 +4145,14 @@ class task
4105
4145
details::_CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token () ? _TaskOptions.get_cancellation_token ()._GetImplValue () : nullptr ;
4106
4146
auto _Scheduler = _TaskOptions.has_scheduler () ? _TaskOptions.get_scheduler () : _GetImpl ()->_GetScheduler ();
4107
4147
auto _CreationStack = details::_get_internal_task_options (_TaskOptions)._M_hasPresetCreationCallstack ? details::_get_internal_task_options (_TaskOptions)._M_presetCreationCallstack : details::_TaskCreationCallstack ();
4108
- return _ThenImpl<_InternalReturnType, _Function>(_Func, _PTokenState, _TaskOptions.get_continuation_context (), _Scheduler, _CreationStack);
4148
+ return _ThenImpl<_InternalReturnType, _Function>(std::forward<_Function>( _Func) , _PTokenState, _TaskOptions.get_continuation_context (), _Scheduler, _CreationStack);
4109
4149
}
4110
4150
4111
4151
// / <summary>
4112
4152
// / The one and only implementation of then for void and non-void tasks.
4113
4153
// / </summary>
4114
4154
template <typename _InternalReturnType, typename _Function>
4115
- auto _ThenImpl (const _Function& _Func, details::_CancellationTokenState *_PTokenState, const task_continuation_context& _ContinuationContext, scheduler_ptr _Scheduler, details::_TaskCreationCallstack _CreationStack,
4155
+ auto _ThenImpl (_Function& & _Func, details::_CancellationTokenState *_PTokenState, const task_continuation_context& _ContinuationContext, scheduler_ptr _Scheduler, details::_TaskCreationCallstack _CreationStack,
4116
4156
details::_TaskInliningMode_t _InliningMode = details::_NoInline) const -> typename details::_ContinuationTypeTraits<_Function, _InternalReturnType>::_TaskOfType
4117
4157
{
4118
4158
if (!_M_Impl)
@@ -4149,7 +4189,7 @@ class task
4149
4189
_ContinuationTask._SetTaskCreationCallstack (_CreationStack);
4150
4190
4151
4191
_GetImpl ()->_ScheduleContinuation (new _ContinuationTaskHandle<_InternalReturnType, _TaskType, _Function, typename _Function_type_traits::_Takes_task, typename _Async_type_traits::_AsyncKind>(
4152
- _GetImpl (), _ContinuationTask._GetImpl (), _Func, _ContinuationContext, _InliningMode));
4192
+ _GetImpl (), _ContinuationTask._GetImpl (), std::forward<_Function>( _Func) , _ContinuationContext, _InliningMode));
4153
4193
4154
4194
return _ContinuationTask;
4155
4195
}
@@ -4371,10 +4411,10 @@ class task<void>
4371
4411
/* */
4372
4412
template <typename _Function>
4373
4413
__declspec (noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
4374
- auto then (const _Function& _Func, task_options _TaskOptions = task_options()) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
4414
+ auto then (_Function& & _Func, task_options _TaskOptions = task_options()) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
4375
4415
{
4376
4416
details::_get_internal_task_options (_TaskOptions)._set_creation_callstack (_CAPTURE_CALLSTACK ());
4377
- return _M_unitTask._ThenImpl <void , _Function>(_Func, _TaskOptions);
4417
+ return _M_unitTask._ThenImpl <void , _Function>(std::forward<_Function>( _Func) , _TaskOptions);
4378
4418
}
4379
4419
4380
4420
// / <summary>
@@ -4407,11 +4447,11 @@ class task<void>
4407
4447
/* */
4408
4448
template <typename _Function>
4409
4449
__declspec (noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
4410
- auto then (const _Function& _Func, cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
4450
+ auto then (_Function& & _Func, cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
4411
4451
{
4412
4452
task_options _TaskOptions (_CancellationToken, _ContinuationContext);
4413
4453
details::_get_internal_task_options (_TaskOptions)._set_creation_callstack (_CAPTURE_CALLSTACK ());
4414
- return _M_unitTask._ThenImpl <void , _Function>(_Func, _TaskOptions);
4454
+ return _M_unitTask._ThenImpl <void , _Function>(std::forward<_Function>( _Func) , _TaskOptions);
4415
4455
}
4416
4456
4417
4457
// / <summary>
@@ -4555,13 +4595,13 @@ class task<void>
4555
4595
// / An internal version of then that takes additional flags and executes the continuation inline. Used for runtime internal continuations only.
4556
4596
// / </summary>
4557
4597
template <typename _Function>
4558
- auto _Then (const _Function& _Func, details::_CancellationTokenState *_PTokenState,
4598
+ auto _Then (_Function& & _Func, details::_CancellationTokenState *_PTokenState,
4559
4599
details::_TaskInliningMode_t _InliningMode = details::_ForceInline) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
4560
4600
{
4561
4601
// inherit from antecedent
4562
4602
auto _Scheduler = _GetImpl ()->_GetScheduler ();
4563
4603
4564
- return _M_unitTask._ThenImpl <void , _Function>(_Func, _PTokenState, task_continuation_context::use_default (), _Scheduler, _CAPTURE_CALLSTACK (), _InliningMode);
4604
+ return _M_unitTask._ThenImpl <void , _Function>(std::forward<_Function>( _Func) , _PTokenState, task_continuation_context::use_default (), _Scheduler, _CAPTURE_CALLSTACK (), _InliningMode);
4565
4605
}
4566
4606
4567
4607
private:
0 commit comments