]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ////////////////////////////////////////////////////////////////////////////// | |
8 | ||
9 | ||
10 | ||
11 | #include <boost/statechart/event_base.hpp> | |
12 | #include <boost/statechart/event_processor.hpp> | |
13 | ||
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 | |
22 | ||
23 | #include <boost/detail/workaround.hpp> | |
24 | #include <boost/detail/allocator_utilities.hpp> | |
25 | ||
26 | #include <set> | |
11fdf7f2 | 27 | #include <memory> // std::allocator, std::unique_ptr |
7c673cae FG |
28 | |
29 | ||
30 | ||
31 | namespace boost | |
32 | { | |
33 | namespace statechart | |
34 | { | |
35 | namespace detail | |
36 | { | |
37 | template<bool IsReferenceWrapper> | |
38 | struct unwrap_impl | |
39 | { | |
40 | template< typename T > | |
41 | struct apply { typedef T type; }; | |
42 | }; | |
43 | ||
44 | template<> | |
45 | struct unwrap_impl<true> | |
46 | { | |
47 | template< typename T > | |
48 | struct apply { typedef typename T::type & type; }; | |
49 | }; | |
50 | ||
51 | template<typename T> | |
52 | struct unwrap | |
53 | { | |
54 | typedef typename unwrap_impl< | |
55 | is_reference_wrapper< T >::value >::template apply< T >::type type; | |
56 | }; | |
57 | } | |
58 | ||
59 | ||
60 | template< | |
61 | class Scheduler, | |
62 | class WorkItem, | |
92f5a8d4 | 63 | class Allocator = std::allocator< none > > |
7c673cae FG |
64 | class processor_container : noncopyable |
65 | { | |
66 | typedef event_processor< Scheduler > processor_base_type; | |
11fdf7f2 TL |
67 | #ifdef BOOST_NO_AUTO_PTR |
68 | typedef std::unique_ptr< processor_base_type > processor_holder_type; | |
69 | #else | |
7c673cae | 70 | typedef std::auto_ptr< processor_base_type > processor_holder_type; |
11fdf7f2 | 71 | #endif |
7c673cae FG |
72 | typedef shared_ptr< processor_holder_type > processor_holder_ptr_type; |
73 | ||
74 | public: | |
75 | ////////////////////////////////////////////////////////////////////////// | |
76 | typedef weak_ptr< processor_holder_type > processor_handle; | |
77 | ||
78 | class processor_context | |
79 | { | |
80 | processor_context( | |
81 | Scheduler & scheduler, const processor_handle & handle | |
82 | ) : | |
83 | scheduler_( scheduler ), | |
84 | handle_( handle ) | |
85 | { | |
86 | } | |
87 | ||
88 | #if BOOST_WORKAROUND( BOOST_INTEL, BOOST_TESTED_AT( 800 ) ) | |
89 | public: | |
90 | // for some reason Intel 8.0 seems to think that the following functions | |
91 | // are inaccessible from event_processor<>::event_processor | |
92 | #endif | |
93 | ||
94 | Scheduler & my_scheduler() const { return scheduler_; } | |
95 | const processor_handle & my_handle() const { return handle_; } | |
96 | ||
97 | #if BOOST_WORKAROUND( BOOST_INTEL, BOOST_TESTED_AT( 800 ) ) | |
98 | private: | |
99 | #endif | |
100 | ||
101 | // avoids C4512 (assignment operator could not be generated) | |
102 | processor_context & operator=( const processor_context & ); | |
103 | ||
104 | Scheduler & scheduler_; | |
105 | const processor_handle handle_; | |
106 | ||
107 | friend class processor_container; | |
108 | friend class event_processor< Scheduler >; | |
109 | }; | |
110 | ||
111 | template< class Processor > | |
112 | WorkItem create_processor( processor_handle & handle, Scheduler & scheduler ) | |
113 | { | |
114 | processor_holder_ptr_type pProcessor = make_processor_holder(); | |
115 | handle = pProcessor; | |
116 | typedef void ( processor_container::*impl_fun_ptr )( | |
117 | const processor_holder_ptr_type &, const processor_context & ); | |
118 | impl_fun_ptr pImpl = | |
119 | &processor_container::template create_processor_impl0< Processor >; | |
120 | return WorkItem( | |
121 | boost::bind( pImpl, this, pProcessor, | |
122 | processor_context( scheduler, handle ) ), | |
123 | Allocator() ); | |
124 | } | |
125 | ||
126 | template< class Processor, typename Arg1 > | |
127 | WorkItem create_processor( | |
128 | processor_handle & handle, Scheduler & scheduler, Arg1 arg1 ) | |
129 | { | |
130 | processor_holder_ptr_type pProcessor = make_processor_holder(); | |
131 | handle = pProcessor; | |
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 &, | |
135 | arg1_type ); | |
136 | impl_fun_ptr pImpl = | |
137 | &processor_container::template create_processor_impl1< | |
138 | Processor, arg1_type >; | |
139 | return WorkItem( | |
140 | boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ), | |
141 | arg1 ), | |
142 | Allocator() ); | |
143 | } | |
144 | ||
145 | template< class Processor, typename Arg1, typename Arg2 > | |
146 | WorkItem create_processor( | |
147 | processor_handle & handle, Scheduler & scheduler, Arg1 arg1, Arg2 arg2 ) | |
148 | { | |
149 | processor_holder_ptr_type pProcessor = make_processor_holder(); | |
150 | handle = pProcessor; | |
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 ); | |
156 | impl_fun_ptr pImpl = | |
157 | &processor_container::template create_processor_impl2< | |
158 | Processor, arg1_type, arg2_type >; | |
159 | return WorkItem( | |
160 | boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ), | |
161 | arg1, arg2 ), | |
162 | Allocator() ); | |
163 | } | |
164 | ||
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 ) | |
169 | { | |
170 | processor_holder_ptr_type pProcessor = make_processor_holder(); | |
171 | handle = pProcessor; | |
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 ); | |
178 | impl_fun_ptr pImpl = | |
179 | &processor_container::template create_processor_impl3< | |
180 | Processor, arg1_type, arg2_type, arg3_type >; | |
181 | return WorkItem( | |
182 | boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ), | |
183 | arg1, arg2, arg3 ), | |
184 | Allocator() ); | |
185 | } | |
186 | ||
187 | template< | |
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 ) | |
193 | { | |
194 | processor_holder_ptr_type pProcessor = make_processor_holder(); | |
195 | handle = pProcessor; | |
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 ); | |
203 | impl_fun_ptr pImpl = | |
204 | &processor_container::template create_processor_impl4< | |
205 | Processor, arg1_type, arg2_type, arg3_type, arg4_type >; | |
206 | return WorkItem( | |
207 | boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ), | |
208 | arg1, arg2, arg3, arg4 ), | |
209 | Allocator() ); | |
210 | } | |
211 | ||
212 | template< | |
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 ) | |
218 | { | |
219 | processor_holder_ptr_type pProcessor = make_processor_holder(); | |
220 | handle = pProcessor; | |
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 ); | |
229 | impl_fun_ptr pImpl = | |
230 | &processor_container::template create_processor_impl5< | |
231 | Processor, arg1_type, arg2_type, arg3_type, arg4_type, arg5_type >; | |
232 | return WorkItem( | |
233 | boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ), | |
234 | arg1, arg2, arg3, arg4, arg5 ), | |
235 | Allocator() ); | |
236 | } | |
237 | ||
238 | template< | |
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 ) | |
244 | { | |
245 | processor_holder_ptr_type pProcessor = make_processor_holder(); | |
246 | handle = pProcessor; | |
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 ); | |
256 | impl_fun_ptr pImpl = | |
257 | &processor_container::template create_processor_impl6< | |
258 | Processor, | |
259 | arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type >; | |
260 | return WorkItem( | |
261 | boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ), | |
262 | arg1, arg2, arg3, arg4, arg5, arg6 ), | |
263 | Allocator() ); | |
264 | } | |
265 | ||
266 | WorkItem destroy_processor( const processor_handle & processor ) | |
267 | { | |
268 | return WorkItem( | |
269 | boost::bind( &processor_container::destroy_processor_impl, this, processor ), | |
270 | Allocator() ); | |
271 | } | |
272 | ||
273 | WorkItem initiate_processor( const processor_handle & processor ) | |
274 | { | |
275 | return WorkItem( | |
276 | boost::bind( &processor_container::initiate_processor_impl, this, | |
277 | processor ), | |
278 | Allocator() ); | |
279 | } | |
280 | ||
281 | WorkItem terminate_processor( const processor_handle & processor ) | |
282 | { | |
283 | return WorkItem( | |
284 | boost::bind( &processor_container::terminate_processor_impl, this, | |
285 | processor ), | |
286 | Allocator() ); | |
287 | } | |
288 | ||
289 | typedef intrusive_ptr< const event_base > event_ptr_type; | |
290 | ||
291 | WorkItem queue_event( | |
292 | const processor_handle & processor, const event_ptr_type & pEvent ) | |
293 | { | |
294 | BOOST_ASSERT( pEvent.get() != 0 ); | |
295 | ||
296 | return WorkItem( | |
297 | boost::bind( &processor_container::queue_event_impl, this, processor, | |
298 | pEvent ), | |
299 | Allocator() ); | |
300 | } | |
301 | ||
302 | private: | |
303 | ////////////////////////////////////////////////////////////////////////// | |
304 | processor_holder_ptr_type make_processor_holder() | |
305 | { | |
306 | return processor_holder_ptr_type( new processor_holder_type() ); | |
307 | } | |
308 | ||
309 | template< class Processor > | |
310 | void create_processor_impl0( | |
311 | const processor_holder_ptr_type & pProcessor, | |
312 | const processor_context & context ) | |
313 | { | |
314 | processorSet_.insert( pProcessor ); | |
11fdf7f2 | 315 | *pProcessor = processor_holder_type( new Processor( context ) ); |
7c673cae FG |
316 | } |
317 | ||
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 ) | |
322 | { | |
323 | processorSet_.insert( pProcessor ); | |
11fdf7f2 | 324 | *pProcessor = processor_holder_type( new Processor( context, arg1 ) ); |
7c673cae FG |
325 | } |
326 | ||
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 ) | |
331 | { | |
332 | processorSet_.insert( pProcessor ); | |
11fdf7f2 | 333 | *pProcessor = processor_holder_type( new Processor( context, arg1, arg2 ) ); |
7c673cae FG |
334 | } |
335 | ||
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 ) | |
340 | { | |
341 | processorSet_.insert( pProcessor ); | |
11fdf7f2 | 342 | *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3 ) ); |
7c673cae FG |
343 | } |
344 | ||
345 | template< | |
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 ) | |
352 | { | |
353 | processorSet_.insert( pProcessor ); | |
11fdf7f2 | 354 | *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3, arg4 ) ); |
7c673cae FG |
355 | } |
356 | ||
357 | template< | |
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 ) | |
364 | { | |
365 | processorSet_.insert( pProcessor ); | |
11fdf7f2 | 366 | *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3, arg4, arg5 ) ); |
7c673cae FG |
367 | } |
368 | ||
369 | template< | |
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 ) | |
376 | { | |
377 | processorSet_.insert( pProcessor ); | |
11fdf7f2 | 378 | *pProcessor = processor_holder_type( new Processor( context, arg1, arg2, arg3, arg4, arg5, arg6 ) ); |
7c673cae FG |
379 | } |
380 | ||
381 | void destroy_processor_impl( const processor_handle & processor ) | |
382 | { | |
383 | const processor_holder_ptr_type pProcessor = processor.lock(); | |
384 | ||
385 | if ( pProcessor != 0 ) | |
386 | { | |
387 | processorSet_.erase( pProcessor ); | |
388 | } | |
389 | } | |
390 | ||
391 | void initiate_processor_impl( const processor_handle & processor ) | |
392 | { | |
393 | const processor_holder_ptr_type pProcessor = processor.lock(); | |
394 | ||
395 | if ( pProcessor != 0 ) | |
396 | { | |
397 | ( *pProcessor )->initiate(); | |
398 | } | |
399 | } | |
400 | ||
401 | void terminate_processor_impl( const processor_handle & processor ) | |
402 | { | |
403 | const processor_holder_ptr_type pProcessor = processor.lock(); | |
404 | ||
405 | if ( pProcessor != 0 ) | |
406 | { | |
407 | ( *pProcessor )->terminate(); | |
408 | } | |
409 | } | |
410 | ||
411 | void queue_event_impl( | |
412 | const processor_handle & processor, const event_ptr_type & pEvent ) | |
413 | { | |
414 | const processor_holder_ptr_type pProcessor = processor.lock(); | |
415 | ||
416 | if ( pProcessor != 0 ) | |
417 | { | |
418 | ( *pProcessor )->process_event( *pEvent ); | |
419 | } | |
420 | } | |
421 | ||
422 | typedef std::set< | |
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; | |
428 | ||
429 | event_processor_set_type processorSet_; | |
430 | }; | |
431 | ||
432 | ||
433 | } // namespace statechart | |
434 | } // namespace boost | |
435 | ||
436 | ||
437 | ||
438 | #endif |