1 #ifndef BOOST_STATECHART_PROCESSOR_CONTAINER_HPP_INCLUDED
2 #define BOOST_STATECHART_PROCESSOR_CONTAINER_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 //////////////////////////////////////////////////////////////////////////////
11 #include <boost/statechart/event_base.hpp>
12 #include <boost/statechart/event_processor.hpp>
14 #include <boost/assert.hpp>
15 #include <boost/ref.hpp>
16 #include <boost/noncopyable.hpp>
17 #include <boost/intrusive_ptr.hpp>
18 #include <boost/shared_ptr.hpp>
19 #include <boost/weak_ptr.hpp>
20 #include <boost/bind.hpp>
21 #include <boost/config.hpp> // BOOST_INTEL
23 #include <boost/detail/workaround.hpp>
24 #include <boost/detail/allocator_utilities.hpp>
27 #include <memory> // std::allocator, std::unique_ptr
37 template<bool IsReferenceWrapper>
40 template< typename T >
41 struct apply { typedef T type; };
45 struct unwrap_impl<true>
47 template< typename T >
48 struct apply { typedef typename T::type & type; };
54 typedef typename unwrap_impl<
55 is_reference_wrapper< T >::value >::template apply< T >::type type;
63 class Allocator = std::allocator< void > >
64 class processor_container : noncopyable
66 typedef event_processor< Scheduler > processor_base_type;
67 #ifdef BOOST_NO_AUTO_PTR
68 typedef std::unique_ptr< processor_base_type > processor_holder_type;
70 typedef std::auto_ptr< processor_base_type > processor_holder_type;
72 typedef shared_ptr< processor_holder_type > processor_holder_ptr_type;
75 //////////////////////////////////////////////////////////////////////////
76 typedef weak_ptr< processor_holder_type > processor_handle;
78 class processor_context
81 Scheduler & scheduler, const processor_handle & handle
83 scheduler_( scheduler ),
88 #if BOOST_WORKAROUND( BOOST_INTEL, BOOST_TESTED_AT( 800 ) )
90 // for some reason Intel 8.0 seems to think that the following functions
91 // are inaccessible from event_processor<>::event_processor
94 Scheduler & my_scheduler() const { return scheduler_; }
95 const processor_handle & my_handle() const { return handle_; }
97 #if BOOST_WORKAROUND( BOOST_INTEL, BOOST_TESTED_AT( 800 ) )
101 // avoids C4512 (assignment operator could not be generated)
102 processor_context & operator=( const processor_context & );
104 Scheduler & scheduler_;
105 const processor_handle handle_;
107 friend class processor_container;
108 friend class event_processor< Scheduler >;
111 template< class Processor >
112 WorkItem create_processor( processor_handle & handle, Scheduler & scheduler )
114 processor_holder_ptr_type pProcessor = make_processor_holder();
116 typedef void ( processor_container::*impl_fun_ptr )(
117 const processor_holder_ptr_type &, const processor_context & );
119 &processor_container::template create_processor_impl0< Processor >;
121 boost::bind( pImpl, this, pProcessor,
122 processor_context( scheduler, handle ) ),
126 template< class Processor, typename Arg1 >
127 WorkItem create_processor(
128 processor_handle & handle, Scheduler & scheduler, Arg1 arg1 )
130 processor_holder_ptr_type pProcessor = make_processor_holder();
132 typedef typename detail::unwrap< Arg1 >::type arg1_type;
133 typedef void ( processor_container::*impl_fun_ptr )(
134 const processor_holder_ptr_type &, const processor_context &,
137 &processor_container::template create_processor_impl1<
138 Processor, arg1_type >;
140 boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
145 template< class Processor, typename Arg1, typename Arg2 >
146 WorkItem create_processor(
147 processor_handle & handle, Scheduler & scheduler, Arg1 arg1, Arg2 arg2 )
149 processor_holder_ptr_type pProcessor = make_processor_holder();
151 typedef typename detail::unwrap< Arg1 >::type arg1_type;
152 typedef typename detail::unwrap< Arg2 >::type arg2_type;
153 typedef void ( processor_container::*impl_fun_ptr )(
154 const processor_holder_ptr_type &, const processor_context &,
155 arg1_type, arg2_type );
157 &processor_container::template create_processor_impl2<
158 Processor, arg1_type, arg2_type >;
160 boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
165 template< class Processor, typename Arg1, typename Arg2, typename Arg3 >
166 WorkItem create_processor(
167 processor_handle & handle, Scheduler & scheduler,
168 Arg1 arg1, Arg2 arg2, Arg3 arg3 )
170 processor_holder_ptr_type pProcessor = make_processor_holder();
172 typedef typename detail::unwrap< Arg1 >::type arg1_type;
173 typedef typename detail::unwrap< Arg2 >::type arg2_type;
174 typedef typename detail::unwrap< Arg3 >::type arg3_type;
175 typedef void ( processor_container::*impl_fun_ptr )(
176 const processor_holder_ptr_type &, const processor_context &,
177 arg1_type, arg2_type, arg3_type );
179 &processor_container::template create_processor_impl3<
180 Processor, arg1_type, arg2_type, arg3_type >;
182 boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
188 class Processor, typename Arg1, typename Arg2,
189 typename Arg3, typename Arg4 >
190 WorkItem create_processor(
191 processor_handle & handle, Scheduler & scheduler,
192 Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4 )
194 processor_holder_ptr_type pProcessor = make_processor_holder();
196 typedef typename detail::unwrap< Arg1 >::type arg1_type;
197 typedef typename detail::unwrap< Arg2 >::type arg2_type;
198 typedef typename detail::unwrap< Arg3 >::type arg3_type;
199 typedef typename detail::unwrap< Arg4 >::type arg4_type;
200 typedef void ( processor_container::*impl_fun_ptr )(
201 const processor_holder_ptr_type &, const processor_context &,
202 arg1_type, arg2_type, arg3_type, arg4_type );
204 &processor_container::template create_processor_impl4<
205 Processor, arg1_type, arg2_type, arg3_type, arg4_type >;
207 boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
208 arg1, arg2, arg3, arg4 ),
213 class Processor, typename Arg1, typename Arg2,
214 typename Arg3, typename Arg4, typename Arg5 >
215 WorkItem create_processor(
216 processor_handle & handle, Scheduler & scheduler,
217 Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5 )
219 processor_holder_ptr_type pProcessor = make_processor_holder();
221 typedef typename detail::unwrap< Arg1 >::type arg1_type;
222 typedef typename detail::unwrap< Arg2 >::type arg2_type;
223 typedef typename detail::unwrap< Arg3 >::type arg3_type;
224 typedef typename detail::unwrap< Arg4 >::type arg4_type;
225 typedef typename detail::unwrap< Arg5 >::type arg5_type;
226 typedef void ( processor_container::*impl_fun_ptr )(
227 const processor_holder_ptr_type &, const processor_context &,
228 arg1_type, arg2_type, arg3_type, arg4_type, arg5_type );
230 &processor_container::template create_processor_impl5<
231 Processor, arg1_type, arg2_type, arg3_type, arg4_type, arg5_type >;
233 boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
234 arg1, arg2, arg3, arg4, arg5 ),
239 class Processor, typename Arg1, typename Arg2,
240 typename Arg3, typename Arg4, typename Arg5, typename Arg6 >
241 WorkItem create_processor(
242 processor_handle & handle, Scheduler & scheduler,
243 Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6 )
245 processor_holder_ptr_type pProcessor = make_processor_holder();
247 typedef typename detail::unwrap< Arg1 >::type arg1_type;
248 typedef typename detail::unwrap< Arg2 >::type arg2_type;
249 typedef typename detail::unwrap< Arg3 >::type arg3_type;
250 typedef typename detail::unwrap< Arg4 >::type arg4_type;
251 typedef typename detail::unwrap< Arg5 >::type arg5_type;
252 typedef typename detail::unwrap< Arg6 >::type arg6_type;
253 typedef void ( processor_container::*impl_fun_ptr )(
254 const processor_holder_ptr_type &, const processor_context &,
255 arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type );
257 &processor_container::template create_processor_impl6<
259 arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type >;
261 boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
262 arg1, arg2, arg3, arg4, arg5, arg6 ),
266 WorkItem destroy_processor( const processor_handle & processor )
269 boost::bind( &processor_container::destroy_processor_impl, this, processor ),
273 WorkItem initiate_processor( const processor_handle & processor )
276 boost::bind( &processor_container::initiate_processor_impl, this,
281 WorkItem terminate_processor( const processor_handle & processor )
284 boost::bind( &processor_container::terminate_processor_impl, this,
289 typedef intrusive_ptr< const event_base > event_ptr_type;
291 WorkItem queue_event(
292 const processor_handle & processor, const event_ptr_type & pEvent )
294 BOOST_ASSERT( pEvent.get() != 0 );
297 boost::bind( &processor_container::queue_event_impl, this, processor,
303 //////////////////////////////////////////////////////////////////////////
304 processor_holder_ptr_type make_processor_holder()
306 return processor_holder_ptr_type( new processor_holder_type() );
309 template< class Processor >
310 void create_processor_impl0(
311 const processor_holder_ptr_type & pProcessor,
312 const processor_context & context )
314 processorSet_.insert( pProcessor );
315 *pProcessor = processor_holder_type( new Processor( context ) );
318 template< class Processor, typename Arg1 >
319 void create_processor_impl1(
320 const processor_holder_ptr_type & pProcessor,
321 const processor_context & context, Arg1 arg1 )
323 processorSet_.insert( pProcessor );
324 *pProcessor = processor_holder_type( new Processor( context, arg1 ) );
327 template< class Processor, typename Arg1, typename Arg2 >
328 void create_processor_impl2(
329 const processor_holder_ptr_type & pProcessor,
330 const processor_context & context, Arg1 arg1, Arg2 arg2 )
332 processorSet_.insert( pProcessor );
333 *pProcessor = processor_holder_type( new Processor( context, arg1, arg2 ) );
336 template< class Processor, typename Arg1, typename Arg2, typename Arg3 >
337 void create_processor_impl3(
338 const processor_holder_ptr_type & pProcessor,
339 const processor_context & context, Arg1 arg1, Arg2 arg2, Arg3 arg3 )
341 processorSet_.insert( pProcessor );
342 *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3 ) );
346 class Processor, typename Arg1, typename Arg2,
347 typename Arg3, typename Arg4 >
348 void create_processor_impl4(
349 const processor_holder_ptr_type & pProcessor,
350 const processor_context & context,
351 Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4 )
353 processorSet_.insert( pProcessor );
354 *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3, arg4 ) );
358 class Processor, typename Arg1, typename Arg2,
359 typename Arg3, typename Arg4, typename Arg5 >
360 void create_processor_impl5(
361 const processor_holder_ptr_type & pProcessor,
362 const processor_context & context,
363 Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5 )
365 processorSet_.insert( pProcessor );
366 *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3, arg4, arg5 ) );
370 class Processor, typename Arg1, typename Arg2,
371 typename Arg3, typename Arg4, typename Arg5, typename Arg6 >
372 void create_processor_impl6(
373 const processor_holder_ptr_type & pProcessor,
374 const processor_context & context,
375 Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6 )
377 processorSet_.insert( pProcessor );
378 *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3, arg4, arg5, arg6 ) );
381 void destroy_processor_impl( const processor_handle & processor )
383 const processor_holder_ptr_type pProcessor = processor.lock();
385 if ( pProcessor != 0 )
387 processorSet_.erase( pProcessor );
391 void initiate_processor_impl( const processor_handle & processor )
393 const processor_holder_ptr_type pProcessor = processor.lock();
395 if ( pProcessor != 0 )
397 ( *pProcessor )->initiate();
401 void terminate_processor_impl( const processor_handle & processor )
403 const processor_holder_ptr_type pProcessor = processor.lock();
405 if ( pProcessor != 0 )
407 ( *pProcessor )->terminate();
411 void queue_event_impl(
412 const processor_handle & processor, const event_ptr_type & pEvent )
414 const processor_holder_ptr_type pProcessor = processor.lock();
416 if ( pProcessor != 0 )
418 ( *pProcessor )->process_event( *pEvent );
423 processor_holder_ptr_type,
424 std::less< processor_holder_ptr_type >,
425 typename boost::detail::allocator::rebind_to<
426 Allocator, processor_holder_ptr_type >::type
427 > event_processor_set_type;
429 event_processor_set_type processorSet_;
433 } // namespace statechart