]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | |
2 | // Copyright (c) 2008 Peter Dimov | |
3 | // | |
4 | // Distributed under the Boost Software License, Version 1.0. | |
5 | // See accompanying file LICENSE_1_0.txt or copy at | |
6 | // http://www.boost.org/LICENSE_1_0.txt | |
7 | ||
8 | //#define USE_MUTEX | |
9 | //#define USE_RWLOCK | |
10 | ||
11 | #include <boost/config.hpp> | |
12 | ||
13 | #include <boost/shared_ptr.hpp> | |
14 | #include <boost/bind.hpp> | |
15 | ||
16 | #if defined( USE_RWLOCK ) | |
17 | #include <boost/thread/shared_mutex.hpp> | |
18 | #include <boost/thread/locks.hpp> | |
19 | #endif | |
20 | ||
21 | #include <boost/detail/lightweight_mutex.hpp> | |
22 | #include <boost/detail/lightweight_test.hpp> | |
23 | #include <boost/detail/lightweight_thread.hpp> | |
24 | ||
25 | #include <cstdio> | |
26 | #include <ctime> | |
27 | ||
28 | // | |
29 | ||
30 | int const n = 1024 * 1024; | |
31 | ||
32 | struct X | |
33 | { | |
34 | int v_; // version | |
35 | ||
36 | unsigned a_; | |
37 | unsigned b_; | |
38 | ||
39 | X(): v_( 0 ), a_( 1 ), b_( 1 ) | |
40 | { | |
41 | } | |
42 | ||
43 | int get() const | |
44 | { | |
45 | return a_ * 7 + b_ * 11; | |
46 | } | |
47 | ||
48 | void set() | |
49 | { | |
50 | int tmp = get(); | |
51 | ||
52 | b_ = a_; | |
53 | a_ = tmp; | |
54 | ||
55 | ++v_; | |
56 | } | |
57 | }; | |
58 | ||
59 | static boost::shared_ptr<X> ps( new X ); | |
60 | ||
61 | static boost::detail::lightweight_mutex lm; | |
62 | ||
63 | #if defined( USE_RWLOCK ) | |
64 | static boost::shared_mutex rw; | |
65 | #endif | |
66 | ||
67 | static int tr = 0; | |
68 | ||
69 | void reader( int r ) | |
70 | { | |
71 | int k = 0; | |
72 | unsigned s = 0; | |
73 | ||
74 | for( int i = 0; i < n; ++k ) | |
75 | { | |
76 | #if defined( USE_MUTEX ) | |
77 | ||
78 | boost::detail::lightweight_mutex::scoped_lock lock( lm ); | |
79 | ||
80 | s += ps->get(); | |
81 | ||
82 | BOOST_TEST( ps->v_ >= i ); | |
83 | i = ps->v_; | |
84 | ||
85 | #elif defined( USE_RWLOCK ) | |
86 | ||
87 | boost::shared_lock<boost::shared_mutex> lock( rw ); | |
88 | ||
89 | s += ps->get(); | |
90 | ||
91 | BOOST_TEST( ps->v_ >= i ); | |
92 | i = ps->v_; | |
93 | ||
94 | #else | |
95 | ||
96 | boost::shared_ptr<X> p2 = boost::atomic_load( &ps ); | |
97 | ||
98 | s += p2->get(); | |
99 | ||
100 | BOOST_TEST( p2->v_ >= i ); | |
101 | i = p2->v_; | |
102 | ||
103 | #endif | |
104 | } | |
105 | ||
106 | printf( "Reader %d: %9d iterations (%6.3fx), %u\n", r, k, (double)k / n, s ); | |
107 | ||
108 | boost::detail::lightweight_mutex::scoped_lock lock( lm ); | |
109 | tr += k; | |
110 | } | |
111 | ||
112 | void writer() | |
113 | { | |
114 | for( int i = 0; i < n; ++i ) | |
115 | { | |
116 | #if defined( USE_MUTEX ) | |
117 | ||
118 | boost::detail::lightweight_mutex::scoped_lock lock( lm ); | |
119 | ||
120 | BOOST_TEST( ps->v_ == i ); | |
121 | ps->set(); | |
122 | ||
123 | #elif defined( USE_RWLOCK ) | |
124 | ||
125 | boost::unique_lock<boost::shared_mutex> lock( rw ); | |
126 | ||
127 | BOOST_TEST( ps->v_ == i ); | |
128 | ps->set(); | |
129 | ||
130 | #else | |
131 | ||
132 | boost::shared_ptr<X> p2( new X( *ps ) ); | |
133 | ||
134 | BOOST_TEST( p2->v_ == i ); | |
135 | p2->set(); | |
136 | ||
137 | boost::atomic_store( &ps, p2 ); | |
138 | ||
139 | #endif | |
140 | } | |
141 | } | |
142 | ||
143 | #if defined( BOOST_HAS_PTHREADS ) | |
144 | char const * thmodel = "POSIX"; | |
145 | #else | |
146 | char const * thmodel = "Windows"; | |
147 | #endif | |
148 | ||
149 | int const mr = 8; // reader threads | |
150 | int const mw = 1; // writer thread | |
151 | ||
152 | #if defined( USE_MUTEX ) | |
153 | char const * prim = "mutex"; | |
154 | #elif defined( USE_RWLOCK ) | |
155 | char const * prim = "rwlock"; | |
156 | #else | |
157 | char const * prim = "atomics"; | |
158 | #endif | |
159 | ||
160 | int main() | |
161 | { | |
162 | using namespace std; // printf, clock_t, clock | |
163 | ||
164 | printf( "Using %s threads: %dR + %dW threads, %d iterations, %s\n\n", thmodel, mr, mw, n, prim ); | |
165 | ||
166 | clock_t t = clock(); | |
167 | ||
92f5a8d4 | 168 | boost::detail::lw_thread_t a[ mr+mw ]; |
7c673cae FG |
169 | |
170 | for( int i = 0; i < mr; ++i ) | |
171 | { | |
172 | boost::detail::lw_thread_create( a[ i ], boost::bind( reader, i ) ); | |
173 | } | |
174 | ||
175 | for( int i = mr; i < mr+mw; ++i ) | |
176 | { | |
177 | boost::detail::lw_thread_create( a[ i ], writer ); | |
178 | } | |
179 | ||
180 | for( int j = 0; j < mr+mw; ++j ) | |
181 | { | |
92f5a8d4 | 182 | boost::detail::lw_thread_join( a[ j ] ); |
7c673cae FG |
183 | } |
184 | ||
185 | t = clock() - t; | |
186 | ||
187 | double ts = static_cast<double>( t ) / CLOCKS_PER_SEC; | |
188 | printf( "%.3f seconds, %.3f reads per microsecond.\n", ts, tr / ts / 1e+6 ); | |
189 | ||
190 | return boost::report_errors(); | |
191 | } |