fifo_scheduler.hpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. #ifndef BOOST_STATECHART_FIFO_SCHEDULER_HPP_INCLUDED
  2. #define BOOST_STATECHART_FIFO_SCHEDULER_HPP_INCLUDED
  3. //////////////////////////////////////////////////////////////////////////////
  4. // Copyright 2002-2006 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. #include <boost/statechart/event_base.hpp>
  9. #include <boost/statechart/fifo_worker.hpp>
  10. #include <boost/statechart/processor_container.hpp>
  11. #include <boost/intrusive_ptr.hpp>
  12. #include <boost/noncopyable.hpp>
  13. #include <boost/config.hpp> // BOOST_HAS_THREADS
  14. namespace boost
  15. {
  16. namespace statechart
  17. {
  18. //////////////////////////////////////////////////////////////////////////////
  19. template<
  20. class FifoWorker = fifo_worker<>,
  21. class Allocator = std::allocator< none > >
  22. class fifo_scheduler : noncopyable
  23. {
  24. typedef processor_container<
  25. fifo_scheduler, typename FifoWorker::work_item, Allocator > container;
  26. public:
  27. //////////////////////////////////////////////////////////////////////////
  28. #ifdef BOOST_HAS_THREADS
  29. fifo_scheduler( bool waitOnEmptyQueue = false ) :
  30. worker_( waitOnEmptyQueue )
  31. {
  32. }
  33. #endif
  34. typedef typename container::processor_handle processor_handle;
  35. typedef typename container::processor_context processor_context;
  36. template< class Processor >
  37. processor_handle create_processor()
  38. {
  39. processor_handle result;
  40. work_item item =
  41. container_.template create_processor< Processor >( result, *this );
  42. worker_.queue_work_item( item );
  43. return result;
  44. }
  45. template< class Processor, typename Arg1 >
  46. processor_handle create_processor( Arg1 arg1 )
  47. {
  48. processor_handle result;
  49. work_item item = container_.template create_processor< Processor >(
  50. result, *this, arg1 );
  51. worker_.queue_work_item( item );
  52. return result;
  53. }
  54. template< class Processor, typename Arg1, typename Arg2 >
  55. processor_handle create_processor( Arg1 arg1, Arg2 arg2 )
  56. {
  57. processor_handle result;
  58. work_item item = container_.template create_processor< Processor >(
  59. result, *this, arg1, arg2 );
  60. worker_.queue_work_item( item );
  61. return result;
  62. }
  63. template< class Processor, typename Arg1, typename Arg2, typename Arg3 >
  64. processor_handle create_processor( Arg1 arg1, Arg2 arg2, Arg3 arg3 )
  65. {
  66. processor_handle result;
  67. work_item item = container_.template create_processor< Processor >(
  68. result, *this, arg1, arg2, arg3 );
  69. worker_.queue_work_item( item );
  70. return result;
  71. }
  72. template<
  73. class Processor, typename Arg1, typename Arg2,
  74. typename Arg3, typename Arg4 >
  75. processor_handle create_processor(
  76. Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4 )
  77. {
  78. processor_handle result;
  79. work_item item = container_.template create_processor< Processor >(
  80. result, *this, arg1, arg2, arg3, arg4 );
  81. worker_.queue_work_item( item );
  82. return result;
  83. }
  84. template<
  85. class Processor, typename Arg1, typename Arg2,
  86. typename Arg3, typename Arg4, typename Arg5 >
  87. processor_handle create_processor(
  88. Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5 )
  89. {
  90. processor_handle result;
  91. work_item item = container_.template create_processor< Processor >(
  92. result, *this, arg1, arg2, arg3, arg4, arg5 );
  93. worker_.queue_work_item( item );
  94. return result;
  95. }
  96. template<
  97. class Processor, typename Arg1, typename Arg2,
  98. typename Arg3, typename Arg4, typename Arg5, typename Arg6 >
  99. processor_handle create_processor(
  100. Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6 )
  101. {
  102. processor_handle result;
  103. work_item item = container_.template create_processor< Processor >(
  104. result, *this, arg1, arg2, arg3, arg4, arg5, arg6 );
  105. worker_.queue_work_item( item );
  106. return result;
  107. }
  108. void destroy_processor( const processor_handle & processor )
  109. {
  110. work_item item = container_.destroy_processor( processor );
  111. worker_.queue_work_item( item );
  112. }
  113. void initiate_processor( const processor_handle & processor )
  114. {
  115. work_item item = container_.initiate_processor( processor );
  116. worker_.queue_work_item( item );
  117. }
  118. void terminate_processor( const processor_handle & processor )
  119. {
  120. work_item item = container_.terminate_processor( processor );
  121. worker_.queue_work_item( item );
  122. }
  123. typedef intrusive_ptr< const event_base > event_ptr_type;
  124. void queue_event(
  125. const processor_handle & processor, const event_ptr_type & pEvent )
  126. {
  127. work_item item = container_.queue_event( processor, pEvent );
  128. worker_.queue_work_item( item );
  129. }
  130. typedef typename FifoWorker::work_item work_item;
  131. // We take a non-const reference so that we can move (i.e. swap) the item
  132. // into the queue, what avoids copying the (possibly heap-allocated)
  133. // implementation object inside work_item.
  134. void queue_work_item( work_item & item )
  135. {
  136. worker_.queue_work_item( item );
  137. }
  138. // Convenience overload so that temporary objects can be passed directly
  139. // instead of having to create a work_item object first. Under most
  140. // circumstances, this will lead to one unnecessary copy of the
  141. // function implementation object.
  142. void queue_work_item( const work_item & item )
  143. {
  144. worker_.queue_work_item( item );
  145. }
  146. void terminate()
  147. {
  148. worker_.terminate();
  149. }
  150. // Is not mutex-protected! Must only be called from the thread that also
  151. // calls operator().
  152. bool terminated() const
  153. {
  154. return worker_.terminated();
  155. }
  156. unsigned long operator()( unsigned long maxEventCount = 0 )
  157. {
  158. return worker_( maxEventCount );
  159. }
  160. private:
  161. //////////////////////////////////////////////////////////////////////////
  162. container container_;
  163. FifoWorker worker_;
  164. };
  165. } // namespace statechart
  166. } // namespace boost
  167. #endif