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 #include <vector> 8 #include <iostream> 9 #include <boost/thread/condition_variable.hpp> 10 #include <boost/thread/mutex.hpp> 11 #include <boost/thread/recursive_mutex.hpp> 12 #include <boost/thread/thread_only.hpp> 13 14 namespace { 15 const int ITERS = 100; 16 boost::mutex io_mutex; 17 } // namespace 18 19 template <typename M> 20 class buffer_t 21 { 22 public: 23 typedef boost::unique_lock<M> scoped_lock; 24 buffer_t(int n)25 buffer_t(int n) 26 : p(0), c(0), full(0), buf(n) 27 { 28 } 29 send(int m)30 void send(int m) 31 { 32 scoped_lock lk(mutex); 33 while (full == buf.size()) 34 cond.wait(lk); 35 buf[p] = m; 36 p = (p+1) % buf.size(); 37 ++full; 38 cond.notify_one(); 39 } receive()40 int receive() 41 { 42 scoped_lock lk(mutex); 43 while (full == 0) 44 cond.wait(lk); 45 int i = buf[c]; 46 c = (c+1) % buf.size(); 47 --full; 48 cond.notify_one(); 49 return i; 50 } 51 get_buffer()52 static buffer_t& get_buffer() 53 { 54 static buffer_t buf(2); 55 return buf; 56 } 57 do_sender_thread()58 static void do_sender_thread() 59 { 60 for (int n = 0; n < ITERS; ++n) 61 { 62 { 63 boost::unique_lock<boost::mutex> lock(io_mutex); 64 std::cout << "sending: " << n << std::endl; 65 } 66 get_buffer().send(n); 67 } 68 } 69 do_receiver_thread()70 static void do_receiver_thread() 71 { 72 for (int x=0; x < (ITERS/2); ++x) 73 { 74 int n = get_buffer().receive(); 75 { 76 boost::unique_lock<boost::mutex> lock(io_mutex); 77 std::cout << "received: " << n << std::endl; 78 } 79 } 80 } 81 82 private: 83 M mutex; 84 boost::condition_variable_any cond; 85 unsigned int p, c, full; 86 std::vector<int> buf; 87 }; 88 89 template <typename M> do_test(M * dummy=0)90void do_test(M* dummy=0) 91 { 92 (void)dummy; 93 typedef buffer_t<M> buffer_type; 94 buffer_type::get_buffer(); 95 boost::thread thrd1(&buffer_type::do_receiver_thread); 96 boost::thread thrd2(&buffer_type::do_receiver_thread); 97 boost::thread thrd3(&buffer_type::do_sender_thread); 98 thrd1.join(); 99 thrd2.join(); 100 thrd3.join(); 101 } 102 test_buffer()103void test_buffer() 104 { 105 do_test<boost::mutex>(); 106 do_test<boost::recursive_mutex>(); 107 } 108 main()109int main() 110 { 111 test_buffer(); 112 return 0; 113 } 114