#pragma once

//==============================================================================================

//  FileName                    _timer.h

//  Completion Level            2 ( 0 : beginning, 1 : basic, 2 : moderate, 3 : complete )

//  Date                        2016.10.05

/// Since                       2016.08.30

//------------------------------+---------------------------------------------------------------


#include <boost/functional.hpp>

#include <boost/bind.hpp>

#include <boost/date_time/posix_time/posix_time.hpp>

#include <boost/thread.hpp>

#include "_application.h"


//------------------------------+---------------------------------------------------------------


#define MEMBER_ON_TIME( c, m )  std::bind( &c::m, this, _1 )


class                           TIMER : public    COMPONENT

{

    using                       ON_TIME = std::function< xx( TIMER* ) >;


    boost::asio::io_service&    ios;

    boost::asio::deadline_timer timer;

    u32                         interval;

    ox                          repeat;

    ox                          active = false;


    xx                          async_start()

    {

        timer.expires_from_now( boost::posix_time::millisec( interval ) );

        timer.async_wait(

            boost::bind( &TIMER::handler, this, boost::asio::placeholders::error )

        );

    }


    xx                          handler( const  boost::system::error_code& error )

    {

        event_login();

        if( error != boost::asio::error::operation_aborted )

        {

            if( repeat && active )

                async_start();

            if( on_time )

                on_time( this );

        }

    }


    xx                          destroy()

    {

        stop();

    }


public:

    CRE                         TIMER( 

        const u32 interval = 1000, const ON_TIME on_time = nil,

        const ox auto_play = true, const ox repeat = true )

    :   ios( APPLICATION.ios() )

    ,   timer( ios )

    ,   interval( interval )

    ,   on_time( on_time )

    ,   repeat( repeat )

    ,   COMPONENT( APPLICATION.container() )

    {

        if( auto_play )

            play();

    }


    KIL                        ~TIMER()


    {

        stop();

    }


    ox                          is_active()

    {

        return  active;

    }


    ON_TIME                     on_time;


    xx                          play()

    {

        stop();

        active = true;

        ios.reset();

        async_start();

        boost::thread( boost::bind( &boost::asio::io_service::run, &ios ) );

    }


    xx                          stop()

    {

        if( active )

        {

            timer.cancel();

            active = false;

        }

    }


    xx                          set_interval( u32 milli_seconds )

    {

        interval = milli_seconds;

        if( active )

        {

            stop();

            play();

        }

    }


    oo                          left()

    {

        return  (i32)timer.expires_from_now().total_milliseconds();

    }


    i32                         tag;

};

//==============================================================================================


끝~



사용은 이런식.


int main()

{

    {

        oo  f = []( TIMER* timer )

        {

            printf( "[X : %d] %s ( ] msec left ) ",

                (int)timer, timer->tag, date_time_string( now() ).c_str(), timer->left() );

        };


        ( new TIMER( 1000, f ) )->tag = 1;

        ( new TIMER( 1000, f ) )->tag = 2;


        TIMER a( 1000, f );

        a.tag = 3;

        a.stop();

        ssleep(1);

        a.play();

        ssleep(2);


        {

            TIMER b( 1000, f );

            b.tag = 4;

            ssleep( 2 );

        }


        ssleep( 2 );

    }

    getchar();


    APPLICATION.close();


    return  0;

}


주의할점은 쓰레드 관리하기 귀찮아서 VC++ thread 를 쓴게 아니라 boost::thread 를 쓰고 있다는 점.