File indexing completed on 2025-01-30 10:00:51
0001 #ifndef BOOST_STATECHART_FIFO_WORKER_HPP_INCLUDED
0002 #define BOOST_STATECHART_FIFO_WORKER_HPP_INCLUDED
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <boost/assert.hpp>
0012 #include <boost/noncopyable.hpp>
0013 #include <boost/function/function0.hpp>
0014 #include <boost/bind.hpp>
0015
0016 #include <boost/config.hpp>
0017
0018 #include <boost/detail/allocator_utilities.hpp>
0019
0020 #ifdef BOOST_HAS_THREADS
0021 # ifdef BOOST_MSVC
0022 # pragma warning( push )
0023
0024 # pragma warning( disable: 4127 )
0025
0026 # pragma warning( disable: 4244 )
0027
0028 # pragma warning( disable: 4251 )
0029
0030 # pragma warning( disable: 4512 )
0031
0032
0033 # pragma warning( disable: 4996 )
0034 # endif
0035
0036 # include <boost/thread/mutex.hpp>
0037 # include <boost/thread/condition.hpp>
0038
0039 # ifdef BOOST_MSVC
0040 # pragma warning( pop )
0041 # endif
0042 #endif
0043
0044 #include <list>
0045 #include <memory> // std::allocator
0046
0047
0048 namespace boost
0049 {
0050 namespace statechart
0051 {
0052
0053
0054
0055 template< class Allocator = std::allocator< none > >
0056 class fifo_worker : noncopyable
0057 {
0058 public:
0059
0060 #ifdef BOOST_HAS_THREADS
0061 fifo_worker( bool waitOnEmptyQueue = false ) :
0062 waitOnEmptyQueue_( waitOnEmptyQueue ),
0063 #else
0064 fifo_worker() :
0065 #endif
0066 terminated_( false )
0067 {
0068 }
0069
0070 typedef function0< void > work_item;
0071
0072
0073
0074
0075 void queue_work_item( work_item & item )
0076 {
0077 if ( item.empty() )
0078 {
0079 return;
0080 }
0081
0082 #ifdef BOOST_HAS_THREADS
0083 mutex::scoped_lock lock( mutex_ );
0084 #endif
0085
0086 workQueue_.push_back( work_item() );
0087 workQueue_.back().swap( item );
0088
0089 #ifdef BOOST_HAS_THREADS
0090 queueNotEmpty_.notify_one();
0091 #endif
0092 }
0093
0094
0095
0096
0097
0098 void queue_work_item( const work_item & item )
0099 {
0100 work_item copy = item;
0101 queue_work_item( copy );
0102 }
0103
0104 void terminate()
0105 {
0106 work_item item = boost::bind( &fifo_worker::terminate_impl, this );
0107 queue_work_item( item );
0108 }
0109
0110
0111
0112 bool terminated() const
0113 {
0114 return terminated_;
0115 }
0116
0117 unsigned long operator()( unsigned long maxItemCount = 0 )
0118 {
0119 unsigned long itemCount = 0;
0120
0121 while ( !terminated() &&
0122 ( ( maxItemCount == 0 ) || ( itemCount < maxItemCount ) ) )
0123 {
0124 work_item item = dequeue_item();
0125
0126 if ( item.empty() )
0127 {
0128
0129
0130
0131 return itemCount;
0132 }
0133
0134 item();
0135 ++itemCount;
0136 }
0137
0138 return itemCount;
0139 }
0140
0141 private:
0142
0143 work_item dequeue_item()
0144 {
0145 #ifdef BOOST_HAS_THREADS
0146 mutex::scoped_lock lock( mutex_ );
0147
0148 if ( !waitOnEmptyQueue_ && workQueue_.empty() )
0149 {
0150 return work_item();
0151 }
0152
0153 while ( workQueue_.empty() )
0154 {
0155 queueNotEmpty_.wait( lock );
0156 }
0157 #else
0158
0159
0160
0161
0162
0163
0164 if ( workQueue_.empty() )
0165 {
0166 return work_item();
0167 }
0168 #endif
0169
0170
0171
0172 work_item result;
0173 result.swap( workQueue_.front() );
0174 workQueue_.pop_front();
0175 return result;
0176 }
0177
0178 void terminate_impl()
0179 {
0180 terminated_ = true;
0181 }
0182
0183
0184 typedef std::list<
0185 work_item,
0186 typename boost::detail::allocator::rebind_to<
0187 Allocator, work_item >::type
0188 > work_queue_type;
0189
0190 work_queue_type workQueue_;
0191
0192 #ifdef BOOST_HAS_THREADS
0193 mutex mutex_;
0194 condition queueNotEmpty_;
0195 const bool waitOnEmptyQueue_;
0196 #endif
0197
0198 bool terminated_;
0199 };
0200
0201
0202
0203 }
0204 }
0205
0206
0207
0208 #endif