starvephil.cpp 4.9 KB

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