// Copyright (C) 2005  Davis E. King (davis@dlib.net)
// License: Boost Software License   See LICENSE.txt for the full license.
#undef DLIB_TIMER_KERNEl_ABSTRACT_
#ifdef DLIB_TIMER_KERNEl_ABSTRACT_

#include "../threads.h"

namespace dlib
{

    template <
        typename T
        >
    class timer 
    {
        /*!
            INITIAL VALUE
                is_running()      == false
                delay_time()      == 1000
                action_object()   == The object that is passed into the constructor
                action_function() == The member function pointer that is passed to 
                                     the constructor.

            WHAT THIS OBJECT REPRESENTS
                This object represents a timer that will call a given member function 
                (the action function) repeatedly at regular intervals and in its own
                thread.

                Note that the delay_time() is measured in milliseconds but you are not 
                guaranteed to have that level of resolution.  The actual resolution
                is implementation dependent.

            THREAD SAFETY
                All methods of this class are thread safe. 
        !*/

    public:

        typedef void (T::*af_type)();

        timer (  
            T& ao,
            af_type af
        );
        /*!
            requires
                - af does not throw
            ensures                
                - does not block.
                - #*this is properly initialized
                - #action_object() == ao
                - #action_function() == af
                  (af is a member function pointer to a member in the class T)
            throws
                - std::bad_alloc
                - dlib::thread_error
        !*/

        virtual ~timer (
        );
        /*!
            requires
                - is not called from inside the action_function()
            ensures
                - any resources associated with *this have been released
                - will not call the action_function() anymore.
                - if (the action function is currently executing) then
                    - blocks until it finishes
        !*/

        void clear(
        );
        /*!
            ensures
                - #*this has its initial value
                - does not block
            throws
                - std::bad_alloc or dlib::thread_error
                    If either of these exceptions are thrown then #*this is unusable 
                    until clear() is called and succeeds.
        !*/

        af_type action_function (
        ) const;
        /*!
            ensures
                - does not block.
                - returns a pointer to the member function of action_object() that is
                  called by *this.
        !*/

        const T& action_object (
        ) const;
        /*!
            ensures
                - does not block.
                - returns a const reference to the object used to call the member
                  function pointer action_function()
        !*/

        T& action_object (
        );
        /*!
            ensures
                - does not block.
                - returns a non-const reference to the object used to call the member
                  function pointer action_function()
        !*/

        bool is_running (
        ) const;
        /*!
            ensures
                - does not block.
                - if (*this is currently scheduled to call the action_function()) then
                    - returns true
                - else
                    - returns false
        !*/

        unsigned long delay_time (
        ) const;
        /*!
            ensures
                - does not block.
                - returns the amount of time, in milliseconds, that *this will wait between
                  the return of one call to the action_function() and the beginning of the
                  next call to the action_function().
        !*/

        void set_delay_time (
            unsigned long milliseconds
        );
        /*!            
            ensures
                - does not block.
                - #delay_time() == milliseconds
            throws
                - std::bad_alloc or dlib::thread_error
                    If either of these exceptions are thrown then #is_running() == false
                    but otherwise this function succeeds
        !*/
        
        void start (            
        );
        /*!
            ensures
                - does not block.
                - if (is_running() == false) then
                    - #is_running() == true
                    - The action_function() will run in another thread.
                    - The first call to the action_function() will occur in roughly 
                      delay_time() milliseconds.
                - else
                    - this call to start() has no effect
            throws
                - dlib::thread_error or std::bad_alloc
                    If this exception is thrown then #is_running() == false but 
                    otherwise this call to start() has no effect.
        !*/

        void stop (
        );
        /*!
            ensures
                - #is_running() == false
                - does not block.
        !*/

        void stop_and_wait (
        );
        /*!
            ensures 
                - #is_running() == false
                - if (the action function is currently executing) then
                    - blocks until it finishes
        !*/

    private:

        // restricted functions
        timer(const timer<T>&);        // copy constructor
        timer<T>& operator=(const timer<T>&);    // assignment operator

    };    

}

#endif // DLIB_TIMER_KERNEl_ABSTRACT_