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() : 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                     // Use function arity to select implementation :
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                     // Use function arity to select implementation :
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

Generated on Tue Jul 13 11:03:23 2010 for Orocos Real-Time Toolkit by  doxygen 1.6.1