00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef ORO_EVENTPROCESSOR_HPP
00040 #define ORO_EVENTPROCESSOR_HPP
00041
00042 #include "RunnableInterface.hpp"
00043 #include "Signal.hpp"
00044 #include <boost/bind.hpp>
00045 #include <boost/shared_ptr.hpp>
00046 #include <vector>
00047 #include "DataObjectInterfaces.hpp"
00048 #include "List.hpp"
00049 #include "boost/tuple/tuple.hpp"
00050 #include "NA.hpp"
00051 #include "os/Atomic.hpp"
00052
00053 namespace RTT
00054 {
00055 class EventProcessor;
00056
00057 namespace detail {
00058 using boost::make_tuple;
00059
00060 struct RTT_API EventCatcher {
00061 EventCatcher();
00062 virtual ~EventCatcher();
00063 virtual void complete() = 0;
00064
00069 void signalWork();
00070
00074 void signalWorkDone();
00075
00080 EventProcessor* mep;
00081
00085 int refCount;
00086
00087
00088 bool enabled;
00089
00090 typedef boost::intrusive_ptr< EventCatcher > shared_ptr;
00091
00092 };
00093
00094 RTT_API void intrusive_ptr_add_ref( EventCatcher* p );
00095 RTT_API void intrusive_ptr_release( EventCatcher* p );
00096
00097 using boost::tuples::get;
00098
00099 template<int, class SignalType, class ContainerType>
00100 struct EventCatcherImpl;
00101
00105 template<class SignalType, class ContainerType>
00106 struct EventCatcherImpl<0, SignalType, ContainerType>
00107 : public EventCatcher
00108 {
00109 typedef boost::intrusive_ptr< EventCatcherImpl<0, SignalType, ContainerType> > shared_ptr;
00110 typedef typename SignalType::SlotFunction Function;
00111 typedef typename Function::result_type Result;
00112
00113 const Function f;
00114 bool work;
00115
00116 EventCatcherImpl(const Function& f_, SignalType& sig )
00117 : f(f_), work(false)
00118 {
00119 }
00120
00121 Handle setup( SignalType& sig ) {
00122 return sig.setup( boost::bind( &EventCatcherImpl<0, SignalType, ContainerType>::handler,
00123 shared_ptr(this)) );
00124 }
00125
00126 Result handler( void ) {
00127 work = this->enabled;
00128 if ( work && mep )
00129 signalWork();
00130 return detail::NA<Result>::na();
00131 }
00132
00133 virtual void complete() {
00134 if (!work)
00135 return;
00136 f();
00137 work = false;
00138 signalWorkDone();
00139 }
00140 };
00141
00142 template<class SignalType, class ContainerType >
00143 struct EventCatcherImpl<1, SignalType, ContainerType>
00144 : public EventCatcher
00145 {
00146 typedef boost::intrusive_ptr< EventCatcherImpl<1, SignalType, ContainerType> > shared_ptr;
00147 typedef typename SignalType::SlotFunction Function;
00148 typedef typename Function::result_type Result;
00149
00150 typename ContainerType::template Data<typename Function::arg1_type> _a1;
00151 Function f;
00152
00153 EventCatcherImpl( const Function& f_, SignalType& sig )
00154 : f(f_)
00155 {
00156 }
00157 Handle setup( SignalType& sig ) {
00158 return sig.setup( boost::bind( &EventCatcherImpl<1, SignalType, ContainerType>::handler,
00159 shared_ptr(this), _1) );
00160 }
00161
00162 Result handler( typename Function::arg1_type a1 ) {
00163 if ( !this->enabled )
00164 return detail::NA<Result>::na();
00165
00166 _a1 = a1;
00167 if ( mep )
00168 signalWork();
00169 return detail::NA<Result>::na();
00170 }
00171
00172 virtual void complete() {
00173 if ( !_a1 )
00174 return;
00175 f( _a1.val() );
00176 _a1.clear();
00177 signalWorkDone();
00178 }
00179 };
00180
00181 struct OnlyFirstCont
00182 {
00183 template< class T>
00184 struct Data
00185 {
00186 Data() : work(false) {}
00187 bool work;
00188 T val_;
00189 typedef T type;
00190 operator bool() const {
00191 return work;
00192 }
00193 T val() const {
00194 return val_;
00195 }
00196 void operator=(const T& t) {
00197 if (work)
00198 return;
00199 val_ = t;
00200 work = true;
00201 }
00202 void clear() {
00203 work = false;
00204 }
00205 };
00206 };
00207
00208 struct OnlyLastCont
00209 {
00210 template< class T>
00211 struct Data
00212 {
00213 Data() : work(false), val_("EventData") {}
00214 bool work;
00215 DataObjectLockFree<T> val_;
00216 typedef T type;
00217 operator bool() const {
00218 return work;
00219 }
00220 void operator=(const T& t) {
00221 val_.Set(t);
00222 work = true;
00223 }
00224 T val() const {
00225 return val_.Get();
00226 }
00227 void clear() {
00228 work = false;
00229 }
00230 };
00231 };
00232
00233 template<class SignalType, class ContainerType>
00234 struct EventCatcherImpl<2, SignalType, ContainerType>
00235 : public EventCatcher
00236 {
00237 typedef boost::intrusive_ptr< EventCatcherImpl<2, SignalType, ContainerType> > shared_ptr;
00238 typedef typename SignalType::SlotFunction Function;
00239 typedef typename Function::result_type Result;
00240
00241 typedef boost::tuple<typename Function::arg1_type,
00242 typename Function::arg2_type> Args;
00243 typename ContainerType::template Data< Args > args;
00244 Function f;
00245
00246 EventCatcherImpl( const Function& f_, SignalType& sig )
00247 : f(f_)
00248 {}
00249 Handle setup( SignalType& sig ) {
00250 return sig.setup( boost::bind( &EventCatcherImpl<2, SignalType, ContainerType>::handler,
00251 shared_ptr(this), _1, _2) );
00252 }
00253
00254 Result handler( typename Function::arg1_type a1,
00255 typename Function::arg2_type a2 ) {
00256 if ( !this->enabled )
00257 return detail::NA<Result>::na();
00258 args = make_tuple( a1, a2 );
00259 if ( mep )
00260 signalWork();
00261 return detail::NA<Result>::na();
00262 }
00263
00264 virtual void complete() {
00265 if ( !args )
00266 return;
00267 f( get<0>(args.val()), get<1>(args.val()) );
00268 args.clear();
00269 signalWorkDone();
00270 }
00271 };
00272
00273 template<class SignalType, class ContainerType>
00274 struct EventCatcherImpl<3, SignalType, ContainerType>
00275 : public EventCatcher
00276 {
00277 typedef boost::intrusive_ptr< EventCatcherImpl<3, SignalType, ContainerType> > shared_ptr;
00278 typedef typename SignalType::SlotFunction Function;
00279 typedef typename Function::result_type Result;
00280
00281 typedef boost::tuple<typename Function::arg1_type,
00282 typename Function::arg2_type,
00283 typename Function::arg3_type> Args;
00284 typename ContainerType::template Data< Args > args;
00285 Function f;
00286
00287 EventCatcherImpl( const Function& f_, SignalType& sig )
00288 : f(f_)
00289 {}
00290
00291 Handle setup( SignalType& sig ) {
00292 return sig.setup( boost::bind( &EventCatcherImpl<3, SignalType, ContainerType>::handler,
00293 shared_ptr(this), _1, _2, _3) );
00294 }
00295
00296 Result handler( typename Function::arg1_type a1,
00297 typename Function::arg2_type a2,
00298 typename Function::arg3_type a3 ) {
00299 if ( !this->enabled )
00300 return detail::NA<Result>::na();
00301 args = make_tuple( a1, a2, a3 );
00302 if ( mep )
00303 signalWork();
00304 return detail::NA<Result>::na();
00305 }
00306
00307 virtual void complete() {
00308 if ( !args )
00309 return;
00310 f( get<0>(args.val()), get<1>(args.val()), get<2>(args.val()) );
00311 args.clear();
00312 signalWorkDone();
00313 }
00314 };
00315
00316 template<class SignalType, class ContainerType>
00317 struct EventCatcherImpl<4, SignalType, ContainerType>
00318 : public EventCatcher
00319 {
00320 typedef boost::intrusive_ptr< EventCatcherImpl<4, SignalType, ContainerType> > shared_ptr;
00321 typedef typename SignalType::SlotFunction Function;
00322 typedef typename Function::result_type Result;
00323
00324 typename Function::arg1_type _a1;
00325 typename Function::arg2_type _a2;
00326 typename Function::arg3_type _a3;
00327 typename Function::arg4_type _a4;
00328 typedef boost::tuple<typename Function::arg1_type,
00329 typename Function::arg2_type,
00330 typename Function::arg3_type,
00331 typename Function::arg4_type> Args;
00332 typename ContainerType::template Data< Args > args;
00333 Function f;
00334
00335 EventCatcherImpl( const Function& f_, SignalType& sig )
00336 : f(f_)
00337 {
00338 }
00339 Handle setup( SignalType& sig ) {
00340 return sig.setup( boost::bind( &EventCatcherImpl<4, SignalType, ContainerType>::handler,
00341 shared_ptr(this), _1, _2, _3, _4) );
00342 }
00343
00344 Result handler( typename Function::arg1_type a1,
00345 typename Function::arg2_type a2,
00346 typename Function::arg3_type a3,
00347 typename Function::arg4_type a4 ) {
00348 if ( !this->enabled )
00349 return detail::NA<Result>::na();
00350 args = make_tuple( a1, a2, a3, a4 );
00351 if ( mep )
00352 signalWork();
00353 return detail::NA<Result>::na();
00354 }
00355
00356 virtual void complete() {
00357 if ( !args )
00358 return;
00359 f( get<0>(args.val()), get<1>(args.val()), get<2>(args.val()), get<3>(args.val()) );
00360 args.clear();
00361 signalWorkDone();
00362 }
00363 };
00364
00365 template<class SignalType, class ContainerType>
00366 struct EventCatcherImpl<5, SignalType, ContainerType>
00367 : public EventCatcher
00368 {
00369 typedef boost::intrusive_ptr< EventCatcherImpl<5, SignalType, ContainerType> > shared_ptr;
00370 typedef typename SignalType::SlotFunction Function;
00371 typedef typename Function::result_type Result;
00372
00373 typename Function::arg1_type _a1;
00374 typename Function::arg2_type _a2;
00375 typename Function::arg3_type _a3;
00376 typename Function::arg4_type _a4;
00377 typename Function::arg5_type _a5;
00378 typedef boost::tuple<typename Function::arg1_type,
00379 typename Function::arg2_type,
00380 typename Function::arg3_type,
00381 typename Function::arg4_type,
00382 typename Function::arg5_type> Args;
00383 typename ContainerType::template Data< Args > args;
00384 Function f;
00385
00386 EventCatcherImpl( const Function& f_, SignalType& sig )
00387 : f(f_)
00388 {
00389 }
00390
00391 Handle setup( SignalType& sig ) {
00392 return sig.setup( boost::bind( &EventCatcherImpl<5, SignalType, ContainerType>::handler,
00393 shared_ptr(this), _1, _2, _3, _4, _5) );
00394 }
00395
00396 Result handler( typename Function::arg1_type a1,
00397 typename Function::arg2_type a2,
00398 typename Function::arg3_type a3,
00399 typename Function::arg4_type a4,
00400 typename Function::arg5_type a5) {
00401 if ( !this->enabled )
00402 return detail::NA<Result>::na();
00403 args = make_tuple( a1, a2, a3, a4, a5 );
00404 if ( mep )
00405 signalWork();
00406 return detail::NA<Result>::na();
00407 }
00408
00409 virtual void complete() {
00410 if ( !args )
00411 return;
00412 f( get<0>(args.val()), get<1>(args.val()), get<2>(args.val()), get<3>(args.val()), get<4>(args.val()) );
00413 args.clear();
00414 signalWorkDone();
00415 }
00416 };
00417
00418 template<class SignalType, class ContainerType>
00419 struct EventCatcherImpl<6, SignalType, ContainerType>
00420 : public EventCatcher
00421 {
00422 typedef boost::intrusive_ptr< EventCatcherImpl<6, SignalType, ContainerType> > shared_ptr;
00423 typedef typename SignalType::SlotFunction Function;
00424 typedef typename Function::result_type Result;
00425
00426 typedef boost::tuple<typename Function::arg1_type,
00427 typename Function::arg2_type,
00428 typename Function::arg3_type,
00429 typename Function::arg4_type,
00430 typename Function::arg5_type,
00431 typename Function::arg6_type> Args;
00432 typename ContainerType::template Data< Args > args;
00433 Function f;
00434
00435 EventCatcherImpl( const Function& f_, SignalType& sig )
00436 : f(f_)
00437 {
00438 }
00439
00440 Handle setup( SignalType& sig )
00441 {
00442 return sig.setup( boost::bind( &EventCatcherImpl<6, SignalType, ContainerType>::handler,
00443 shared_ptr(this), _1, _2, _3, _4, _5, _6) );
00444 }
00445
00446 Result handler( typename Function::arg1_type a1,
00447 typename Function::arg2_type a2,
00448 typename Function::arg3_type a3,
00449 typename Function::arg4_type a4,
00450 typename Function::arg5_type a5,
00451 typename Function::arg6_type a6) {
00452 if ( !this->enabled )
00453 return detail::NA<Result>::na();
00454 args = make_tuple( a1, a2, a3, a4, a5, a6 );
00455 if ( mep )
00456 signalWork();
00457 return detail::NA<Result>::na();
00458 }
00459
00460 virtual void complete() {
00461 if ( !args )
00462 return;
00463 f( get<0>(args.val()), get<1>(args.val()), get<2>(args.val()), get<3>(args.val()), get<4>(args.val()), get<5>(args.val()) );
00464 args.clear();
00465 signalWorkDone();
00466 }
00467 };
00468 }
00469
00490 class RTT_API EventProcessor
00491 : public RunnableInterface
00492 {
00493 protected:
00494 friend class EventCatcher;
00499 typedef List<detail::EventCatcher*> ECList;
00500 ECList catchers;
00501
00502 friend struct detail::EventCatcher;
00503 void destroyed( detail::EventCatcher* ec );
00504
00505 OS::AtomicInt has_work;
00506 public:
00507
00515 enum AsynStorageType {
00516 OnlyFirst,
00517 OnlyLast
00518 };
00519
00523 EventProcessor();
00524
00525 ~EventProcessor();
00526
00527 bool initialize();
00528
00529 void step();
00530
00531 void finalize();
00532
00536 bool breakLoop();
00537
00538 bool hasWork();
00539
00550 template<class SignalType>
00551 Handle connect(const typename SignalType::SlotFunction& f, SignalType& sig, AsynStorageType t )
00552 {
00553 Handle h = this->setup( f, sig, t);
00554 h.connect();
00555 return h;
00556 }
00557
00568 template<class SignalType>
00569 Handle setup(const typename SignalType::SlotFunction& f, SignalType& sig, AsynStorageType t )
00570 {
00571 detail::EventCatcher::shared_ptr eci;
00572 Handle h;
00573 switch ( t ) {
00574 case OnlyFirst:
00575 {
00576
00577 typename detail::EventCatcherImpl<SignalType::SlotFunction::arity, SignalType, detail::OnlyFirstCont>::shared_ptr ecf
00578 (new detail::EventCatcherImpl<SignalType::SlotFunction::arity, SignalType, detail::OnlyFirstCont>(f, sig));
00579 h = ecf->setup( sig );
00580 eci = ecf;
00581 }
00582 break;
00583 case OnlyLast:
00584 {
00585
00586 typename detail::EventCatcherImpl<SignalType::SlotFunction::arity, SignalType, detail::OnlyLastCont>::shared_ptr ecl
00587 (new detail::EventCatcherImpl<SignalType::SlotFunction::arity, SignalType, detail::OnlyLastCont>(f, sig));
00588 h = ecl->setup( sig );
00589 eci = ecl;
00590 }
00591 break;
00592 }
00593 catchers.grow();
00594 catchers.append( eci.get() );
00595 eci->enabled = this->getActivity() && this->getActivity()->isActive();
00596 eci->mep = this;
00597 return h;
00598 }
00599
00600 };
00601
00606 class RTT_API BlockingEventProcessor
00607 : public EventProcessor
00608 {
00609 public:
00614 BlockingEventProcessor();
00615
00616 ~BlockingEventProcessor();
00617
00618 };
00619
00620 }
00621
00622 #endif