Skip to content

Commit c60b35d

Browse files
authored
Merge pull request microsoft#10 from Esri/kevi9186/i832_continuations_scheduling_gap
Provide scheduler_ptr to _ScheduleFuncWithAutoInline
2 parents 532b377 + 59f647f commit c60b35d

File tree

4 files changed

+66
-8
lines changed

4 files changed

+66
-8
lines changed

Release/include/pplx/pplx.h

+11-3
Original file line numberDiff line numberDiff line change
@@ -176,16 +176,24 @@ class _TaskCollectionImpl
176176
scheduler_ptr _GetScheduler() const { return _M_pScheduler; }
177177

178178
// Fire and forget
179-
static void _RunTask(TaskProc_t _Proc, void* _Parameter, _TaskInliningMode _InliningMode)
179+
static void _RunTask(TaskProc_t _Proc, void* _Parameter, _TaskInliningMode _InliningMode, scheduler_ptr _Scheduler)
180180
{
181181
if (_InliningMode == _ForceInline)
182182
{
183183
_Proc(_Parameter);
184184
}
185185
else
186186
{
187-
// Schedule the work on the ambient scheduler
188-
get_ambient_scheduler()->schedule(_Proc, _Parameter);
187+
if (_Scheduler.get())
188+
{
189+
// Schedule the work on the desired scheduler
190+
_Scheduler->schedule(_Proc, _Parameter);
191+
}
192+
else
193+
{
194+
// Schedule the work on the ambient scheduler as a fallback
195+
get_ambient_scheduler()->schedule(_Proc, _Parameter);
196+
}
189197
}
190198
}
191199

Release/include/pplx/pplxtasks.h

+5-2
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,10 @@ struct _TaskProcThunk
603603
/// <param name="_InliningMode">
604604
/// The inlining scheduling policy for current functor.
605605
/// </param>
606-
void _ScheduleFuncWithAutoInline(const std::function<void()>& _Func, _TaskInliningMode_t _InliningMode);
606+
/// <param name="_Scheduler">
607+
/// The intended Scheduler to run the task on.
608+
/// </param>
609+
void _ScheduleFuncWithAutoInline(const std::function<void()>& _Func, _TaskInliningMode_t _InliningMode, scheduler_ptr _Scheduler);
607610

608611
class _ContextCallback
609612
{
@@ -1671,7 +1674,7 @@ struct _Task_impl : public _Task_impl_base
16711674
if (_M_Continuations)
16721675
{
16731676
// Scheduling cancellation with automatic inlining.
1674-
_ScheduleFuncWithAutoInline([=]() { _RunTaskContinuations(); }, details::_DefaultAutoInline);
1677+
_ScheduleFuncWithAutoInline([=]() { _RunTaskContinuations(); }, details::_DefaultAutoInline, _M_TaskCollection._GetScheduler());
16751678
}
16761679
}
16771680
return true;

Release/src/pplx/pplxtasks.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,9 @@ namespace details
7979
delete _M_pThunk;
8080
}
8181

82-
void _ScheduleFuncWithAutoInline(const std::function<void()> & _Func, _TaskInliningMode_t _InliningMode)
82+
void _ScheduleFuncWithAutoInline(const std::function<void()> & _Func, _TaskInliningMode_t _InliningMode, scheduler_ptr _Scheduler)
8383
{
84-
_TaskCollection_t::_RunTask(&_TaskProcThunk::_Bridge, new _TaskProcThunk(_Func), _InliningMode);
84+
_TaskCollection_t::_RunTask(&_TaskProcThunk::_Bridge, new _TaskProcThunk(_Func), _InliningMode, _Scheduler);
8585
}
8686

8787
#if defined (__cplusplus_winrt)
@@ -965,7 +965,8 @@ namespace details
965965
}
966966
}
967967
},
968-
_PTaskHandle->_M_inliningMode);
968+
_PTaskHandle->_M_inliningMode,
969+
_M_TaskCollection._GetScheduler());
969970
}
970971
else
971972
{

Release/tests/functional/pplx/pplx_test/pplx_task_options.cpp

+46
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class TaskOptionsTestScheduler : public pplx::scheduler_interface
3939
{
4040
public:
4141
TaskOptionsTestScheduler() : m_numTasks(0), m_scheduler(get_scheduler()) {}
42+
TaskOptionsTestScheduler(std::shared_ptr<pplx::scheduler_interface> scheduler) : m_numTasks(0), m_scheduler(std::move(scheduler)) {}
4243

4344
virtual void schedule(pplx::TaskProc_t proc, void* param)
4445
{
@@ -159,6 +160,24 @@ SUITE(pplx_task_options_tests)
159160
VERIFY_ARE_EQUAL(sched1.get_num_tasks(), 1);
160161
VERIFY_ARE_EQUAL(sched2.get_num_tasks(), 2);
161162
}
163+
164+
TEST(then_from_exception_custom_scheduler_test)
165+
{
166+
class custom_direct_executor : public pplx::scheduler_interface
167+
{
168+
public:
169+
virtual void schedule(pplx::TaskProc_t proc, _In_ void* param) { proc(param); }
170+
};
171+
172+
TaskOptionsTestScheduler sched(std::make_shared<custom_direct_executor>());
173+
long n = 0;
174+
175+
auto t1 = pplx::create_task([&n]() { n++; throw std::runtime_error("exception"); }, sched);
176+
t1.then([&n](pplx::task<void> task_result) { n++; try { task_result.get(); } catch (...){} }) // inherit sched
177+
.wait();
178+
179+
VERIFY_ARE_EQUAL(sched.get_num_tasks(), n);
180+
}
162181

163182
TEST(opand_nooptions_test)
164183
{
@@ -260,6 +279,33 @@ SUITE(pplx_task_options_tests)
260279
VERIFY_ARE_EQUAL(sched2.get_num_tasks(), 0);
261280
}
262281

282+
TEST(whenall_then_from_exception_custom_scheduler_test)
283+
{
284+
class custom_direct_executor : public pplx::scheduler_interface
285+
{
286+
public:
287+
virtual void schedule(pplx::TaskProc_t proc, _In_ void* param) { proc(param); }
288+
};
289+
290+
TaskOptionsTestScheduler sched(std::make_shared<custom_direct_executor>());
291+
292+
std::vector<pplx::task<void>> taskVect;
293+
const int task_count = 3;
294+
long n = 0;
295+
for (int i = 0; i < (task_count-1); i++)
296+
{
297+
taskVect.push_back(pplx::create_task([&n]() {n++;}, sched));
298+
}
299+
taskVect.push_back(pplx::create_task([&n]() { n++; throw std::runtime_error("exception");}, sched));
300+
301+
auto t3 = pplx::when_all(
302+
begin(taskVect), end(taskVect), sched);
303+
n++; // sched used within when_all
304+
t3.then([&n](pplx::task<void> task_result) { n++; try { task_result.get(); } catch (...){} }, sched).wait();
305+
306+
VERIFY_ARE_EQUAL(sched.get_num_tasks(), n);
307+
}
308+
263309
TEST(opor_nooptions_test)
264310
{
265311
TaskOptionsTestScheduler sched;

0 commit comments

Comments
 (0)