2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 this list of conditions and the following disclaimer in the documentation
17 and/or other materials provided with the distribution.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #ifndef CDSLIB_ALGO_FLAT_COMBINING_WAIT_STRATEGY_H
32 #define CDSLIB_ALGO_FLAT_COMBINING_WAIT_STRATEGY_H
34 #include <cds/algo/flat_combining/defs.h>
35 #include <cds/algo/backoff_strategy.h>
37 #include <condition_variable>
38 #include <boost/thread/tss.hpp> // thread_specific_ptr
41 namespace cds { namespace opt {
43 /// Wait strategy option for \p flat_combining::kernel
44 template <typename Strategy>
45 struct wait_strategy {
47 template <typename Base> struct pack: public Base
49 typedef Strategy wait_strategy;
54 }} // namespace cds::opt
56 namespace cds { namespace algo { namespace flat_combining {
58 /// Wait strategies for \p flat_combining technique
59 namespace wait_strategy {
61 /// Empty wait strategy
65 template <typename PublicationRecord>
66 struct make_publication_record {
67 typedef PublicationRecord type;
70 template <typename PublicationRecord>
71 void prepare( PublicationRecord& /*rec*/ )
74 template <typename FCKernel, typename PublicationRecord>
75 bool wait( FCKernel& /*fc*/, PublicationRecord& /*rec*/ )
80 template <typename FCKernel, typename PublicationRecord>
81 void notify( FCKernel& /*fc*/, PublicationRecord& /*rec*/ )
84 template <typename FCKernel>
85 void wakeup( FCKernel& /*fc*/ )
90 /// Back-off wait strategy
91 template <typename BackOff = cds::backoff::delay_of<2>>
95 typedef BackOff back_off;
97 template <typename PublicationRecord>
98 struct make_publication_record {
99 struct type: public PublicationRecord
105 template <typename PublicationRecord>
106 void prepare( PublicationRecord& rec )
111 template <typename FCKernel, typename PublicationRecord>
112 bool wait( FCKernel& /*fc*/, PublicationRecord& rec )
118 template <typename FCKernel, typename PublicationRecord>
119 void notify( FCKernel& /*fc*/, PublicationRecord& /*rec*/ )
122 template <typename FCKernel>
123 void wakeup( FCKernel& )
128 /// Wait strategy based on the single mutex and the condition variable
130 The strategy shares the mutex and conditional variable for all thread.
132 Template parameter \p Milliseconds specifies waiting duration;
133 the minimal value is 1.
135 template <int Milliseconds = 2>
136 class single_mutex_single_condvar
140 std::condition_variable m_condvar;
142 typedef std::unique_lock< std::mutex > unique_lock;
146 c_nWaitMilliseconds = Milliseconds < 1 ? 1 : Milliseconds
149 template <typename PublicationRecord>
150 struct make_publication_record {
151 typedef PublicationRecord type;
154 template <typename PublicationRecord>
155 void prepare( PublicationRecord& /*rec*/ )
158 template <typename FCKernel, typename PublicationRecord>
159 bool wait( FCKernel& fc, PublicationRecord& rec )
161 if ( fc.get_operation( rec ) >= req_Operation ) {
162 unique_lock lock( m_mutex );
163 if ( fc.get_operation( rec ) >= req_Operation )
164 return m_condvar.wait_for( lock, std::chrono::milliseconds( c_nWaitMilliseconds )) == std::cv_status::no_timeout;
169 template <typename FCKernel, typename PublicationRecord>
170 void notify( FCKernel& fc, PublicationRecord& rec )
172 m_condvar.notify_all();
175 template <typename FCKernel>
176 void wakeup( FCKernel& /*fc*/ )
178 m_condvar.notify_all();
183 /// Wait strategy based on the single mutex and thread-local condition variables
185 The strategy shares the mutex, but each thread has its own conditional variable
187 Template parameter \p Milliseconds specifies waiting duration;
188 the minimal value is 1.
190 template <int Milliseconds = 2>
191 class single_mutex_multi_condvar
196 typedef std::unique_lock< std::mutex > unique_lock;
200 c_nWaitMilliseconds = Milliseconds < 1 ? 1 : Milliseconds
203 template <typename PublicationRecord>
204 struct make_publication_record {
205 struct type: public PublicationRecord
207 std::condition_variable m_condvar;
211 template <typename PublicationRecord>
212 void prepare( PublicationRecord& /*rec*/ )
215 template <typename FCKernel, typename PublicationRecord>
216 bool wait( FCKernel& fc, PublicationRecord& rec )
218 if ( fc.get_operation( rec ) >= req_Operation ) {
219 unique_lock lock( m_mutex );
220 if ( fc.get_operation( rec ) >= req_Operation )
221 return rec.m_condvar.wait_for( lock, std::chrono::milliseconds( c_nWaitMilliseconds )) == std::cv_status::no_timeout;
226 template <typename FCKernel, typename PublicationRecord>
227 void notify( FCKernel& fc, PublicationRecord& rec )
229 rec.m_condvar.notify_one();
232 template <typename FCKernel>
233 void wakeup( FCKernel& fc )
240 /// Wait strategy where each thread has a mutex and a condition variable
242 Template parameter \p Milliseconds specifies waiting duration;
243 the minimal value is 1.
245 template <int Milliseconds = 10>
246 class multi_mutex_multi_condvar
249 typedef std::unique_lock< std::mutex > unique_lock;
253 c_nWaitMilliseconds = Milliseconds < 1 ? 1 : Milliseconds
256 template <typename PublicationRecord>
257 struct make_publication_record {
258 struct type: public PublicationRecord
261 std::condition_variable m_condvar;
265 template <typename PublicationRecord>
266 void prepare( PublicationRecord& /*rec*/ )
269 template <typename FCKernel, typename PublicationRecord>
270 bool wait( FCKernel& fc, PublicationRecord& rec )
272 if ( fc.get_operation( rec ) >= req_Operation ) {
273 unique_lock lock( rec.m_mutex );
274 if ( fc.get_operation( rec ) >= req_Operation )
275 return rec.m_condvar.wait_for( lock, std::chrono::milliseconds( c_nWaitMilliseconds )) == std::cv_status::no_timeout;
280 template <typename FCKernel, typename PublicationRecord>
281 void notify( FCKernel& /*fc*/, PublicationRecord& rec )
283 rec.m_condvar.notify_one();
286 template <typename FCKernel>
287 void wakeup( FCKernel& fc )
294 } // namespace wait_strategy
295 }}} // namespace cds::algo::flat_combining
297 #endif //CDSLIB_ALGO_FLAT_COMBINING_WAIT_STRATEGY_H