-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathppltasks_extra.h
105 lines (95 loc) · 4.41 KB
/
ppltasks_extra.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#pragma once
#include <ppltasks.h>
#include <agents.h>
#include <memory>
#include <chrono>
namespace Concurrency
{
namespace extras
{
namespace details
{
static void iterative_task_impl(concurrency::task_completion_event<void> finished, std::function<concurrency::task<bool>()> body, concurrency::cancellation_token ct)
{
body().then([=] (concurrency::task<bool> previous) {
try {
if (previous.get())
iterative_task_impl(finished, body, ct);
else
finished.set();
} catch (...) {
finished.set_exception(std::current_exception());
}
}, ct);
}
} // namespace details
/// <summary>
/// Creates a task from given user Functor, which will be scheduled after <paramref name="delay"/> million senconds.
/// </summary>
/// <typeparam name="Func">
/// The type of the user task Functor.
/// </typeparam>
/// <param name="delay">
/// The delay before starting the task.
/// </param>
/// <param name="func">
/// The user task Functor.
/// </param>
/// <param name="token">
/// The optional cancellation token, which will be passed to the return task.
/// </param>
/// <returns>
/// It will return a task constructed with user Functor <paramref name="func"/>, and cancellation token <paramref name="token"/>.
/// The returning task will be scheduled after <paramref name="delay"/> million seconds.
/// </returns>
/// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
/**/
template <typename Func>
auto create_delayed_task(std::chrono::milliseconds delay, Func func, concurrency::cancellation_token token = concurrency::cancellation_token::none()) -> decltype(create_task(func))
{
concurrency::task_completion_event<void> tce;
auto pTimer = new concurrency::timer<int>(static_cast<int>(delay.count()), 0, NULL, false);
auto pCallback = new concurrency::call<int>([tce](int) {
tce.set();
});
pTimer->link_target(pCallback);
pTimer->start();
return create_task(tce).then([pCallback, pTimer]() {
delete pCallback;
delete pTimer;
}).then(func, token);
}
/// <summary>
/// Creates a task iteratively execute user Functor. During the process, each new iteration will be the continuation of the
/// last iteration's returning task, and the process will keep going on until the Boolean value from returning task becomes False.
/// </summary>
/// <param name="body">
/// The user Functor used as loop body. It is required to return a task with type bool, which used as predictor that decides
/// whether the loop needs to be continued.
/// </param>
/// <param name="ct">
/// The cancellation token linked to the iterative task.
/// </param>
/// <returns>
/// The task that will perform the asynchronous iterative execution.
/// </returns>
/// <remarks>
/// This function dynamically creates a long chain of continuations by iteratively concating tasks created by user Functor <paramref name="body"/>,
/// The iteration will not stop until the result of the returning task from user Functor <paramref name="body"/> is <c> False </c>.
/// </remarks>
/// <seealso cref="Task Parallelism (Concurrency Runtime)"/>
/**/
inline task<void> create_iterative_task(std::function<concurrency::task<bool>()> body, cancellation_token ct = cancellation_token::none())
{
concurrency::task_completion_event<void> finished;
create_task([=] {
try {
details::iterative_task_impl(finished, body, ct);
} catch (...) {
finished.set_exception(std::current_exception());
}
}, ct);
return create_task(finished, ct);
}
}
}