-
Notifications
You must be signed in to change notification settings - Fork 277
Expand file tree
/
Copy pathasync_progress.cpp
More file actions
109 lines (89 loc) · 2.97 KB
/
Copy pathasync_progress.cpp
File metadata and controls
109 lines (89 loc) · 2.97 KB
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
106
107
108
109
#include "pch.h"
using namespace winrt;
using namespace Windows::Foundation;
namespace
{
//
// Checks that progress reporting works.
//
IAsyncActionWithProgress<int> Action(HANDLE event)
{
co_await resume_on_signal(event);
auto progress = co_await get_progress_token();
progress(123);
}
IAsyncOperationWithProgress<hstring, int> Operation(HANDLE event)
{
co_await resume_on_signal(event);
// Invoke from a lambda to ensure that operator() is const.
[progress = co_await get_progress_token()]()
{
progress.set_result(L"working");
progress(123);
}();
co_return L"done";
}
template <typename F>
IAsyncAction Check(F make)
{
// Event not set to allow Progress handler to be wired up.
handle start{ CreateEvent(nullptr, true, false, nullptr) };
auto async = make(start.get());
using TResult = decltype(async.GetResults());
bool progress = false;
async.Progress([&](auto&& sender, int value)
{
progress = true;
REQUIRE(async == sender);
REQUIRE(async.Status() == AsyncStatus::Started);
if constexpr (std::is_same_v<TResult, hstring>)
{
REQUIRE(async.GetResults() == L"working");
// Confirm that reading does not destroy partial results.
REQUIRE(async.GetResults() == L"working");
}
REQUIRE(value == 123);
});
SetEvent(start.get());
co_await async;
REQUIRE(progress);
REQUIRE(async.Status() == AsyncStatus::Completed);
REQUIRE(async.ErrorCode() == S_OK);
// Confirm that you can read results from a completed WithProgress multiple times.
// (We must allow this to avoid race conditions where a progress callback
// does async work and then tries to read an intermediate result, only to
// discover that the operation has already completed.)
if constexpr (std::is_same_v<TResult, hstring>)
{
REQUIRE(async.GetResults() == L"done");
}
else
{
REQUIRE_NOTHROW(async.GetResults());
}
}
template <typename F>
IAsyncAction TooLate(F make)
{
// Event initially set so that coroutine does not suspend.
handle start{ CreateEvent(nullptr, true, true, nullptr) };
auto async = make(start.get());
REQUIRE(async.Status() == AsyncStatus::Completed);
bool progress = false;
async.Progress([&](auto&&...)
{
REQUIRE(false);
});
co_await async;
REQUIRE(!progress);
REQUIRE(async.Status() == AsyncStatus::Completed);
REQUIRE(async.ErrorCode() == S_OK);
}
}
TEST_CASE("async_progress")
{
Check(Action);
Check(Operation);
TooLate(Action);
TooLate(Operation);
}