Imported Upstream version 1.57.0
[platform/upstream/boost.git] / libs / thread / example / starvephil.cpp
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(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(&xt, 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(&xt, 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(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(&xt, 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(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 }