Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/statechart/fifo_worker.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 #ifndef BOOST_STATECHART_FIFO_WORKER_HPP_INCLUDED | |
2 #define BOOST_STATECHART_FIFO_WORKER_HPP_INCLUDED | |
3 ////////////////////////////////////////////////////////////////////////////// | |
4 // Copyright 2002-2008 Andreas Huber Doenni | |
5 // Distributed under the Boost Software License, Version 1.0. (See accompany- | |
6 // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
7 ////////////////////////////////////////////////////////////////////////////// | |
8 | |
9 | |
10 | |
11 #include <boost/assert.hpp> | |
12 #include <boost/noncopyable.hpp> | |
13 #include <boost/function/function0.hpp> | |
14 #include <boost/bind.hpp> | |
15 // BOOST_HAS_THREADS, BOOST_MSVC | |
16 #include <boost/config.hpp> | |
17 | |
18 #include <boost/detail/allocator_utilities.hpp> | |
19 | |
20 #ifdef BOOST_HAS_THREADS | |
21 # ifdef BOOST_MSVC | |
22 # pragma warning( push ) | |
23 // "conditional expression is constant" in basic_timed_mutex.hpp | |
24 # pragma warning( disable: 4127 ) | |
25 // "conversion from 'int' to 'unsigned short'" in microsec_time_clock.hpp | |
26 # pragma warning( disable: 4244 ) | |
27 // "... needs to have dll-interface to be used by clients of class ..." | |
28 # pragma warning( disable: 4251 ) | |
29 // "... assignment operator could not be generated" | |
30 # pragma warning( disable: 4512 ) | |
31 // "Function call with parameters that may be unsafe" in | |
32 // condition_variable.hpp | |
33 # pragma warning( disable: 4996 ) | |
34 # endif | |
35 | |
36 # include <boost/thread/mutex.hpp> | |
37 # include <boost/thread/condition.hpp> | |
38 | |
39 # ifdef BOOST_MSVC | |
40 # pragma warning( pop ) | |
41 # endif | |
42 #endif | |
43 | |
44 #include <list> | |
45 #include <memory> // std::allocator | |
46 | |
47 | |
48 namespace boost | |
49 { | |
50 namespace statechart | |
51 { | |
52 | |
53 | |
54 | |
55 template< class Allocator = std::allocator< void > > | |
56 class fifo_worker : noncopyable | |
57 { | |
58 public: | |
59 ////////////////////////////////////////////////////////////////////////// | |
60 #ifdef BOOST_HAS_THREADS | |
61 fifo_worker( bool waitOnEmptyQueue = false ) : | |
62 waitOnEmptyQueue_( waitOnEmptyQueue ), | |
63 #else | |
64 fifo_worker() : | |
65 #endif | |
66 terminated_( false ) | |
67 { | |
68 } | |
69 | |
70 typedef function0< void > work_item; | |
71 | |
72 // We take a non-const reference so that we can move (i.e. swap) the item | |
73 // into the queue, what avoids copying the (possibly heap-allocated) | |
74 // implementation object inside work_item. | |
75 void queue_work_item( work_item & item ) | |
76 { | |
77 if ( item.empty() ) | |
78 { | |
79 return; | |
80 } | |
81 | |
82 #ifdef BOOST_HAS_THREADS | |
83 mutex::scoped_lock lock( mutex_ ); | |
84 #endif | |
85 | |
86 workQueue_.push_back( work_item() ); | |
87 workQueue_.back().swap( item ); | |
88 | |
89 #ifdef BOOST_HAS_THREADS | |
90 queueNotEmpty_.notify_one(); | |
91 #endif | |
92 } | |
93 | |
94 // Convenience overload so that temporary objects can be passed directly | |
95 // instead of having to create a work_item object first. Under most | |
96 // circumstances, this will lead to one unnecessary copy of the | |
97 // function implementation object. | |
98 void queue_work_item( const work_item & item ) | |
99 { | |
100 work_item copy = item; | |
101 queue_work_item( copy ); | |
102 } | |
103 | |
104 void terminate() | |
105 { | |
106 work_item item = boost::bind( &fifo_worker::terminate_impl, this ); | |
107 queue_work_item( item ); | |
108 } | |
109 | |
110 // Is not mutex-protected! Must only be called from the thread that also | |
111 // calls operator(). | |
112 bool terminated() const | |
113 { | |
114 return terminated_; | |
115 } | |
116 | |
117 unsigned long operator()( unsigned long maxItemCount = 0 ) | |
118 { | |
119 unsigned long itemCount = 0; | |
120 | |
121 while ( !terminated() && | |
122 ( ( maxItemCount == 0 ) || ( itemCount < maxItemCount ) ) ) | |
123 { | |
124 work_item item = dequeue_item(); | |
125 | |
126 if ( item.empty() ) | |
127 { | |
128 // item can only be empty when the queue is empty, which only | |
129 // happens in ST builds or when users pass false to the fifo_worker | |
130 // constructor | |
131 return itemCount; | |
132 } | |
133 | |
134 item(); | |
135 ++itemCount; | |
136 } | |
137 | |
138 return itemCount; | |
139 } | |
140 | |
141 private: | |
142 ////////////////////////////////////////////////////////////////////////// | |
143 work_item dequeue_item() | |
144 { | |
145 #ifdef BOOST_HAS_THREADS | |
146 mutex::scoped_lock lock( mutex_ ); | |
147 | |
148 if ( !waitOnEmptyQueue_ && workQueue_.empty() ) | |
149 { | |
150 return work_item(); | |
151 } | |
152 | |
153 while ( workQueue_.empty() ) | |
154 { | |
155 queueNotEmpty_.wait( lock ); | |
156 } | |
157 #else | |
158 // If the queue happens to run empty in a single-threaded system, | |
159 // waiting for new work items (which means to loop indefinitely!) is | |
160 // pointless as there is no way that new work items could find their way | |
161 // into the queue. The only sensible thing is to exit the loop and | |
162 // return to the caller in this case. | |
163 // Users can then queue new work items before calling operator() again. | |
164 if ( workQueue_.empty() ) | |
165 { | |
166 return work_item(); | |
167 } | |
168 #endif | |
169 | |
170 // Optimization: Swap rather than assign to avoid the copy of the | |
171 // implementation object inside function | |
172 work_item result; | |
173 result.swap( workQueue_.front() ); | |
174 workQueue_.pop_front(); | |
175 return result; | |
176 } | |
177 | |
178 void terminate_impl() | |
179 { | |
180 terminated_ = true; | |
181 } | |
182 | |
183 | |
184 typedef std::list< | |
185 work_item, | |
186 typename boost::detail::allocator::rebind_to< | |
187 Allocator, work_item >::type | |
188 > work_queue_type; | |
189 | |
190 work_queue_type workQueue_; | |
191 | |
192 #ifdef BOOST_HAS_THREADS | |
193 mutex mutex_; | |
194 condition queueNotEmpty_; | |
195 const bool waitOnEmptyQueue_; | |
196 #endif | |
197 | |
198 bool terminated_; | |
199 }; | |
200 | |
201 | |
202 | |
203 } // namespace statechart | |
204 } // namespace boost | |
205 | |
206 | |
207 | |
208 #endif |