#ifndef PERIODICACTION
#define PERIODICACTION
/** 
 * Class for periodically calls to a slot: a global function or a method of a
 * given object.
 *
 * Connects the slot to a PeriodicSignal, that wraps a thread, which
 * periodically will call the doWhile[doWhileNot] slot until this returns
 * false[true]. If a FinallyDo action is registered, when the PeriodicAction
 * has finished it will call this finalizing slot
 *
 * To wrap the doWhile, doWhileNot or FinallyDo action properly (type safer
 * than pointer to functions, better object oriented), call the slot factory:
 *
 * slot(global_function)
 * slot(anObject,&Object::Method)
 *
 * EXAMPLE: -----------------------------------------------------------------
 *
 * class Counter: public Object{
 *    Counter(int max, int incr);
 *    bool isIncrementPossible();
 *    void PrintIAmDone();
 * };
 *
 * bool end;void endMe(){end=true;}
 *
 * int main(){
 *   end=false;
 *   Counter byTwo(100,2), byThree(100,3);
 *   
 *   PeriodicAction byTwoEachSec(1000000);
 *   byTwoEachSec.DoWhile(slot(byTwo,&Counter::isIncrementPossible));
 *   byTwoEachSec.FinallyDo(slot(byTwo,&Counter::PrintIAmDone));
 *   byTwoEachSec.Start();
 *   
 *   PeriodicAction byThreeEachTwoSec(2000000);
 *   byThreeEachTwoSec.DoWhile(slot(byThree,&Counter::isIncrementPossible));
 *   byThreeEachTwoSec.FinallyDo(slot(endMe));
 *   byThreeEachTwoSec.Start();
 *   
 *   while(!end){
 *   }
 * }
 * ----------------------------------------------------------------------------
 *
 * Pending: Define behaviour of synchronization of diferent periodicactions
 *
 * Implementation Pending: Check the periodicaction is not running before
 * starting, and it is running before stopping it. (With
 * PeriodicSignal::isRunning) 
 *
 * Implementation Pending: Not thread safe when two periodic actions may
 * access the same variables
 */


#include "PeriodicSignal.hxx"
//for signals, and Object
#include <sigc++/signal_system.h>
using namespace SigC;

class PeriodicAction: public Object {

public:
        /** Aproximate period (+-500ms) in microsec (so, greater than 500000)
         *  to repeat doWhile or doWhileNot actions
         *  @see #doWhile
         *  @see #doWhileNot
         */
    unsigned int period;
public:
    PeriodicAction( unsigned int period_);
                
    PeriodicAction ( unsigned int period_, const Slot0<bool> & doWhileData,
                     const Slot0<void> & finallyData );
    void DoWhileNot( const Slot0<bool> & s);
    void DoWhile(const Slot0<bool> &s);
    void FinallyDo( const Slot0<void> & s);
    void Start();
    void Stop();
//  void SetPeriod(unsigned long int period_);
private:
    PeriodicSignal periodic;
    Connection actionConn,periodConn;
    
    Signal0<bool> doWhile;
    Signal0<bool> doWhileNot;
    
    Signal0<void> finally;
    
    void DoItOnceAndCheckContinuance();
    void DoItOnceAndCheckContinuance_Not();
};



#endif
