1 | // Copyright (C) 2001-2003 |
2 | // William E. Kempf |
3 | // |
4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
6 | |
7 | #undef BOOST_THREAD_VERSION |
8 | #define BOOST_THREAD_VERSION 2 |
9 | |
10 | #include <boost/thread/mutex.hpp> |
11 | #include <boost/thread/condition.hpp> |
12 | #include <boost/thread/thread_only.hpp> |
13 | #include <boost/thread/xtime.hpp> |
14 | #include <iostream> |
15 | |
16 | #if defined(BOOST_HAS_WINTHREADS) |
17 | # include <windows.h> |
18 | # include <process.h> |
19 | #endif |
20 | |
21 | enum game_state |
22 | { |
23 | START, |
24 | PLAYER_A, |
25 | PLAYER_B, |
26 | GAME_OVER, |
27 | ONE_PLAYER_GONE, |
28 | BOTH_PLAYERS_GONE |
29 | }; |
30 | |
31 | int state; |
32 | boost::mutex mutex; |
33 | boost::condition cond; |
34 | |
35 | const char* player_name(int state) |
36 | { |
37 | if (state == PLAYER_A) |
38 | return "PLAYER-A" ; |
39 | if (state == PLAYER_B) |
40 | return "PLAYER-B" ; |
41 | throw "bad player" ; |
42 | //return 0; |
43 | } |
44 | |
45 | void player(int active) |
46 | { |
47 | boost::unique_lock<boost::mutex> lock(mutex); |
48 | |
49 | int other = active == PLAYER_A ? PLAYER_B : PLAYER_A; |
50 | |
51 | while (state < GAME_OVER) |
52 | { |
53 | //std::cout << player_name(active) << ": Play." << std::endl; |
54 | state = other; |
55 | cond.notify_all(); |
56 | do |
57 | { |
58 | cond.wait(m&: lock); |
59 | if (state == other) |
60 | { |
61 | std::cout << "---" << player_name(state: active) |
62 | << ": Spurious wakeup!" << std::endl; |
63 | } |
64 | } while (state == other); |
65 | } |
66 | |
67 | ++state; |
68 | std::cout << player_name(state: active) << ": Gone." << std::endl; |
69 | cond.notify_all(); |
70 | } |
71 | |
72 | struct thread_adapt |
73 | { |
74 | thread_adapt(void (*func)(void*), void* param) |
75 | : _func(func), _param(param) |
76 | { |
77 | } |
78 | int operator()() const |
79 | { |
80 | _func(_param); |
81 | return 0; |
82 | } |
83 | |
84 | void (*_func)(void*); |
85 | void* _param; |
86 | }; |
87 | |
88 | class thread_adapter |
89 | { |
90 | public: |
91 | thread_adapter(void (*func)(void*), void* param) |
92 | : _func(func), _param(param) |
93 | { |
94 | } |
95 | void operator()() const { _func(_param); } |
96 | private: |
97 | void (*_func)(void*); |
98 | void* _param; |
99 | }; |
100 | |
101 | int main() |
102 | { |
103 | state = START; |
104 | |
105 | boost::thread thrda(&player, PLAYER_A); |
106 | boost::thread thrdb(&player, PLAYER_B); |
107 | |
108 | boost::xtime xt; |
109 | boost::xtime_get(xtp: &xt, clock_type: boost::TIME_UTC_); |
110 | xt.sec += 1; |
111 | boost::thread::sleep(xt); |
112 | { |
113 | boost::unique_lock<boost::mutex> lock(mutex); |
114 | std::cout << "---Noise ON..." << std::endl; |
115 | } |
116 | |
117 | for (int i = 0; i < 10; ++i) |
118 | cond.notify_all(); |
119 | |
120 | { |
121 | boost::unique_lock<boost::mutex> lock(mutex); |
122 | std::cout << "---Noise OFF..." << std::endl; |
123 | state = GAME_OVER; |
124 | cond.notify_all(); |
125 | do |
126 | { |
127 | cond.wait(m&: lock); |
128 | } while (state != BOTH_PLAYERS_GONE); |
129 | } |
130 | |
131 | std::cout << "GAME OVER" << std::endl; |
132 | |
133 | thrda.join(); |
134 | thrdb.join(); |
135 | |
136 | return 0; |
137 | } |
138 | |