Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

/home/slang/XVision2/src/Pipes/PipeEvents.h

00001 # ifndef _PIPEEVENTS_H_
00002 # define _PIPEEVENTS_H_
00003 
00004 # include "PipeModules.h"
00005 
00006 // Events are basically synchronous, which means possibly to compute for 
00007 // a value which is never used. We'll have asynchronous version soon.
00008 
00009 // Helper functions
00010 
00011 template<class T>
00012 class Maybe : protected Pair<bool,T> {
00013  public:
00014   Maybe() : Pair<bool,T>() { lval = false ; }
00015   Maybe( const T& x ) : Pair<bool,T>(true,x) {}
00016   Maybe( bool f, const T& x ) : Pair<bool,T>(f,x) {}
00017   Maybe( const Maybe<T>& x ) : Pair<bool,T>(x) {}
00018   Maybe<T>& operator = (const Maybe<T>& x) 
00019     {
00020       if( &x != this ) {
00021      if( lval = x.lval ) {
00022        rval = x.rval ;
00023      }
00024       }
00025       return *this ;
00026     }
00027 
00028   bool hasValue(void) const { return lval ; }
00029   T getValue(void) const { return rval ; }
00030   operator bool () const { return hasValue(); }
00031   bool operator ! () const { return !hasValue(); }
00032   T operator *() const { return getValue(); }
00033 };
00034 
00035 template<class T>
00036 inline Maybe<T> maybePair( bool f, const T& x ) {
00037   return Maybe<T>(f,x);
00038 }
00039 // Caution -- PipeModuleLift implementaion dependent!
00040 template<class T>
00041 inline Pipe<Maybe<T> > maybeP( const Pipe<bool>& x1, const Pipe<T>& x2 ) {
00042   PipeModuleLift2<Maybe<T>,bool,T,Maybe<T> (*)(bool, const T&)> pair
00043     (maybePair<T>) ;
00044   return pair(x1,x2);
00045 }
00046 
00047 template<class T1, class T2>
00048 Maybe<Pair<T1,T2> > maybeAnd ( const Maybe<T1>& x1, 
00049                       const Maybe<T2>& x2 ) {
00050   if( x1 && x2 ) {
00051     return Maybe<Pair<T1,T2> >(Pair<T1,T2>(*x1,*x2));
00052   }else {
00053     return Maybe<Pair<T1,T2> >();
00054   }
00055 }
00056 
00057 template<class T1, class T2>
00058 Maybe<Pair<T1,T2> > maybeOr ( const Maybe<T1>& x1, 
00059                      const Maybe<T2>& x2 ) {
00060   if( x1 || x2 ) {
00061     return Maybe<Pair<T1,T2> >(Pair<T1,T2>(*x1,*x2));
00062   }else {
00063     return Maybe<Pair<T1,T2> >();
00064   }
00065 }
00066 
00067 // PipeEvents is a stream of events, each of them contains a data pack
00068 
00069 template<class T>
00070 class PipeEvents : public Pipe<Maybe<T> > {
00071  protected:
00072 
00073   PipeEvents<T>* duplicate(void) const { return new PipeEvents<T>(*this); }
00074 
00075  public:
00076 
00077   PipeEvents() : Pipe<Maybe<T> >() {}
00078   PipeEvents( const PipeEvents<T>& p ) : Pipe<Maybe<T> >(p) {}
00079   PipeEvents( const Pipe<Maybe<T> >& p ) : Pipe<Maybe<T> >(p) {}
00080   PipeEvents( PipeModule<Maybe<T> > *v ) : Pipe<Maybe<T> >(v) {}
00081 
00082   PipeEvents<T>& operator = ( const PipeEvents<T>& p )
00083     { Pipe<Maybe<T> >::operator = (p); return *this ; }
00084   PipeEvents<T>& operator = ( const Pipe<Maybe<T> >& p )
00085     { Pipe<Maybe<T> >::operator = (p); return *this ; }
00086 
00087   bool hasValue(void) { return current_value().hasValue() ; }
00088   bool hasValue( int fc ) { return get_value(fc).hasValue() ; }
00089   T getValue( int fc ) { return get_value(fc).getValue() ; }
00090 };
00091 
00092 // whileP is a direct way to convert Pipe to PipeEvents
00093 template<class T, class Fn>
00094 inline PipeEvents<T> whileP( Fn fn, const Pipe<T>& p ) {
00095   return PipeEvents<T>( maybeP<T>( liftP(fn)(p), p ) );
00096 }
00097 
00098 inline PipeEvents<bool> whileP( const Pipe<bool>& p ) {
00099   return PipeEvents<bool>( maybeP<bool>( p, p ) );
00100 }
00101 
00102 // auxiliary class for whileP
00103 
00104 template<class T, class Fn>
00105 class PipeWhileModule : XVFunctoid1<Fn,PipeEvents<T>,Pipe<T> > {
00106   typedef XVFunctoid1<Fn,PipeEvents<T>,Pipe<T> > BaseType ;
00107  public:
00108   PipeWhileModule( Fn fn ) : BaseType(fn) {}
00109   virtual PipeEvents<T> operator () ( const Pipe<T>& x )
00110     { return maybeP<T>( liftP(f)(x), x ) ; }
00111 };
00112 
00113 template<class T, class Fn>
00114 inline PipeWhileModule<T,Fn> whileP( Fn fn ) {
00115   return PipeWhileModule<T,Fn>(fn);
00116 }
00117 template<class T>
00118 inline PipeWhileModule<T,bool (*)(T)> whileP( bool (*fn)(T) ) {
00119   return PipeWhileModule<T,bool (*)(T)>(fn);
00120 }
00121 template<class T>
00122 inline PipeWhileModule<T,bool (*)(const T&)> whileP( bool (*fn)(const T&) ) {
00123   return PipeWhileModule<T,bool (*)(const T&)>(fn);
00124 }
00125 
00126 // uniqueP, suppress duplicate successive events in an event pipe
00127 
00128 template<class T>
00129 Maybe<T> maybeNotAnd ( const Maybe<T>& x1, const Maybe<T>& x2 ) {
00130   if( !x1 && x2 ) {
00131     return x2;
00132   }else {
00133     return Maybe<T>(/*false*/);
00134   }
00135 }
00136 
00137 template<class T>
00138 inline PipeEvents<T> uniqueP( const PipeEvents<T>& p ) {
00139   typedef Maybe<T> MT ;
00140   PipeModuleLift2<MT,MT,MT,MT (*)(const MT&,const MT&)> ufun(maybeNotAnd<T>) ;
00141   return ufun( delayP(Maybe<T>()) <<= p, p ) ;
00142 }
00143 
00144 // WhenP = uniqueP(whileP)
00145 
00146 template<class T, class Fn>
00147 class PipeWhenModule : XVFunctoid1<Fn,PipeEvents<T>,Pipe<T> > {
00148   typedef XVFunctoid1<Fn,PipeEvents<T>,Pipe<T> > BaseType ;
00149  public:
00150   PipeWhenModule( Fn fn ) : BaseType(fn) {}
00151   virtual PipeEvents<T> operator () ( const Pipe<T>& x )
00152     { return uniqueP( PipeEvents<T>( maybeP<T>( liftP(f)(x), x ) ) ); }
00153 };
00154 
00155 template<class T, class Fn>
00156 inline PipeWhenModule<T,Fn> whenP( Fn fn ) {
00157   return PipeWhenModule<T,Fn>(fn);
00158 }
00159 template<class T>
00160 inline PipeWhenModule<T,bool (*)(T)> whenP( bool (*fn)(T) ) {
00161   return PipeWhenModule<T,bool (*)(T)>(fn);
00162 }
00163 template<class T>
00164 inline PipeWhenModule<T,bool (*)(const T&)> whenP( bool (*fn)(const T&) ) {
00165   return PipeWhenModule<T,bool (*)(const T&)>(fn);
00166 }
00167 
00168 // thenP, same as -=> in frp, use operator |= here
00169 
00170 // We have three version of then/until: statical and dynamical, and functional,
00171 // indicated by postfix s, d and f respectivly.
00172 // statical version wastes computation, while dynamical one wastes memory
00173 // without a garbage collector. Functional one always creates new pipe when 
00174 // switched to, so it can't be used to switch back again to the same pipe.
00175 // The default one is statical. Functional version is not implemented yet.
00176 
00177 template<class T1, class T2>
00178 PipeEvents<T2> thenPs( const PipeEvents<T1>& e, const Pipe<T2>& p ) {
00179   return maybeP( liftP(&Maybe<T1>::hasValue)(e), p );
00180 }
00181 
00182 template<class T1, class T2>
00183 PipeEvents<Pipe<T2>*> thenPd( const PipeEvents<T1>& e, const Pipe<T2>& p ) {
00184   return maybeP( liftP(&Maybe<T1>::hasValue)(e), 
00185            Pipe<Pipe<T2>*>(new Pipe<T2>(p)) );
00186 }
00187 
00188 template<class T1, class T2>
00189 inline PipeEvents<T2> thenP( const PipeEvents<T1>& e, const Pipe<T2>& p ) {
00190   return thenPs(e,p) ;
00191 }
00192 
00193 template<class T1, class T2>
00194 inline PipeEvents<T2> 
00195 operator |= ( const PipeEvents<T1>& e, const Pipe<T2>& p ) {
00196   return thenP( e, p );
00197 }
00198 
00199 // switchP, or *= for `until` in frp
00200 
00201 template<class T>
00202 T switchFunS( const Maybe<T>& x1, const T& x2 ) {
00203   if( x1 ) {
00204     return x1.getValue() ;
00205   }else {
00206     return x2 ;
00207   }
00208 }
00209 
00210 // Caution -- PipeModuleLift implementaion dependent!
00211 template<class T>
00212 inline Pipe<T> switchPs( const Pipe<T>& p, const PipeEvents<T>& e ) {
00213   PipeModuleLift2<T,Maybe<T>,T,T (*)(const Maybe<T>&, const T&)> sfun
00214     (switchFunS<T>) ;
00215   return sfun( e, p );
00216 }
00217 
00218 template<class T>
00219 class SwitchFunD : public XVFunctoid2<int,T,T,Maybe<Pipe<T>*> >{
00220   typedef XVFunctoid2<int,T,T,Maybe<Pipe<T>*> > BaseType ;
00221 public:
00222   SwitchFunD( int fc ) : BaseType(fc) {}
00223   int set( int fc ) { return f = fc ; }
00224   operator bool (void) { return true ; }
00225   T operator ()( const T& x, const Maybe<Pipe<T>*>& e ) 
00226     { if( e ) return e.getValue()->get_value(f) ; else return x ; }
00227 };
00228 
00229 
00230 template<class T>
00231 class PipeModuleSwitchD : 
00232  public PipeModuleLift2<T,T,Maybe<Pipe<T>*>,SwitchFunD<T> > {
00233   typedef PipeModuleSwitchD<T> ThisType ;
00234   typedef PipeModuleLift2<T,T,Maybe<Pipe<T>*>,SwitchFunD<T> > BaseType ;
00235  protected:
00236   ThisType * duplicate(void) const { return new ThisType(*this); }
00237  public:
00238   PipeModuleSwitchD() : BaseType(0) {}
00239   PipeModuleSwitchD( const ThisType& p ) : BaseType(p) {}
00240   T compute_local_fn( int fc ) 
00241     { return BaseType::compute_local_fn( fn.set(fc) ) ; }
00242 };
00243 
00244 template<class T>
00245 inline Pipe<T> switchPd( const Pipe<T>& p, const PipeEvents<Pipe<T>*>& e ) {
00246   PipeModuleSwitchD<T> sfun ;
00247   return sfun(p,e);
00248 }
00249 
00250 /*
00251 template<class T>
00252 class PipeModuleSwitchD : public PipeLift2<T,T,Maybe<Pipe<T> > > {
00253   typedef PipeModuleSwitchD<T> ThisType ;
00254   typedef PipeLift2<T,T,Maybe<Pipe<T> > > BaseType ;
00255   typedef T Tin1 ;
00256   typedef Maybe<Pipe<T> > Tin2 ;
00257  protected:
00258   Pipe<Tin1> * pred1 ;
00259   Pipe<Tin2> * pred2 ;
00260 
00261  protected:
00262   void setDependency(void) 
00263     { 
00264       addDependency((DependencyUnit**)&pred1); 
00265       addDependency((DependencyUnit**)&pred2); 
00266     }
00267   DependencyUnit * duplicate(void) const 
00268     { return new ThisType(*this); }
00269 
00270   inline void check(void) 
00271     { PipeModule<Tout>::check( (bool)fn&&pred1&&pred2 ); }
00272 
00273  public:
00274   PipeModuleSwitchD() : pred1(0), pred2(0), switched(false)
00275     { setDependency(); } 
00276   PipeModuleSwitchD( const ThisType& p ) : 
00277     BaseType(p), pred1(p.pred1), pred2(p.pred2), switched(p.switched)
00278     { setDependency(); } 
00279 
00280   virtual Pipe<Tout> 
00281     operator ()( const Pipe<Tin1>& x1, const Pipe<Tin2>& x2 ) const
00282     { 
00283       ThisType *p = new ThisType(*this);
00284       p->pred1 = new Pipe<Tin1>(x1); 
00285       p->pred2 = new Pipe<Tin2>(x2); 
00286       return Pipe<Tout>(p) ; 
00287     }
00288 
00289   Tout compute_local_fn( int fc ) 
00290     { 
00291       check(); 
00292       Tin2 = pred2->get_value(fc) ;
00293       if( switched ) {
00294      return Tin2.getValue().get_value(fc) ;
00295       }else {
00296      return pred1->get_value(fc) ;
00297       }
00298     }
00299 };
00300 */
00301 
00302 template<class T>
00303 inline Pipe<T> switchP( const Pipe<T>& p, const PipeEvents<T>& e ) {
00304   return switchPs( p, e );
00305 }
00306 
00307 template<class T>
00308 inline Pipe<T> 
00309 operator *= ( const Pipe<T>& p, const PipeEvents<T>& e ) {
00310   return switchP( p, e );
00311 }
00312 
00313 # define SWITCH_P *=
00314 
00315 // PipeEvents operations
00316 
00317 template<class T1, class T2>
00318 PipeEvents<Pair<T1,T2> > operator && ( const PipeEvents<T1>& x1,
00319                            const PipeEvents<T2>& x2 ) {
00320   return PipeEvents<Pair<T1,T2> >( liftP(maybeAnd<T1,T2>)(x1,x2) );
00321 }
00322 template<class T1, class T2>
00323 PipeEvents<Pair<T1,T2> > operator || ( const PipeEvents<T1>& x1,
00324                            const PipeEvents<T2>& x2 ) {
00325   return PipeEvents<Pair<T1,T2> >( liftP(maybeOr<T1,T2>)(x1,x2) );
00326 }
00327 
00328 template<class T>
00329 class PipeEventOnce : public PipeModule<Maybe<T> > {
00330   typedef PipeEventOnce<T> ThisType ;
00331   typedef PipeModule<Maybe<T> > BaseType ;
00332  protected:
00333   Maybe<T> happened ;
00334   PipeEvents<T> * pred ;
00335 
00336  protected:
00337 
00338   void setDependency(void) { addDependency((DependencyUnit**)&pred); }
00339   ThisType * duplicate(void) const { return new ThisType(*this); }
00340 
00341  public:
00342   PipeEventOnce( const PipeEvents<T>& x ) :
00343     happened(/*false*/), pred(new PipeEvents<T>(x)) { setDependency(); }
00344   PipeEventOnce( const ThisType& e ) : BaseType(e), 
00345     happened(e.happened), pred(e.pred) { setDependency(); }
00346 
00347   Maybe<T> compute_local_fn( int fc ) 
00348     {
00349       if( !happened ) {
00350      happened = pred->get_value(fc);
00351       }
00352       return happened ;
00353     }
00354 };
00355 
00356 template<class T>
00357 PipeEvents<T> onceP( const PipeEvents<T>& p ) {
00358   return PipeEvents<T>(new PipeEventOnce<T>(p));
00359 }
00360 
00361 template<class T>
00362 class PipeEventNth : public PipeModule<Maybe<T> > {
00363   typedef PipeEventNth<T> ThisType ;
00364   typedef PipeModule<Maybe<T> > BaseType ;
00365  protected:
00366   int n, c ;
00367   PipeEvents<T> * pred ;
00368 
00369  protected:
00370 
00371   void setDependency(void) { addDependency((DependencyUnit**)&pred); }
00372   ThisType * duplicate(void) const { return new ThisType(*this); }
00373 
00374  protected:
00375 
00376   void check(void) { PipeModule<Maybe<T> >::check( pred ); }
00377 
00378  public:
00379   PipeEventNth( int nth ) : n(nth), c(0), pred(0) { setDependency(); }
00380   PipeEventNth( const ThisType& e ) : BaseType(e),
00381     n(e.n), c(e.c), pred(e.pred) { setDependency(); }
00382 
00383   PipeEvents<T> operator ()( const PipeEvents<T>& x ) const 
00384     {
00385       PipeEventNth<T> *p = new PipeEventNth<T>(*this);
00386       p->pred = new PipeEvents<T>(x);
00387       return PipeEvents<T>(p);
00388     }
00389 
00390   Maybe<T> compute_local_fn( int fc ) 
00391     {
00392       check();
00393       if( c < n && pred->get_value(fc) && ++c == n ) {
00394      return pred->get_value(fc);
00395       }else {
00396      return Maybe<T>(/*false*/);
00397       }
00398     }
00399 };
00400 
00401 template<class T>
00402 PipeEventNth<T> nthP( int n ) {
00403   return PipeEventNth<T>(n);
00404 }
00405 template<class T>
00406 inline PipeEvents<T> 
00407 operator <<= ( const PipeEventNth<T>& m, const PipeEvents<T>& p ){
00408   return m(p);
00409 }
00410 
00411 /* Old code
00412 
00413 // whenP is a direct way to convert Pipe to PipeEvents
00414 
00415 template<class T, class Fn>
00416 PipeEvents<T> whenP( const Pipe<T>& p, Fn fn ) {
00417   return PipeEvents<T>( liftP(maybePair<T>)( liftP(fn)(p), p ) );
00418 }
00419 template<class T>
00420 PipeEvents<T> whenP( const Pipe<bool>& flag, const Pipe<T>& data ) {
00421   return PipeEvents<T>( liftP(maybePair<T>)( falg, data ) );
00422 }
00423 template<class T>
00424 PipeEvents<T> whenP( const Pipe<Maybe<T> >& p ) {
00425   return PipeEvents<T>(p);
00426 }
00427 
00428 // Switch -- basic unit for events affect pipe's behavior
00429 
00430 template<class Tout, class Tvoid>
00431 class PipeModuleSwitch : public PipeModule<Tout> {
00432   typedef PipeModuleSwitch<Tout,Tvoid> ThisType ;
00433  protected:
00434   bool sync ;   // whether the switch is a synchronous one or not
00435   PipeEvents<Tvoid> * events ;
00436   Pipe<Tout> * pred1 ;
00437   Pipe<Tout> * pred2 ;
00438 
00439  protected:
00440 
00441   void setDependency(void) 
00442     { 
00443       addDependency((DependencyUnit**)&events); 
00444       addDependency((DependencyUnit**)&pred1); 
00445       addDependency((DependencyUnit**)&pred2); 
00446     }
00447   DependencyUnit * duplicate(void) const { return new ThisType(*this); }
00448 
00449  protected:
00450 
00451   inline void check(void)
00452     { PipeModule<Tout>::check( events && pred1 && pred2 ); }
00453 
00454  public:
00455   
00456   PipeModuleSwitch( const PipeEvents<Tvoid>& e, bool s=false ) : 
00457     sync(s), events(new PipeEvents<Tvoid>(e)), pred1(0), pred2(0) 
00458     { setDependency(); }
00459   PipeModuleSwitch( const ThisType& s ) : PipeModule<Tout>(s), 
00460     sync(s.sync), events(s.events), pred1(s.pred1), pred2(s.pred2) 
00461     { setDependency(); }
00462 
00463   Pipe<Tout> operator ()( const Pipe<Tout>& x1, const Pipe<Tout>& x2 ) const 
00464     {
00465       ThisType *p = new ThisType(*this) ;
00466       p->pred1 = new Pipe<Tout>(x1);
00467       p->pred2 = new Pipe<Tout>(x2);
00468       return Pipe<Tout>(p);
00469     }
00470 
00471   Tout compute_local_fn( int fc ) 
00472     { 
00473       check(); 
00474       return events->hasValue(fc)?pred1->get_value(fc):pred2->get_value(fc);
00475     }
00476 };
00477 
00478 template<class Tout, class Tvoid>
00479 PipeModuleSwitch<Tout, Tvoid> 
00480 switchP( const PipeEvents<Tvoid>& events, bool sync=false ) {
00481   return PipeModuleSwitch<Tout, Tvoid>( events, sync );
00482 }
00483 template<class Tout, class Tvoid>
00484 Pipe<Tout> 
00485 switchP( const PipeEvents<Tvoid>& events, const Pipe<Tout>& x1,
00486       const Pipe<Tout>& x2, bool sync=false ) {
00487   return PipeModuleSwitch<Tout, Tvoid>( events, sync )( x1, x2 );
00488 }
00489 
00490 // PipeUntil -- a new pipe is created each time
00491 
00492 template<class Tout, class Tevent, class Fn>
00493 class PipeModuleUntil : public PipeModule<Tout> {
00494   typedef PipeModuleUntil<Tout,Tevent,Fn> ThisType ;
00495  protected:
00496   Fn fn ;
00497   PipeEvents<Tevent> * events ;
00498   Pipe<Tout> * pred ;
00499 
00500  protected:
00501 
00502   void setDependency(void) 
00503     { 
00504       addDependency((DependencyUnit**)&events); 
00505       addDependency((DependencyUnit**)&pred); 
00506     }
00507   DependencyUnit * duplicate(void) const { return new ThisType(*this); }
00508 
00509  protected:
00510 
00511   inline void check(void)
00512     { PipeModule<Tout>::check( events && pred ); }
00513 
00514  public:
00515 
00516   PipeModuleUntil( const PipeEvents<Tevent>& e, Fn fnin ) :
00517     fn(fnin), events(new PipeEvents<Tevent>(e)), pred(0) { setDependency(); }
00518   PipeModuleUntil( const ThisType& u ) : PipeModule<Tout>(u), 
00519     fn(u.fn), events(u.events), pred(u.pred) { setDependency(); }
00520 
00521   Pipe<Tout> operator ()( const Pipe<Tout>& x ) const
00522     {
00523       ThisType *p = new ThisType(*this);
00524       p->pred = new Pipe<Tout>(x);
00525       return Pipe<Tout>(p);
00526     }
00527 
00528   Tout compute_local_fn( int fc )
00529     {
00530       check();
00531       if( events->hasValue(fc) ) {
00532      pred = new Pipe<Tout>( fn( events->getValue(fc), *pred ) );
00533       }
00534       Tout v = pred->get_value(fc);
00535       return v ;
00536     }
00537 };
00538 
00539 template<class Tout, class Tevent>
00540 PipeModuleUntil<Tout,Tevent,Pipe<Tout> (*)(Tevent, const Pipe<Tout>&)>
00541 untilP( const PipeEvents<Tevent>& e, 
00542      Pipe<Tout> (*fn)(Tevent, const Pipe<Tout>&) ) {
00543   return PipeModuleUntil<Tout,Tevent,
00544     Pipe<Tout> (*)(Tevent, const Pipe<Tout>&)>( e, fn );
00545 }
00546 */
00547 
00548 # endif //_PIPEEVENTS_H_

Generated at Thu Mar 29 22:37:28 2001 for XVision by doxygen1.2.0 written by Dimitri van Heesch, © 1997-2000