• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)90 void 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()103 void test_buffer()
104 {
105     do_test<boost::mutex>();
106     do_test<boost::recursive_mutex>();
107 }
108 
main()109 int main()
110 {
111     test_buffer();
112     return 0;
113 }
114