Skip to content

Commit 333c3c4

Browse files
committed
Add event_wait_handle example
1 parent 3283199 commit 333c3c4

File tree

4 files changed

+215
-0
lines changed

4 files changed

+215
-0
lines changed

examples/xtd.core.examples/threading/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ find_package(xtd REQUIRED)
55

66
add_projects(
77
auto_reset_event
8+
event_wait_handle
89
interlocked
910
interlocked_decrement
1011
mixing_std_and_xtd_threads
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
cmake_minimum_required(VERSION 3.5)
2+
3+
project(event_wait_handle)
4+
find_package(xtd REQUIRED)
5+
add_sources(README.md src/event_wait_handle.cpp)
6+
target_type(CONSOLE_APPLICATION)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# auto_reset_event
2+
3+
Shows how to use [xtd::threading::auto_reset_event](https://gammasoft71.github.io/xtd/reference_guides/latest/classxtd_1_1threading_1_1auto_reset_event.html) class.
4+
5+
## Sources
6+
7+
[src/auto_reset_event.cpp](src/auto_reset_event.cpp)
8+
9+
[CMakeLists.txt](CMakeLists.txt)
10+
11+
# Build and run
12+
13+
Open "Command Prompt" or "Terminal". Navigate to the folder that contains the project and type the following:
14+
15+
```cmake
16+
xtdc run
17+
```
18+
19+
# Output
20+
21+
```
22+
Press Enter to create three threads and start them.
23+
The threads wait on auto_reset_event #1, which was created
24+
in the signaled state, so the first thread is released.
25+
This puts auto_reset_event #1 into the unsignaled state.
26+
27+
thread_0x16fe87000 waits on auto_reset_event #1.
28+
thread_0x16fe87000 is released from auto_reset_event #1.
29+
thread_0x16fe87000 waits on auto_reset_event #2.
30+
thread_0x16ff13000 waits on auto_reset_event #1.
31+
thread_0x16ff9f000 waits on auto_reset_event #1.
32+
Press Enter to release another thread.
33+
34+
thread_0x16ff9f000 is released from auto_reset_event #1.
35+
thread_0x16ff9f000 waits on auto_reset_event #2.
36+
Press Enter to release another thread.
37+
38+
thread_0x16ff13000 is released from auto_reset_event #1.
39+
thread_0x16ff13000 waits on auto_reset_event #2.
40+
41+
All threads are now waiting on auto_reset_event #2.
42+
Press Enter to release a thread.
43+
44+
thread_0x16ff9f000 is released from auto_reset_event #2.
45+
thread_0x16ff9f000 ends.
46+
Press Enter to release a thread.
47+
48+
thread_0x16fe87000 is released from auto_reset_event #2.
49+
thread_0x16fe87000 ends.
50+
Press Enter to release a thread.
51+
52+
thread_0x16ff13000 is released from auto_reset_event #2.
53+
thread_0x16ff13000 ends.
54+
```
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
#include <xtd/threading/event_wait_handle>
2+
#include <xtd/threading/interlocked>
3+
#include <xtd/threading/thread>
4+
#include <xtd/console>
5+
#include <xtd/startup>
6+
7+
using namespace xtd;
8+
using namespace xtd::threading;
9+
10+
class example {
11+
private:
12+
// The event_wait_handle used to demonstrate the difference
13+
// between auto_reset and manual_reset synchronization events.
14+
//
15+
inline static event_wait_handle ewh;
16+
17+
// A counter to make sure all threads are started and
18+
// blocked before any are released. A Long is used to show
19+
// the use of the 64-bit Interlocked methods.
20+
//
21+
inline static int64 thread_count = 0;
22+
23+
// An auto_reset event that allows the main thread to block
24+
// until an exiting thread has decremented the count.
25+
//
26+
inline static event_wait_handle clear_count {false, event_reset_mode::auto_reset};
27+
28+
public:
29+
static void main() {
30+
// Create an auto_reset event_wait_handle.
31+
//
32+
ewh = event_wait_handle {false, event_reset_mode::auto_reset};
33+
34+
// Create and start five numbered threads. Use the
35+
// ParameterizedThreadStart delegate, so the thread
36+
// number can be passed as an argument to the Start
37+
// method.
38+
for (int i = 0; i <= 4; i++) {
39+
threads[i] = thread {parameterized_thread_start {thread_proc}};
40+
threads[i].start(i);
41+
}
42+
43+
// Wait until all the threads have started and blocked.
44+
// When multiple threads use a 64-bit value on a 32-bit
45+
// system, you must access the value through the
46+
// Interlocked class to guarantee thread safety.
47+
//
48+
while (interlocked::read(thread_count) < 5) {
49+
thread::sleep(500);
50+
}
51+
52+
// Release one thread each time the user presses ENTER,
53+
// until all threads have been released.
54+
//
55+
while (interlocked::read(thread_count) > 0) {
56+
console::write_line("Press ENTER to release a waiting thread.");
57+
console::read_line();
58+
59+
// SignalAndWait signals the event_wait_handle, which
60+
// releases exactly one thread before resetting,
61+
// because it was created with auto_reset mode.
62+
// SignalAndWait then blocks on clear_count, to
63+
// allow the signaled thread to decrement the count
64+
// before looping again.
65+
//
66+
wait_handle::signal_and_wait(ewh, clear_count);
67+
}
68+
console::write_line();
69+
70+
// Create a manual_reset event_wait_handle.
71+
//
72+
ewh = event_wait_handle(false, event_reset_mode::manual_reset);
73+
74+
// Create and start five more numbered threads.
75+
//
76+
for(int i = 0; i <= 4; i++) {
77+
threads[i] = thread {parameterized_thread_start {thread_proc}};
78+
threads[i].start(i);
79+
}
80+
81+
// Wait until all the threads have started and blocked.
82+
//
83+
while (interlocked::read(thread_count) < 5) {
84+
thread::sleep(500);
85+
}
86+
87+
// Because the event_wait_handle was created with
88+
// manual_reset mode, signaling it releases all the
89+
// waiting threads.
90+
//
91+
console::write_line("Press ENTER to release the waiting threads.");
92+
console::read_line();
93+
ewh.set();
94+
}
95+
96+
static void thread_proc(std::any data) {
97+
console::write_line("Thread {0} blocks.", as<int>(data));
98+
// Increment the count of blocked threads.
99+
interlocked::increment(thread_count);
100+
101+
// Wait on the event_wait_handle.
102+
ewh.wait_one();
103+
104+
console::write_line("Thread {0} exits.", as<int>(data));
105+
// Decrement the count of blocked threads.
106+
interlocked::decrement(thread_count);
107+
108+
// After signaling ewh, the main thread blocks on
109+
// clear_count until the signaled thread has
110+
// decremented the count. Signal it now.
111+
//
112+
clear_count.set();
113+
}
114+
115+
inline static std::vector<thread> threads = std::vector<thread>(4);
116+
};
117+
118+
startup_(example);
119+
120+
// This example produces output similar to the following:
121+
//
122+
// Thread 2 blocks.
123+
// Thread 4 blocks.
124+
// Thread 0 blocks.
125+
// Thread 1 blocks.
126+
// Thread 3 blocks.
127+
// Press ENTER to release a waiting thread.
128+
//
129+
// Thread 4 exits.
130+
// Press ENTER to release a waiting thread.
131+
//
132+
// Thread 2 exits.
133+
// Press ENTER to release a waiting thread.
134+
//
135+
// Thread 0 exits.
136+
// Press ENTER to release a waiting thread.
137+
//
138+
// Thread 1 exits.
139+
// Press ENTER to release a waiting thread.
140+
//
141+
// Thread 3 exits.
142+
//
143+
// Thread 0 blocks.
144+
// Thread 1 blocks.
145+
// Thread 3 blocks.
146+
// Thread 2 blocks.
147+
// Thread 4 blocks.
148+
// Press ENTER to release the waiting threads.
149+
//
150+
// Thread 2 exits.
151+
// Thread 1 exits.
152+
// Thread 4 exits.
153+
// Thread 3 exits.
154+
// Thread 0 exits.

0 commit comments

Comments
 (0)