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 
player_name(int state)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 
player(int active)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(lock);
59             if (state == other)
60             {
61                 std::cout << "---" << player_name(active)
62                           << ": Spurious wakeup!" << std::endl;
63             }
64         } while (state == other);
65     }
66 
67     ++state;
68     std::cout << player_name(active) << ": Gone." << std::endl;
69     cond.notify_all();
70 }
71 
72 struct thread_adapt
73 {
thread_adaptthread_adapt74     thread_adapt(void (*func)(void*), void* param)
75         : _func(func), _param(param)
76     {
77     }
operator ()thread_adapt78     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:
thread_adapter(void (* func)(void *),void * param)91     thread_adapter(void (*func)(void*), void* param)
92         : _func(func), _param(param)
93     {
94     }
operator ()() const95     void operator()() const { _func(_param); }
96 private:
97     void (*_func)(void*);
98     void* _param;
99 };
100 
main()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(&xt, 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(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