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() : tag(0), tagged(0), val_("EventData") {}
00214 volatile int tag;
00215 mutable int tagged;
00216 #ifndef OROBLD_OS_NO_ASM
00217 DataObjectLockFree<T> val_;
00218 #else
00219 DataObjectLocked<T> val_;
00220 #endif
00221 typedef T type;
00222 operator bool() const {
00223
00224 return (tagged != tag);
00225 }
00226 void operator=(const T& t) {
00227 val_.Set(t);
00228 tag++;
00229 }
00230 T val() const {
00231 tagged = tag;
00232 return val_.Get();
00233 }
00234 void clear() {
00235 #ifndef OROBLD_OS_NO_ASM
00236 if(OS::CAS(&tag, tagged, tagged+1))
00237 #endif
00238 {
00239
00240 tagged++;
00241 }
00242 }
00243 };
00244 };
00245
00246 template<class SignalType, class ContainerType>
00247 struct EventCatcherImpl<2, SignalType, ContainerType>
00248 : public EventCatcher
00249 {
00250 typedef boost::intrusive_ptr< EventCatcherImpl<2, SignalType, ContainerType> > shared_ptr;
00251 typedef typename SignalType::SlotFunction Function;
00252 typedef typename Function::result_type Result;
00253
00254 typedef boost::tuple<typename Function::arg1_type,
00255 typename Function::arg2_type> Args;
00256 typename ContainerType::template Data< Args > args;
00257 Function f;
00258
00259 EventCatcherImpl( const Function& f_, SignalType& sig )
00260 : f(f_)
00261 {}
00262 Handle setup( SignalType& sig ) {
00263 return sig.setup( boost::bind( &EventCatcherImpl<2, SignalType, ContainerType>::handler,
00264 shared_ptr(this), _1, _2) );
00265 }
00266
00267 Result handler( typename Function::arg1_type a1,
00268 typename Function::arg2_type a2 ) {
00269 if ( !this->enabled )
00270 return detail::NA<Result>::na();
00271 args = boost::make_tuple( a1, a2 );
00272 if ( mep )
00273 signalWork();
00274 return detail::NA<Result>::na();
00275 }
00276
00277 virtual void complete() {
00278 if ( !args )
00279 return;
00280 Args tmp_args = args.val();
00281 f( get<0>(tmp_args), get<1>(tmp_args) );
00282 args.clear();
00283 signalWorkDone();
00284 }
00285 };
00286
00287 template<class SignalType, class ContainerType>
00288 struct EventCatcherImpl<3, SignalType, ContainerType>
00289 : public EventCatcher
00290 {
00291 typedef boost::intrusive_ptr< EventCatcherImpl<3, SignalType, ContainerType> > shared_ptr;
00292 typedef typename SignalType::SlotFunction Function;
00293 typedef typename Function::result_type Result;
00294
00295 typedef boost::tuple<typename Function::arg1_type,
00296 typename Function::arg2_type,
00297 typename Function::arg3_type> Args;
00298 typename ContainerType::template Data< Args > args;
00299 Function f;
00300
00301 EventCatcherImpl( const Function& f_, SignalType& sig )
00302 : f(f_)
00303 {}
00304
00305 Handle setup( SignalType& sig ) {
00306 return sig.setup( boost::bind( &EventCatcherImpl<3, SignalType, ContainerType>::handler,
00307 shared_ptr(this), _1, _2, _3) );
00308 }
00309
00310 Result handler( typename Function::arg1_type a1,
00311 typename Function::arg2_type a2,
00312 typename Function::arg3_type a3 ) {
00313 if ( !this->enabled )
00314 return detail::NA<Result>::na();
00315 args = boost::make_tuple( a1, a2, a3 );
00316 if ( mep )
00317 signalWork();
00318 return detail::NA<Result>::na();
00319 }
00320
00321 virtual void complete() {
00322 if ( !args )
00323 return;
00324 Args tmp_args = args.val();
00325 f( get<0>(tmp_args), get<1>(tmp_args), get<2>(tmp_args) );
00326 args.clear();
00327 signalWorkDone();
00328 }
00329 };
00330
00331 template<class SignalType, class ContainerType>
00332 struct EventCatcherImpl<4, SignalType, ContainerType>
00333 : public EventCatcher
00334 {
00335 typedef boost::intrusive_ptr< EventCatcherImpl<4, SignalType, ContainerType> > shared_ptr;
00336 typedef typename SignalType::SlotFunction Function;
00337 typedef typename Function::result_type Result;
00338
00339 typename Function::arg1_type _a1;
00340 typename Function::arg2_type _a2;
00341 typename Function::arg3_type _a3;
00342 typename Function::arg4_type _a4;
00343 typedef boost::tuple<typename Function::arg1_type,
00344 typename Function::arg2_type,
00345 typename Function::arg3_type,
00346 typename Function::arg4_type> Args;
00347 typename ContainerType::template Data< Args > args;
00348 Function f;
00349
00350 EventCatcherImpl( const Function& f_, SignalType& sig )
00351 : f(f_)
00352 {
00353 }
00354 Handle setup( SignalType& sig ) {
00355 return sig.setup( boost::bind( &EventCatcherImpl<4, SignalType, ContainerType>::handler,
00356 shared_ptr(this), _1, _2, _3, _4) );
00357 }
00358
00359 Result handler( typename Function::arg1_type a1,
00360 typename Function::arg2_type a2,
00361 typename Function::arg3_type a3,
00362 typename Function::arg4_type a4 ) {
00363 if ( !this->enabled )
00364 return detail::NA<Result>::na();
00365 args = make_tuple( a1, a2, a3, a4 );
00366 if ( mep )
00367 signalWork();
00368 return detail::NA<Result>::na();
00369 }
00370
00371 virtual void complete() {
00372 if ( !args )
00373 return;
00374 Args tmp_args = args.val();
00375 f( get<0>(tmp_args), get<1>(tmp_args), get<2>(tmp_args), get<3>(tmp_args) );
00376 args.clear();
00377 signalWorkDone();
00378 }
00379 };
00380
00381 template<class SignalType, class ContainerType>
00382 struct EventCatcherImpl<5, SignalType, ContainerType>
00383 : public EventCatcher
00384 {
00385 typedef boost::intrusive_ptr< EventCatcherImpl<5, SignalType, ContainerType> > shared_ptr;
00386 typedef typename SignalType::SlotFunction Function;
00387 typedef typename Function::result_type Result;
00388
00389 typename Function::arg1_type _a1;
00390 typename Function::arg2_type _a2;
00391 typename Function::arg3_type _a3;
00392 typename Function::arg4_type _a4;
00393 typename Function::arg5_type _a5;
00394 typedef boost::tuple<typename Function::arg1_type,
00395 typename Function::arg2_type,
00396 typename Function::arg3_type,
00397 typename Function::arg4_type,
00398 typename Function::arg5_type> Args;
00399 typename ContainerType::template Data< Args > args;
00400 Function f;
00401
00402 EventCatcherImpl( const Function& f_, SignalType& sig )
00403 : f(f_)
00404 {
00405 }
00406
00407 Handle setup( SignalType& sig ) {
00408 return sig.setup( boost::bind( &EventCatcherImpl<5, SignalType, ContainerType>::handler,
00409 shared_ptr(this), _1, _2, _3, _4, _5) );
00410 }
00411
00412 Result handler( typename Function::arg1_type a1,
00413 typename Function::arg2_type a2,
00414 typename Function::arg3_type a3,
00415 typename Function::arg4_type a4,
00416 typename Function::arg5_type a5) {
00417 if ( !this->enabled )
00418 return detail::NA<Result>::na();
00419 args = make_tuple( a1, a2, a3, a4, a5 );
00420 if ( mep )
00421 signalWork();
00422 return detail::NA<Result>::na();
00423 }
00424
00425 virtual void complete() {
00426 if ( !args )
00427 return;
00428 Args tmp_args = args.val();
00429 f( get<0>(tmp_args), get<1>(tmp_args), get<2>(tmp_args), get<3>(tmp_args), get<4>(tmp_args) );
00430 args.clear();
00431 signalWorkDone();
00432 }
00433 };
00434
00435 template<class SignalType, class ContainerType>
00436 struct EventCatcherImpl<6, SignalType, ContainerType>
00437 : public EventCatcher
00438 {
00439 typedef boost::intrusive_ptr< EventCatcherImpl<6, SignalType, ContainerType> > shared_ptr;
00440 typedef typename SignalType::SlotFunction Function;
00441 typedef typename Function::result_type Result;
00442
00443 typedef boost::tuple<typename Function::arg1_type,
00444 typename Function::arg2_type,
00445 typename Function::arg3_type,
00446 typename Function::arg4_type,
00447 typename Function::arg5_type,
00448 typename Function::arg6_type> Args;
00449 typename ContainerType::template Data< Args > args;
00450 Function f;
00451
00452 EventCatcherImpl( const Function& f_, SignalType& sig )
00453 : f(f_)
00454 {
00455 }
00456
00457 Handle setup( SignalType& sig )
00458 {
00459 return sig.setup( boost::bind( &EventCatcherImpl<6, SignalType, ContainerType>::handler,
00460 shared_ptr(this), _1, _2, _3, _4, _5, _6) );
00461 }
00462
00463 Result handler( typename Function::arg1_type a1,
00464 typename Function::arg2_type a2,
00465 typename Function::arg3_type a3,
00466 typename Function::arg4_type a4,
00467 typename Function::arg5_type a5,
00468 typename Function::arg6_type a6) {
00469 if ( !this->enabled )
00470 return detail::NA<Result>::na();
00471 args = make_tuple( a1, a2, a3, a4, a5, a6 );
00472 if ( mep )
00473 signalWork();
00474 return detail::NA<Result>::na();
00475 }
00476
00477 virtual void complete() {
00478 if ( !args )
00479 return;
00480 Args tmp_args = args.val();
00481 f( get<0>(tmp_args), get<1>(tmp_args), get<2>(tmp_args), get<3>(tmp_args), get<4>(tmp_args), get<5>(tmp_args) );
00482 args.clear();
00483 signalWorkDone();
00484 }
00485 };
00486 }
00487
00508 class RTT_API EventProcessor
00509 : public RunnableInterface
00510 {
00511 protected:
00512 friend struct EventCatcher;
00517 typedef List<detail::EventCatcher*> ECList;
00518 ECList catchers;
00519
00520 friend struct detail::EventCatcher;
00521 void destroyed( detail::EventCatcher* ec );
00522
00523 OS::AtomicInt has_work;
00524 public:
00525
00533 enum AsynStorageType {
00534 OnlyFirst,
00535 OnlyLast
00536 };
00537
00541 EventProcessor();
00542
00543 ~EventProcessor();
00544
00545 bool initialize();
00546
00547 void step();
00548
00549 void finalize();
00550
00554 bool breakLoop();
00555
00556 bool hasWork();
00557
00568 template<class SignalType>
00569 Handle connect(const typename SignalType::SlotFunction& f, SignalType& sig, AsynStorageType t )
00570 {
00571 Handle h = this->setup( f, sig, t);
00572 h.connect();
00573 return h;
00574 }
00575
00586 template<class SignalType>
00587 Handle setup(const typename SignalType::SlotFunction& f, SignalType& sig, AsynStorageType t )
00588 {
00589 detail::EventCatcher::shared_ptr eci;
00590 Handle h;
00591 switch ( t ) {
00592 case OnlyFirst:
00593 {
00594
00595 typename detail::EventCatcherImpl<SignalType::SlotFunction::arity, SignalType, detail::OnlyFirstCont>::shared_ptr ecf
00596 (new detail::EventCatcherImpl<SignalType::SlotFunction::arity, SignalType, detail::OnlyFirstCont>(f, sig));
00597 h = ecf->setup( sig );
00598 eci = ecf;
00599 }
00600 break;
00601 case OnlyLast:
00602 {
00603
00604 typename detail::EventCatcherImpl<SignalType::SlotFunction::arity, SignalType, detail::OnlyLastCont>::shared_ptr ecl
00605 (new detail::EventCatcherImpl<SignalType::SlotFunction::arity, SignalType, detail::OnlyLastCont>(f, sig));
00606 h = ecl->setup( sig );
00607 eci = ecl;
00608 }
00609 break;
00610 }
00611 catchers.grow();
00612 catchers.append( eci.get() );
00613 eci->enabled = this->getActivity() && this->getActivity()->isActive();
00614 eci->mep = this;
00615 return h;
00616 }
00617
00618 };
00619
00624 class RTT_API BlockingEventProcessor
00625 : public EventProcessor
00626 {
00627 public:
00632 BlockingEventProcessor();
00633
00634 ~BlockingEventProcessor();
00635
00636 };
00637
00638 }
00639
00640 #endif