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
16namespace
17{
18boost::mutex iomx;
19} // namespace
20
21class canteen
22{
23public:
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
68private:
69 boost::mutex m_mutex;
70 boost::condition m_condition;
71 int m_chickens;
72};
73
74canteen g_canteen;
75
76void 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
102struct 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
140struct 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
156class thread_adapter
157{
158public:
159 thread_adapter(void (*func)(void*), void* param)
160 : _func(func), _param(param)
161 {
162 }
163 void operator()() const { _func(_param); }
164private:
165 void (*_func)(void*);
166 void* _param;
167};
168
169int 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

source code of boost/libs/thread/example/starvephil.cpp