EventProcessor.hpp

00001 /***************************************************************************
00002   tag: Peter Soetens  Tue Dec 21 22:43:07 CET 2004  EventProcessor.hpp
00003 
00004                         EventProcessor.hpp -  description
00005                            -------------------
00006     begin                : Tue December 21 2004
00007     copyright            : (C) 2004 Peter Soetens
00008     email                : peter.soetens@mech.kuleuven.ac.be
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU General Public                   *
00013  *   License as published by the Free Software Foundation;                 *
00014  *   version 2 of the License.                                             *
00015  *                                                                         *
00016  *   As a special exception, you may use this file as part of a free       *
00017  *   software library without restriction.  Specifically, if other files   *
00018  *   instantiate templates or use macros or inline functions from this     *
00019  *   file, or you compile this file and link it with other files to        *
00020  *   produce an executable, this file does not by itself cause the         *
00021  *   resulting executable to be covered by the GNU General Public          *
00022  *   License.  This exception does not however invalidate any other        *
00023  *   reasons why the executable file might be covered by the GNU General   *
00024  *   Public License.                                                       *
00025  *                                                                         *
00026  *   This library is distributed in the hope that it will be useful,       *
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00029  *   Lesser General Public License for more details.                       *
00030  *                                                                         *
00031  *   You should have received a copy of the GNU General Public             *
00032  *   License along with this library; if not, write to the Free Software   *
00033  *   Foundation, Inc., 59 Temple Place,                                    *
00034  *   Suite 330, Boston, MA  02111-1307  USA                                *
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             // do not accept 'work'
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 ) // if enabled and mep, there is an getActivity() present.
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                 // the container decides if a1 needs to be stored
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                     /*Check for work.*/
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                         /*Try to clear work. If pre-empted here by operator=() tag will be incremented toO.*/
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                     // Use function arity to select implementation :
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                     // Use function arity to select implementation :
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
Generated on Thu Dec 23 13:22:37 2010 for Orocos Real-Time Toolkit by  doxygen 1.6.3