-
Notifications
You must be signed in to change notification settings - Fork 186
/
debug_async_scope_test.cpp
100 lines (88 loc) · 3.12 KB
/
debug_async_scope_test.cpp
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
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* Licensed under the Apache License Version 2.0 with LLVM Exceptions
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* https://llvm.org/LICENSE.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <unifex/async_manual_reset_event.hpp>
#include <unifex/inplace_stop_token.hpp>
#include <unifex/just_from.hpp>
#include <unifex/nest.hpp>
#include <unifex/scheduler_concepts.hpp>
#include <unifex/single_thread_context.hpp>
#include <unifex/spawn_detached.hpp>
#include <unifex/sync_wait.hpp>
#include <unifex/v1/async_scope.hpp>
#include <unifex/v1/debug_async_scope.hpp>
#include <unifex/v2/async_scope.hpp>
#include <unifex/v2/debug_async_scope.hpp>
#include <chrono>
#include <cstdio>
#include <thread>
#include <gtest/gtest.h>
using namespace unifex;
using namespace std::chrono;
using namespace std::literals;
// guaranteed to deadlock, useful for validating operation states can be
// inspected in a debugger
// use --gtest_also_run_disabled_tests to run manually
TEST(Debug, DISABLED_SyncWaitDeadlockV1) {
v1::debug_async_scope scope;
spawn_detached(
just_from([&scope]() noexcept { //
sync_wait(scope.complete()); //
}),
scope);
}
TEST(Debug, DISABLED_SyncWaitDeadlockV1Meth) {
v1::debug_async_scope scope;
scope.detached_spawn(just_from([&scope]() noexcept { //
sync_wait(scope.complete()); //
}));
}
TEST(Debug, DISABLED_SyncWaitDeadlockV1TooLate) {
single_thread_context ctx;
v1::debug_async_scope scope;
async_manual_reset_event evt;
std::atomic_bool scheduled{false};
// wait for evt to be set on a background thread; note that the `async_wait()`
// _Sender_ is unstoppable
auto fut = scope.spawn_on(
ctx.get_scheduler(),
sequence(
just_from([&scheduled]() noexcept { scheduled = true; }),
evt.async_wait()));
// wait for the scheduled op to be started
while (!scheduled) {
continue;
}
// send a stop request to all the Senders spawned within the scope; this will
// trigger the future to cancel itself, but not the unstoppable `async_wait()`
scope.request_stop();
// with the scope joined, pending futures should all immediately
// complete with done. result has no value.
auto result = sync_wait(std::move(fut));
ASSERT_FALSE(result.has_value());
// but the scope itself won't complete until the spawned work is actually
// done so we will be stuck waiting for the event to be signaled
sync_wait(scope.cleanup());
// it's too late. this should be called before `scope.cleanup()`
evt.set();
}
TEST(Debug, DISABLED_SyncWaitDeadlockV2) {
v2::debug_async_scope scope;
spawn_detached(
just_from([&scope]() noexcept { //
sync_wait(scope.join()); //
}),
scope);
}