Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
e708c1a
Fixing .then to work with movable-only types
AntonBikineev Jan 6, 2016
8b6f832
fix for build on Linux
snikulov Feb 2, 2016
01e3eff
Added prefix to credentials to avoid compilation errors on Linux conf…
leighsmith Feb 9, 2016
58c1a64
Add a project for compiling as a static lib
Feb 9, 2016
f15910c
Merge pull request #65 from snikulov/linux_build_fix
ras0219-msft Feb 26, 2016
9052811
Merge pull request #70 from leighsmith/development
ras0219-msft Feb 26, 2016
2320e0c
Changing use of C++14 capture initialization to usual functor in pplx…
AntonBikineev Feb 27, 2016
ff4f311
Disabling movable_then test on Windows
AntonBikineev Feb 28, 2016
7a07d38
Merge branch 'development' into fixing#418
AntonBikineev Mar 1, 2016
cd97141
Fixing noncopyablewrapper ctor
AntonBikineev Mar 1, 2016
2e23b2a
Adding decay to noncopyablefunctorwrapper
AntonBikineev Mar 2, 2016
5f75ec9
Merge pull request #47 from anton/fixing#418
ras0219-msft Mar 3, 2016
2bf31b7
Fixed ambiguous call to begin when using with boost library.
Mar 3, 2016
ef8e748
Fix use after free in HTTPS listener on non-windows.
ras0219-msft Mar 5, 2016
0d615a1
Fix obtaining raw string_t pointer from temporary
Mar 9, 2016
2b7b52f
Fix typo hexidecimal/hexadecimal
LocutusOfBorg Mar 17, 2016
f063765
Removed redundant std::move() that was causing errors on Xcode 7.3 gcc
leighsmith Mar 30, 2016
42d6366
Merge pull request #96 from locutus/patch-2
ras0219-msft Mar 31, 2016
a13c132
Resolved merge conflicts with PR #71
ras0219-msft Mar 31, 2016
356639d
Adding 'lib' prefix to v140 static lib to prevent collision with impo…
ras0219-msft Mar 31, 2016
43c1c87
Merge pull request #86 from schellap/patch-1
ras0219-msft Mar 31, 2016
fb4aba9
Merge pull request #82 from dogukan/master
ras0219-msft Mar 31, 2016
29ba42e
Merge pull request #114 from leighsmith/xcode7.3
ras0219-msft Mar 31, 2016
5d84d4c
Fixing latin1 to UTF-16 convertion
pp555 Mar 23, 2016
1c4171b
Merge pull request #116 from pp555/fix-latin1-convertion
ras0219-msft Mar 31, 2016
dac2c16
Consolidate x509's into a single file. No need to have a file per (mu…
ras0219 Apr 3, 2016
2b79bd3
Declaration for verify_x509_cert_chain does not need external linkage.
ras0219 Apr 3, 2016
6f5f815
Move definitions from http_helpers into http_msg, removing external d…
ras0219 Apr 3, 2016
9869462
Localized conversion functions from http_helpers.h to http_msg.cpp
ras0219 Apr 3, 2016
9b5ecb1
Move mime_types and charset_types to the header matching the defining…
ras0219 Apr 3, 2016
d3391c8
http_helpers only uses string_t.
ras0219 Apr 3, 2016
a0a0f8d
Refactor http_client_impl.h to be internal.
ras0219 Apr 3, 2016
aff4a1a
Refactor to remove web::http::details::http_network_handler.
ras0219 Apr 3, 2016
7c9189e
Fix android build after refactor.
ras0219-msft Apr 5, 2016
fde3e9a
Update tests to account for outside site fixing bad certificate.
ras0219-msft Apr 14, 2016
f4c8a47
Merge branch fix-https-linux into development
ras0219-msft Apr 14, 2016
98320fe
Hide definition of http_pipeline.
ras0219-msft Apr 14, 2016
baa8c9b
Add final for internal types. Fix docs.
ras0219 Apr 3, 2016
ba2adb3
http_pipeline does not have correct semantics under move.
ras0219-msft Apr 5, 2016
479ebe7
Code review comments for 952a0e22
ras0219-msft Apr 12, 2016
621f0da
Merge branch 'http-pipeline-refactor' into development
ras0219-msft Apr 14, 2016
b332591
Fix move of http_pipeline into web::http::client namespace
ras0219-msft Apr 14, 2016
54d7fcd
Mark add_handler std::function argument as requiring __cdecl to guard…
ras0219-msft Apr 14, 2016
834491e
Improve CMake support for windows.
ras0219-msft Apr 12, 2016
5abe0cb
Merge branch 'improve-buildsystem' into development
ras0219-msft Apr 14, 2016
45ff2f6
Remove extraneous allocation of boost::asio::ssl::stream
ras0219-msft Apr 14, 2016
7ff0685
Update to include access control allow origin
jsonng Apr 17, 2016
b61cbe1
Merge pull request #131 from jsonng/patch-1
ras0219-msft Apr 21, 2016
1e0b5c5
Remove Windows-On-Devices and android test runner from the default so…
ras0219-msft Apr 21, 2016
12619af
Work around SSL compression methods memory leak in ASIO
vadz May 6, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Fixing .then to work with movable-only types
  • Loading branch information
AntonBikineev committed Jan 12, 2016
commit e708c1a9d7304633fa204a1baf3abfd419a0cccd
82 changes: 61 additions & 21 deletions Release/include/pplx/pplxtasks.h
Original file line number Diff line number Diff line change
Expand Up @@ -3093,6 +3093,45 @@ namespace details
template<typename _Ty>
static std::false_type _IsValidCreateAsync(_Ty _Param, ...);
#endif /* defined (__cplusplus_winrt) */

/// <summary>
/// A helper class template that makes only movable functions be able to be passed to std::function
/// </summary>
template<typename _Ty>
struct _NonCopyableFunctorWrapper
{
template<typename _Tx>
_NonCopyableFunctorWrapper(_Tx&& f)
: _M_functor{std::make_shared<_Ty>(std::forward<_Tx>(f))}
{}

template <class... _Args>
auto operator()(_Args&&... args) -> decltype(std::declval<_Ty>()(std::forward<_Args>(args)...))
{
return _M_functor->operator()(std::forward<_Args>(args)...);
}

template <class... _Args>
auto operator()(_Args&&... args) const -> decltype(std::declval<_Ty>()(std::forward<_Args>(args)...))
{
return _M_functor->operator()(std::forward<_Args>(args)...);
}

std::shared_ptr<_Ty> _M_functor;
};

template<typename _Ty, typename Enable = void>
struct _CopyableFunctor
{
typedef _Ty _Type;
};

template<typename _Ty>
struct _CopyableFunctor<_Ty, typename std::enable_if<
std::is_move_constructible<_Ty>::value && !std::is_copy_constructible<_Ty>::value>::type>
{
typedef _NonCopyableFunctorWrapper<_Ty> _Type;
};
}
/// <summary>
/// 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
Expand Down Expand Up @@ -3424,11 +3463,11 @@ class task
/**/
template<typename _Function>
__declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
auto then(const _Function& _Func) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
auto then(_Function&& _Func) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
{
task_options _TaskOptions;
details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(_CAPTURE_CALLSTACK());
return _ThenImpl<_ReturnType, _Function>(_Func, _TaskOptions);
return _ThenImpl<_ReturnType, _Function>(std::forward<_Function>(_Func), _TaskOptions);
}

/// <summary>
Expand Down Expand Up @@ -3457,10 +3496,10 @@ class task
/**/
template<typename _Function>
__declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
auto then(const _Function& _Func, task_options _TaskOptions) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
auto then(_Function&& _Func, task_options _TaskOptions) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
{
details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(_CAPTURE_CALLSTACK());
return _ThenImpl<_ReturnType, _Function>(_Func, _TaskOptions);
return _ThenImpl<_ReturnType, _Function>(std::forward<_Function>(_Func), _TaskOptions);
}

/// <summary>
Expand Down Expand Up @@ -3493,11 +3532,11 @@ class task
/**/
template<typename _Function>
__declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
auto then(const _Function& _Func, cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
auto then(_Function&& _Func, cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
{
task_options _TaskOptions(_CancellationToken, _ContinuationContext);
details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(_CAPTURE_CALLSTACK());
return _ThenImpl<_ReturnType, _Function>(_Func, _TaskOptions);
return _ThenImpl<_ReturnType, _Function>(std::forward<_Function>(_Func), _TaskOptions);
}

/// <summary>
Expand Down Expand Up @@ -3682,13 +3721,13 @@ class task
/// This function is Used for runtime internal continuations only.
/// </summary>
template<typename _Function>
auto _Then(const _Function& _Func, details::_CancellationTokenState *_PTokenState,
auto _Then(_Function&& _Func, details::_CancellationTokenState *_PTokenState,
details::_TaskInliningMode_t _InliningMode = details::_ForceInline) const -> typename details::_ContinuationTypeTraits<_Function, _ReturnType>::_TaskOfType
{
// inherit from antecedent
auto _Scheduler = _GetImpl()->_GetScheduler();

return _ThenImpl<_ReturnType, _Function>(_Func, _PTokenState, task_continuation_context::use_default(), _Scheduler, _CAPTURE_CALLSTACK(), _InliningMode);
return _ThenImpl<_ReturnType, _Function>(std::forward<_Function>(_Func), _PTokenState, task_continuation_context::use_default(), _Scheduler, _CAPTURE_CALLSTACK(), _InliningMode);
}

private:
Expand Down Expand Up @@ -3801,16 +3840,17 @@ class task
typedef typename details::_NormalizeVoidToUnitType<_ContinuationReturnType>::_Type _NormalizedContinuationReturnType;

typename details::_Task_ptr<_ReturnType>::_Type _M_ancestorTaskImpl;
_Function _M_function;
typename details::_CopyableFunctor<_Function>::_Type _M_function;

template <class _ForwardedFunction>
_ContinuationTaskHandle(const typename details::_Task_ptr<_ReturnType>::_Type & _AncestorImpl,
const typename details::_Task_ptr<_NormalizedContinuationReturnType>::_Type & _ContinuationImpl,
const _Function & _Func, const task_continuation_context & _Context, details::_TaskInliningMode_t _InliningMode)
_ForwardedFunction&& _Func, const task_continuation_context & _Context, details::_TaskInliningMode_t _InliningMode)
: details::_PPLTaskHandle<typename details::_NormalizeVoidToUnitType<_ContinuationReturnType>::_Type,
_ContinuationTaskHandle<_InternalReturnType, _ContinuationReturnType, _Function, _IsTaskBased, _TypeSelection>, details::_ContinuationTaskHandleBase>
::_PPLTaskHandle(_ContinuationImpl)
, _M_ancestorTaskImpl(_AncestorImpl)
, _M_function(_Func)
, _M_function(std::forward<_ForwardedFunction>(_Func))
{
this->_M_isTaskBasedContinuation = _IsTaskBased::value;
this->_M_continuationContext = _Context;
Expand Down Expand Up @@ -4095,7 +4135,7 @@ class task
}

template<typename _InternalReturnType, typename _Function>
auto _ThenImpl(const _Function& _Func, const task_options& _TaskOptions) const -> typename details::_ContinuationTypeTraits<_Function, _InternalReturnType>::_TaskOfType
auto _ThenImpl(_Function&& _Func, const task_options& _TaskOptions) const -> typename details::_ContinuationTypeTraits<_Function, _InternalReturnType>::_TaskOfType
{
if (!_M_Impl)
{
Expand All @@ -4105,14 +4145,14 @@ class task
details::_CancellationTokenState *_PTokenState = _TaskOptions.has_cancellation_token() ? _TaskOptions.get_cancellation_token()._GetImplValue() : nullptr;
auto _Scheduler = _TaskOptions.has_scheduler() ? _TaskOptions.get_scheduler() : _GetImpl()->_GetScheduler();
auto _CreationStack = details::_get_internal_task_options(_TaskOptions)._M_hasPresetCreationCallstack ? details::_get_internal_task_options(_TaskOptions)._M_presetCreationCallstack : details::_TaskCreationCallstack();
return _ThenImpl<_InternalReturnType, _Function>(_Func, _PTokenState, _TaskOptions.get_continuation_context(), _Scheduler, _CreationStack);
return _ThenImpl<_InternalReturnType, _Function>(std::forward<_Function>(_Func), _PTokenState, _TaskOptions.get_continuation_context(), _Scheduler, _CreationStack);
}

/// <summary>
/// The one and only implementation of then for void and non-void tasks.
/// </summary>
template<typename _InternalReturnType, typename _Function>
auto _ThenImpl(const _Function& _Func, details::_CancellationTokenState *_PTokenState, const task_continuation_context& _ContinuationContext, scheduler_ptr _Scheduler, details::_TaskCreationCallstack _CreationStack,
auto _ThenImpl(_Function&& _Func, details::_CancellationTokenState *_PTokenState, const task_continuation_context& _ContinuationContext, scheduler_ptr _Scheduler, details::_TaskCreationCallstack _CreationStack,
details::_TaskInliningMode_t _InliningMode = details::_NoInline) const -> typename details::_ContinuationTypeTraits<_Function, _InternalReturnType>::_TaskOfType
{
if (!_M_Impl)
Expand Down Expand Up @@ -4149,7 +4189,7 @@ class task
_ContinuationTask._SetTaskCreationCallstack(_CreationStack);

_GetImpl()->_ScheduleContinuation(new _ContinuationTaskHandle<_InternalReturnType, _TaskType, _Function, typename _Function_type_traits::_Takes_task, typename _Async_type_traits::_AsyncKind>(
_GetImpl(), _ContinuationTask._GetImpl(), _Func, _ContinuationContext, _InliningMode));
_GetImpl(), _ContinuationTask._GetImpl(), std::forward<_Function>(_Func), _ContinuationContext, _InliningMode));

return _ContinuationTask;
}
Expand Down Expand Up @@ -4371,10 +4411,10 @@ class task<void>
/**/
template<typename _Function>
__declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
auto then(const _Function& _Func, task_options _TaskOptions = task_options()) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
auto then(_Function&& _Func, task_options _TaskOptions = task_options()) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
{
details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(_CAPTURE_CALLSTACK());
return _M_unitTask._ThenImpl<void, _Function>(_Func, _TaskOptions);
return _M_unitTask._ThenImpl<void, _Function>(std::forward<_Function>(_Func), _TaskOptions);
}

/// <summary>
Expand Down Expand Up @@ -4407,11 +4447,11 @@ class task<void>
/**/
template<typename _Function>
__declspec(noinline) // Ask for no inlining so that the _CAPTURE_CALLSTACK gives us the expected result
auto then(const _Function& _Func, cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
auto then(_Function&& _Func, cancellation_token _CancellationToken, task_continuation_context _ContinuationContext) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
{
task_options _TaskOptions(_CancellationToken, _ContinuationContext);
details::_get_internal_task_options(_TaskOptions)._set_creation_callstack(_CAPTURE_CALLSTACK());
return _M_unitTask._ThenImpl<void, _Function>(_Func, _TaskOptions);
return _M_unitTask._ThenImpl<void, _Function>(std::forward<_Function>(_Func), _TaskOptions);
}

/// <summary>
Expand Down Expand Up @@ -4555,13 +4595,13 @@ class task<void>
/// An internal version of then that takes additional flags and executes the continuation inline. Used for runtime internal continuations only.
/// </summary>
template<typename _Function>
auto _Then(const _Function& _Func, details::_CancellationTokenState *_PTokenState,
auto _Then(_Function&& _Func, details::_CancellationTokenState *_PTokenState,
details::_TaskInliningMode_t _InliningMode = details::_ForceInline) const -> typename details::_ContinuationTypeTraits<_Function, void>::_TaskOfType
{
// inherit from antecedent
auto _Scheduler = _GetImpl()->_GetScheduler();

return _M_unitTask._ThenImpl<void, _Function>(_Func, _PTokenState, task_continuation_context::use_default(), _Scheduler, _CAPTURE_CALLSTACK(), _InliningMode);
return _M_unitTask._ThenImpl<void, _Function>(std::forward<_Function>(_Func), _PTokenState, task_continuation_context::use_default(), _Scheduler, _CAPTURE_CALLSTACK(), _InliningMode);
}

private:
Expand Down
15 changes: 15 additions & 0 deletions Release/tests/functional/pplx/pplx_test/pplxtask_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,21 @@ TEST(TestTasks_void_tasks_default_construction)
}
}

TEST(TestTasks_movable_then)
{
struct A
{
A() = default;
A(A&&) = default;
A& operator=(A&&) = default;
} a;

task<int> task = create_task([]{ return 2; });
auto f = task.then([a = std::move(a)](int) { return 'c'; });

IsTrue(f.get() == 'c', L".then should be able to work with movable functors");
}

TEST(TestTasks_constant_this)
{
#ifdef _MSC_VER
Expand Down