#ifndef AUTORUNNER_H
#define AUTORUNNER_H
/*
//範例 ，處理進入Block 與 出Block 產生CallBack 
template <void (*SF)(), void (*EF)()>
class AutoRunnerStatic
{
public:
AutoRunnerStatic  () { SF();}
~AutoRunnerStatic () { EF();}
};

void FirstAction() { std::cout << " FirstAction" << std::endl;}
void LastAction () { std::cout << " LastAction"  << std::endl;}
typedef AutoRunnerStatic<FirstAction,LastAction> AutoAction;

int main()
{
    std::cout << "In beginning of main" << std::endl;
        {
        AutoAction autoAction;
        std::cout << "  In sub block" << std::endl;
        }
    std::cout << "At end of main" << std::endl;

    return 0;
}

//範例2
#include <iostream>

template <class T, void (T::*SF)(), void (T::*EF)()>
class AutoRunner
{
public:
    AutoRunner  (T &instance) : m_instance(instance) { (m_instance.*SF)();}
    ~AutoRunner () { (m_instance.*EF)();}
private:
    T &m_instance;
};

class MyClass
{
public:
    MyClass (long value) : m_value(value) {}
    void FirstMethod() { std::cout << " FirstMethod, value is " << m_value << std::endl;}
    void LastMethod () { std::cout << " LastMethod , value is " << m_value << std::endl;}
private:
    long m_value;
};

typedef AutoRunner<MyClass,&MyClass::FirstMethod,&MyClass::LastMethod> MyClassAuto;

int main()
{
    std::cout << "In beginning of main" << std::endl;

    MyClass myInstance(1);
    MyClass myInstance2(2);
    {
        MyClassAuto myClassAuto(myInstance);
        std::cout << "  In sub block" << std::endl;
    }
    {
        MyClassAuto myClassAuto(myInstance2);
        std::cout << "  In sub block" << std::endl;
    }

    std::cout << "At end of main" << std::endl;

    return 0;
}
*/
/*!
The AutoRunnerStatic template class can be used for coupling actions that need to be performed before and after a block of code.
The template should be given 2 function pointers, a start function (SF) and an end function (EF).
If an instance of the template class is created, the start function is executed.
If the instance is deleted, the end function is executed.
The two functions must be functions that have no arguments and no return value (void).

In the following example we create a type based on the AutoRunnerStatic tempate class.  It is intended to manage the transactions on a
database.  If an instance is created, a transation is started.  If the instance is deleted, the transaction is automatically committed.

\code
typedef AutoRunnerStatic<StartTransaction,CommitTransaction> Transaction;

void someFunction()
{
Transaction t;                // A transaction is automatically started.
...
}                             // The transaction is automatically committed at the end of the code block, when t goes out of scope.
\endcode

\sa http://www.codeproject.com/useritems/AutoRunner.asp
\sa AutoRunnerConst
\sa AutoRunner
\author Patje
*/
template <void (*SF)(), void (*EF)()>
class AutoRunnerStatic
   {
   public:
      AutoRunnerStatic  () { SF();}
      ~AutoRunnerStatic () { EF();}
   };

/*!
The AutoRunner template class can be used for coupling actions that need to be performed before and after a block of code.
The template should be given one class type and 2 function pointers, a start method/function (SF) and an end method/function (EF).
The constructor of the template class should be given an instance of the class type that was specified in the template class
If an instance of the template class is created, the start method SF is called on the instance given to the constructor.
If the instance is deleted, the end method SF is executed for the instance given to the constructor.
The two methods must be methods that have no arguments and no return value (void).

In the following example we create a type based on the AutoRunner tempate class.  It is intended to manage the locking of a
data structure.  If an instance of the template class is created, The data structure is locked.
If the instance is deleted, the data structure is automatically unlocked.

\code
class DataStructure
   {
   public:
      ...
      void lock();
      void unlock();
   };

typedef AutoRunner<DataStructure,lock,unlock> Locker;

void someFunction (DataStructure &data)
{
Locker locker(data);          // The data is locked
...
}                             // The data is automatically unlocked at the end of the code block, when locker goes out of scope.
\endcode

\sa http://www.codeproject.com/useritems/AutoRunner.asp
\sa AutoRunnerStatic
\sa AutoRunnerConst
\author Patje
*/
template <class T, void (T::*SF)(), void (T::*EF)()>
class AutoRunner
   {
   public:
      AutoRunner  (T &instance) : m_instance(instance) { (m_instance.*SF)();}
      ~AutoRunner () { (m_instance.*EF)();}
   private:
      T &m_instance;
   };

/*!
The AutoRunnerConst template class can be used for coupling actions that need to be performed before and after a block of code.
It is similar to the AutoRunner template class, but is defined in terms of a const instance and const methods.
It can be used when the two given methods are const methods, working on a const instance (given to the constructor).

\sa AutoRunner
*/
template <class T, void (T::*SF)() const, void (T::*EF)() const>
class AutoRunnerConst
   {
   public:
      AutoRunnerConst  (const T &instance) : m_instance(instance) { (m_instance.*SF)();}
      ~AutoRunnerConst () { (m_instance.*EF)();}
   private:
      const T &m_instance;
   };
