forked from microsoft/cppwinrt
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwhen.cpp
More file actions
95 lines (75 loc) · 2.37 KB
/
when.cpp
File metadata and controls
95 lines (75 loc) · 2.37 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
#include "pch.h"
#include <pplawait.h>
using namespace concurrency;
using namespace winrt;
using namespace Windows::Foundation;
#ifdef __cpp_lib_coroutine
using std::suspend_never;
#else
using std::experimental::suspend_never;
#endif
struct CommaStruct : suspend_never
{
// If the comma operator is invoked, we will get a build failure.
CommaStruct operator,(CommaStruct) = delete;
// Awaiting the object just returns itself.
auto await_resume() const { return *this; }
};
task<void> ppl(bool& done)
{
co_await resume_background();
done = true;
}
IAsyncAction async(bool& done)
{
co_await resume_background();
done = true;
}
IAsyncOperation<int> when_signaled(int value, handle const& event)
{
co_await resume_on_signal(event.get());
co_return value;
}
IAsyncAction done()
{
co_return;
}
TEST_CASE("when")
{
{
bool ppl_done = false;
bool async_done = false;
// Ensures that different async types can be aggregated.
when_all(ppl(ppl_done), async(async_done)).get();
REQUIRE(ppl_done);
REQUIRE(async_done);
}
{
// Works with IAsyncAction (with no return value).
IAsyncAction result = when_any(done(), done());
result.get();
}
// Verify edge case of empty parameter list.
when_all().get();
// Verify edge case of overloaded comma operator (shame on you).
when_all(CommaStruct{}, CommaStruct{}).get();
{
handle first_event{ check_pointer(CreateEventW(nullptr, true, false, nullptr)) };
handle second_event{ check_pointer(CreateEventW(nullptr, true, false, nullptr)) };
IAsyncOperation<int> first = when_signaled(1, first_event);
IAsyncOperation<int> second = when_signaled(2, second_event);
IAsyncOperation<int> result = when_any(first, second);
// Make sure we're still waiting.
Sleep(100);
REQUIRE(result.Status() == AsyncStatus::Started);
REQUIRE(first.Status() == AsyncStatus::Started);
REQUIRE(second.Status() == AsyncStatus::Started);
// Allow only one of the async objects to complete.
SetEvent(second_event.get());
// This should now complete.
REQUIRE(2 == result.get());
REQUIRE(first.Status() == AsyncStatus::Started);
REQUIRE(second.Status() == AsyncStatus::Completed);
SetEvent(first_event.get());
}
}