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::auto_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 typedef std::auto_ptr< processor_base_type > processor_holder_type;
68 typedef shared_ptr< processor_holder_type > processor_holder_ptr_type;
71 //////////////////////////////////////////////////////////////////////////
72 typedef weak_ptr< processor_holder_type > processor_handle;
74 class processor_context
77 Scheduler & scheduler, const processor_handle & handle
79 scheduler_( scheduler ),
84 #if BOOST_WORKAROUND( BOOST_INTEL, BOOST_TESTED_AT( 800 ) )
86 // for some reason Intel 8.0 seems to think that the following functions
87 // are inaccessible from event_processor<>::event_processor
90 Scheduler & my_scheduler() const { return scheduler_; }
91 const processor_handle & my_handle() const { return handle_; }
93 #if BOOST_WORKAROUND( BOOST_INTEL, BOOST_TESTED_AT( 800 ) )
97 // avoids C4512 (assignment operator could not be generated)
98 processor_context & operator=( const processor_context & );
100 Scheduler & scheduler_;
101 const processor_handle handle_;
103 friend class processor_container;
104 friend class event_processor< Scheduler >;
107 template< class Processor >
108 WorkItem create_processor( processor_handle & handle, Scheduler & scheduler )
110 processor_holder_ptr_type pProcessor = make_processor_holder();
112 typedef void ( processor_container::*impl_fun_ptr )(
113 const processor_holder_ptr_type &, const processor_context & );
115 &processor_container::template create_processor_impl0< Processor >;
117 boost::bind( pImpl, this, pProcessor,
118 processor_context( scheduler, handle ) ),
122 template< class Processor, typename Arg1 >
123 WorkItem create_processor(
124 processor_handle & handle, Scheduler & scheduler, Arg1 arg1 )
126 processor_holder_ptr_type pProcessor = make_processor_holder();
128 typedef typename detail::unwrap< Arg1 >::type arg1_type;
129 typedef void ( processor_container::*impl_fun_ptr )(
130 const processor_holder_ptr_type &, const processor_context &,
133 &processor_container::template create_processor_impl1<
134 Processor, arg1_type >;
136 boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
141 template< class Processor, typename Arg1, typename Arg2 >
142 WorkItem create_processor(
143 processor_handle & handle, Scheduler & scheduler, Arg1 arg1, Arg2 arg2 )
145 processor_holder_ptr_type pProcessor = make_processor_holder();
147 typedef typename detail::unwrap< Arg1 >::type arg1_type;
148 typedef typename detail::unwrap< Arg2 >::type arg2_type;
149 typedef void ( processor_container::*impl_fun_ptr )(
150 const processor_holder_ptr_type &, const processor_context &,
151 arg1_type, arg2_type );
153 &processor_container::template create_processor_impl2<
154 Processor, arg1_type, arg2_type >;
156 boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
161 template< class Processor, typename Arg1, typename Arg2, typename Arg3 >
162 WorkItem create_processor(
163 processor_handle & handle, Scheduler & scheduler,
164 Arg1 arg1, Arg2 arg2, Arg3 arg3 )
166 processor_holder_ptr_type pProcessor = make_processor_holder();
168 typedef typename detail::unwrap< Arg1 >::type arg1_type;
169 typedef typename detail::unwrap< Arg2 >::type arg2_type;
170 typedef typename detail::unwrap< Arg3 >::type arg3_type;
171 typedef void ( processor_container::*impl_fun_ptr )(
172 const processor_holder_ptr_type &, const processor_context &,
173 arg1_type, arg2_type, arg3_type );
175 &processor_container::template create_processor_impl3<
176 Processor, arg1_type, arg2_type, arg3_type >;
178 boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
184 class Processor, typename Arg1, typename Arg2,
185 typename Arg3, typename Arg4 >
186 WorkItem create_processor(
187 processor_handle & handle, Scheduler & scheduler,
188 Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4 )
190 processor_holder_ptr_type pProcessor = make_processor_holder();
192 typedef typename detail::unwrap< Arg1 >::type arg1_type;
193 typedef typename detail::unwrap< Arg2 >::type arg2_type;
194 typedef typename detail::unwrap< Arg3 >::type arg3_type;
195 typedef typename detail::unwrap< Arg4 >::type arg4_type;
196 typedef void ( processor_container::*impl_fun_ptr )(
197 const processor_holder_ptr_type &, const processor_context &,
198 arg1_type, arg2_type, arg3_type, arg4_type );
200 &processor_container::template create_processor_impl4<
201 Processor, arg1_type, arg2_type, arg3_type, arg4_type >;
203 boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
204 arg1, arg2, arg3, arg4 ),
209 class Processor, typename Arg1, typename Arg2,
210 typename Arg3, typename Arg4, typename Arg5 >
211 WorkItem create_processor(
212 processor_handle & handle, Scheduler & scheduler,
213 Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5 )
215 processor_holder_ptr_type pProcessor = make_processor_holder();
217 typedef typename detail::unwrap< Arg1 >::type arg1_type;
218 typedef typename detail::unwrap< Arg2 >::type arg2_type;
219 typedef typename detail::unwrap< Arg3 >::type arg3_type;
220 typedef typename detail::unwrap< Arg4 >::type arg4_type;
221 typedef typename detail::unwrap< Arg5 >::type arg5_type;
222 typedef void ( processor_container::*impl_fun_ptr )(
223 const processor_holder_ptr_type &, const processor_context &,
224 arg1_type, arg2_type, arg3_type, arg4_type, arg5_type );
226 &processor_container::template create_processor_impl5<
227 Processor, arg1_type, arg2_type, arg3_type, arg4_type, arg5_type >;
229 boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
230 arg1, arg2, arg3, arg4, arg5 ),
235 class Processor, typename Arg1, typename Arg2,
236 typename Arg3, typename Arg4, typename Arg5, typename Arg6 >
237 WorkItem create_processor(
238 processor_handle & handle, Scheduler & scheduler,
239 Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6 )
241 processor_holder_ptr_type pProcessor = make_processor_holder();
243 typedef typename detail::unwrap< Arg1 >::type arg1_type;
244 typedef typename detail::unwrap< Arg2 >::type arg2_type;
245 typedef typename detail::unwrap< Arg3 >::type arg3_type;
246 typedef typename detail::unwrap< Arg4 >::type arg4_type;
247 typedef typename detail::unwrap< Arg5 >::type arg5_type;
248 typedef typename detail::unwrap< Arg6 >::type arg6_type;
249 typedef void ( processor_container::*impl_fun_ptr )(
250 const processor_holder_ptr_type &, const processor_context &,
251 arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type );
253 &processor_container::template create_processor_impl6<
255 arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type >;
257 boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
258 arg1, arg2, arg3, arg4, arg5, arg6 ),
262 WorkItem destroy_processor( const processor_handle & processor )
265 boost::bind( &processor_container::destroy_processor_impl, this, processor ),
269 WorkItem initiate_processor( const processor_handle & processor )
272 boost::bind( &processor_container::initiate_processor_impl, this,
277 WorkItem terminate_processor( const processor_handle & processor )
280 boost::bind( &processor_container::terminate_processor_impl, this,
285 typedef intrusive_ptr< const event_base > event_ptr_type;
287 WorkItem queue_event(
288 const processor_handle & processor, const event_ptr_type & pEvent )
290 BOOST_ASSERT( pEvent.get() != 0 );
293 boost::bind( &processor_container::queue_event_impl, this, processor,
299 //////////////////////////////////////////////////////////////////////////
300 processor_holder_ptr_type make_processor_holder()
302 return processor_holder_ptr_type( new processor_holder_type() );
305 template< class Processor >
306 void create_processor_impl0(
307 const processor_holder_ptr_type & pProcessor,
308 const processor_context & context )
310 processorSet_.insert( pProcessor );
311 processor_holder_type holder( new Processor( context ) );
312 *pProcessor = holder;
315 template< class Processor, typename Arg1 >
316 void create_processor_impl1(
317 const processor_holder_ptr_type & pProcessor,
318 const processor_context & context, Arg1 arg1 )
320 processorSet_.insert( pProcessor );
321 processor_holder_type holder( new Processor( context, arg1 ) );
322 *pProcessor = holder;
325 template< class Processor, typename Arg1, typename Arg2 >
326 void create_processor_impl2(
327 const processor_holder_ptr_type & pProcessor,
328 const processor_context & context, Arg1 arg1, Arg2 arg2 )
330 processorSet_.insert( pProcessor );
331 processor_holder_type holder( new Processor( context, arg1, arg2 ) );
332 *pProcessor = holder;
335 template< class Processor, typename Arg1, typename Arg2, typename Arg3 >
336 void create_processor_impl3(
337 const processor_holder_ptr_type & pProcessor,
338 const processor_context & context, Arg1 arg1, Arg2 arg2, Arg3 arg3 )
340 processorSet_.insert( pProcessor );
341 processor_holder_type holder(
342 new Processor( context, arg1, arg2, arg3 ) );
343 *pProcessor = holder;
347 class Processor, typename Arg1, typename Arg2,
348 typename Arg3, typename Arg4 >
349 void create_processor_impl4(
350 const processor_holder_ptr_type & pProcessor,
351 const processor_context & context,
352 Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4 )
354 processorSet_.insert( pProcessor );
355 processor_holder_type holder(
356 new Processor( context, arg1, arg2, arg3, arg4 ) );
357 *pProcessor = holder;
361 class Processor, typename Arg1, typename Arg2,
362 typename Arg3, typename Arg4, typename Arg5 >
363 void create_processor_impl5(
364 const processor_holder_ptr_type & pProcessor,
365 const processor_context & context,
366 Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5 )
368 processorSet_.insert( pProcessor );
369 processor_holder_type holder(
370 new Processor( context, arg1, arg2, arg3, arg4, arg5 ) );
371 *pProcessor = holder;
375 class Processor, typename Arg1, typename Arg2,
376 typename Arg3, typename Arg4, typename Arg5, typename Arg6 >
377 void create_processor_impl6(
378 const processor_holder_ptr_type & pProcessor,
379 const processor_context & context,
380 Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6 )
382 processorSet_.insert( pProcessor );
383 processor_holder_type holder(
384 new Processor( context, arg1, arg2, arg3, arg4, arg5, arg6 ) );
385 *pProcessor = holder;
388 void destroy_processor_impl( const processor_handle & processor )
390 const processor_holder_ptr_type pProcessor = processor.lock();
392 if ( pProcessor != 0 )
394 processorSet_.erase( pProcessor );
398 void initiate_processor_impl( const processor_handle & processor )
400 const processor_holder_ptr_type pProcessor = processor.lock();
402 if ( pProcessor != 0 )
404 ( *pProcessor )->initiate();
408 void terminate_processor_impl( const processor_handle & processor )
410 const processor_holder_ptr_type pProcessor = processor.lock();
412 if ( pProcessor != 0 )
414 ( *pProcessor )->terminate();
418 void queue_event_impl(
419 const processor_handle & processor, const event_ptr_type & pEvent )
421 const processor_holder_ptr_type pProcessor = processor.lock();
423 if ( pProcessor != 0 )
425 ( *pProcessor )->process_event( *pEvent );
430 processor_holder_ptr_type,
431 std::less< processor_holder_ptr_type >,
432 typename boost::detail::allocator::rebind_to<
433 Allocator, processor_holder_ptr_type >::type
434 > event_processor_set_type;
436 event_processor_set_type processorSet_;
440 } // namespace statechart