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 | #define BOOST_THREAD_VERSION 2 |
8 | |
9 | #include <boost/thread/mutex.hpp> |
10 | #include <boost/thread/condition.hpp> |
11 | #include <boost/thread/thread_only.hpp> |
12 | #include <boost/thread/xtime.hpp> |
13 | #include <iostream> |
14 | #include <time.h> |
15 | |
16 | namespace |
17 | { |
18 | boost::mutex iomx; |
19 | } // namespace |
20 | |
21 | class canteen |
22 | { |
23 | public: |
24 | canteen() : m_chickens(0) { } |
25 | |
26 | void get(int id) |
27 | { |
28 | boost::unique_lock<boost::mutex> lock(m_mutex); |
29 | while (m_chickens == 0) |
30 | { |
31 | { |
32 | boost::unique_lock<boost::mutex> lk(iomx); |
33 | std::cout << "(" << clock() << ") Phil" << id << |
34 | ": wot, no chickens? I'll WAIT ..." << std::endl; |
35 | } |
36 | m_condition.wait(m&: lock); |
37 | } |
38 | { |
39 | boost::unique_lock<boost::mutex> lk(iomx); |
40 | std::cout << "(" << clock() << ") Phil" << id << |
41 | ": those chickens look good ... one please ..." << std::endl; |
42 | } |
43 | m_chickens--; |
44 | } |
45 | void put(int value) |
46 | { |
47 | boost::unique_lock<boost::mutex> lock(m_mutex); |
48 | { |
49 | boost::unique_lock<boost::mutex> lk(iomx); |
50 | std::cout << "(" << clock() |
51 | << ") Chef: ouch ... make room ... this dish is " |
52 | << "very hot ..." << std::endl; |
53 | } |
54 | boost::xtime xt; |
55 | boost::xtime_get(xtp: &xt, clock_type: boost::TIME_UTC_); |
56 | xt.sec += 3; |
57 | boost::thread::sleep(xt); |
58 | m_chickens += value; |
59 | { |
60 | boost::unique_lock<boost::mutex> lk(iomx); |
61 | std::cout << "(" << clock() << |
62 | ") Chef: more chickens ... " << m_chickens << |
63 | " now available ... NOTIFYING ..." << std::endl; |
64 | } |
65 | m_condition.notify_all(); |
66 | } |
67 | |
68 | private: |
69 | boost::mutex m_mutex; |
70 | boost::condition m_condition; |
71 | int m_chickens; |
72 | }; |
73 | |
74 | canteen g_canteen; |
75 | |
76 | void chef() |
77 | { |
78 | const int chickens = 4; |
79 | { |
80 | boost::unique_lock<boost::mutex> lock(iomx); |
81 | std::cout << "(" << clock() << ") Chef: starting ..." << std::endl; |
82 | } |
83 | for (;;) |
84 | { |
85 | { |
86 | boost::unique_lock<boost::mutex> lock(iomx); |
87 | std::cout << "(" << clock() << ") Chef: cooking ..." << std::endl; |
88 | } |
89 | boost::xtime xt; |
90 | boost::xtime_get(xtp: &xt, clock_type: boost::TIME_UTC_); |
91 | xt.sec += 2; |
92 | boost::thread::sleep(xt); |
93 | { |
94 | boost::unique_lock<boost::mutex> lock(iomx); |
95 | std::cout << "(" << clock() << ") Chef: " << chickens |
96 | << " chickens, ready-to-go ..." << std::endl; |
97 | } |
98 | g_canteen.put(value: chickens); |
99 | } |
100 | } |
101 | |
102 | struct phil |
103 | { |
104 | phil(int id) : m_id(id) { } |
105 | void run() { |
106 | { |
107 | boost::unique_lock<boost::mutex> lock(iomx); |
108 | std::cout << "(" << clock() << ") Phil" << m_id |
109 | << ": starting ..." << std::endl; |
110 | } |
111 | for (;;) |
112 | { |
113 | if (m_id > 0) |
114 | { |
115 | boost::xtime xt; |
116 | boost::xtime_get(xtp: &xt, clock_type: boost::TIME_UTC_); |
117 | xt.sec += 3; |
118 | boost::thread::sleep(xt); |
119 | } |
120 | { |
121 | boost::unique_lock<boost::mutex> lk(iomx); |
122 | std::cout << "(" << clock() << ") Phil" << m_id |
123 | << ": gotta eat ..." << std::endl; |
124 | } |
125 | g_canteen.get(id: m_id); |
126 | { |
127 | boost::unique_lock<boost::mutex> lk(iomx); |
128 | std::cout << "(" << clock() << ") Phil" << m_id |
129 | << ": mmm ... that's good ..." << std::endl; |
130 | } |
131 | } |
132 | } |
133 | static void do_thread(void* param) { |
134 | static_cast<phil*>(param)->run(); |
135 | } |
136 | |
137 | int m_id; |
138 | }; |
139 | |
140 | struct thread_adapt |
141 | { |
142 | thread_adapt(void (*func)(void*), void* param) |
143 | : _func(func), _param(param) |
144 | { |
145 | } |
146 | int operator()() const |
147 | { |
148 | _func(_param); |
149 | return 0; |
150 | } |
151 | |
152 | void (*_func)(void*); |
153 | void* _param; |
154 | }; |
155 | |
156 | class thread_adapter |
157 | { |
158 | public: |
159 | thread_adapter(void (*func)(void*), void* param) |
160 | : _func(func), _param(param) |
161 | { |
162 | } |
163 | void operator()() const { _func(_param); } |
164 | private: |
165 | void (*_func)(void*); |
166 | void* _param; |
167 | }; |
168 | |
169 | int main() |
170 | { |
171 | boost::thread thrd_chef(&chef); |
172 | phil p[] = { phil(0), phil(1), phil(2), phil(3), phil(4) }; |
173 | boost::thread thrd_phil0(thread_adapter(&phil::do_thread, &p[0])); |
174 | boost::thread thrd_phil1(thread_adapter(&phil::do_thread, &p[1])); |
175 | boost::thread thrd_phil2(thread_adapter(&phil::do_thread, &p[2])); |
176 | boost::thread thrd_phil3(thread_adapter(&phil::do_thread, &p[3])); |
177 | boost::thread thrd_phil4(thread_adapter(&phil::do_thread, &p[4])); |
178 | |
179 | thrd_chef.join(); |
180 | thrd_phil0.join(); |
181 | thrd_phil1.join(); |
182 | thrd_phil2.join(); |
183 | thrd_phil3.join(); |
184 | thrd_phil4.join(); |
185 | |
186 | return 0; |
187 | } |
188 | |