This repository was archived by the owner on Dec 14, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathlatch_test.cpp
More file actions
117 lines (98 loc) · 3.3 KB
/
latch_test.cpp
File metadata and controls
117 lines (98 loc) · 3.3 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
110
111
112
113
114
115
116
117
//
// 32.8 Coordination types [thread.coord]
// 32.8.1 Latches [thread.latch]
// 32.8.1.2 class latch [thread.latch.class]
//
#define CATCH_CONFIG_MAIN
#define CATCH_CONFIG_GLOBAL_NEXTAFTER
#define CATCH_CONFIG_FAST_COMPILE
#include <catch2/catch.hpp>
#include <chrono>
#include <future>
#if defined(__APPLE__)
#include <latch_darwin.h>
#else
#include <latch.h>
#endif
using namespace std;
using namespace std::chrono;
TEST_CASE("latch ctor zero") {
latch wg{0}; // Expects: expected >= 0 is true
REQUIRE(wg.try_wait()); // counter == 0
}
TEST_CASE("latch ctor negative") {
latch wg{-1}; // Expects: expected >= 0 is true
auto update = 0;
// Expects: update >= 0 is true and update <= counter is true
REQUIRE(update >= 0);
// !!! update <= counter is false !!!
REQUIRE_THROWS_AS(wg.count_down(update), std::system_error);
}
TEST_CASE("latch ctor positive") {
latch wg{1}; // Expects: expected >= 0 is true
SECTION("count_down and wait") {
REQUIRE_NOTHROW(wg.count_down(1));
wg.wait();
}
SECTION("count_down and try_wait") {
REQUIRE_NOTHROW(wg.count_down(1));
REQUIRE(wg.try_wait());
}
SECTION("arrive_and_wait") {
REQUIRE_NOTHROW(wg.arrive_and_wait(1));
}
}
TEST_CASE("latch wait") {
latch wg{2};
SECTION("wait then count_down") {
auto f = async(launch::async, //
[&wg]() -> void {
// blocks on *this until a call to count_down that decrements counter to zero
return wg.wait();
});
this_thread::sleep_for(milliseconds{300});
REQUIRE_NOTHROW(wg.count_down(1));
REQUIRE_NOTHROW(wg.count_down(1));
REQUIRE_NOTHROW(f.get()); // wait returned without exception
}
SECTION("count_down then wait") {
REQUIRE_NOTHROW(wg.count_down(2));
REQUIRE_NOTHROW(wg.wait()); // already reached 0
}
SECTION("wait mutliple times") {
// wg.count_down(2);
// wg.wait();
REQUIRE_NOTHROW(wg.arrive_and_wait(2));
REQUIRE_NOTHROW(
wg.wait()); // if counter equals zero, returns immediately
}
}
TEST_CASE("latch try_wait") {
latch wg{1};
SECTION("wait then count_down") {
auto f = async(launch::async, //
[&wg]() -> bool {
// With very low probability false, Otherwise counter == 0
return wg.try_wait();
});
REQUIRE_NOTHROW(wg.count_down(1));
this_thread::sleep_for(milliseconds{300});
REQUIRE(f.get() == true); // TODO: check system error code toghether
}
}
TEST_CASE("latch awake") {
latch wg{3};
SECTION("awake multiple threads") {
auto f1 = async(launch::async, //
[&wg]() -> bool { return wg.try_wait(); });
auto f2 = async(launch::async, //
[&wg]() -> void { return wg.wait(); });
auto f3 = async(launch::async, //
[&wg]() -> void { return wg.arrive_and_wait(2); });
REQUIRE_NOTHROW(wg.count_down(1));
this_thread::sleep_for(milliseconds{300});
REQUIRE(f1.get() == true);
REQUIRE_NOTHROW(f2.get());
REQUIRE_NOTHROW(f3.get());
}
}