// emTimer.h
// Copyright (C) 2006-2008,2010,2016 Oliver Hamann.
// Homepage: http://eaglemode.sourceforge.net/
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License version 3 as published by the
// Free Software Foundation.
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
// more details.
// You should have received a copy of the GNU General Public License version 3
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#ifndef emTimer_h
#define emTimer_h

#ifndef emEngine_h
#include <emCore/emEngine.h>

//================================== emTimer ===================================

class emTimer : public emUncopyable {


        // Class for a timer which signals an emSignal on each timer event.

        emTimer(emScheduler & scheduler);
                // Construct a timer. The given scheduler is used for signaling
                // the timer signal (and for an internal engine which serves all
                // the timers on that scheduler).

        virtual ~emTimer();
                // Destructor.

        emScheduler & GetScheduler() const;
                // Get the scheduler.

        const emSignal & GetSignal() const;
                // This signal is signaled on each timer event.

        void Start(emUInt64 millisecs, bool periodic=false);
                // Start the timer.
                // Arguments:
                //   millisecs - Time in milliseconds after which a timer event
                //               shall be generated.
                //   periodic  - If true, additional timer events are generated
                //               periodically. The given number of milliseconds
                //               is the period duration. The timer tries to keep
                //               up that rate on average, even if timer events
                //               are delayed through blockings of the scheduler,
                //               but it is limited to the rate of scheduler time
                //               slices by all means.

        bool IsRunning() const;
                // Ask whether the timer is still active.

        void Stop(bool abortSignal);
                // Stop the timer.
                // Arguments:
                //   abortSignal - Whether to perform an Abort() on the signal,
                //                 but remember that engines could already have
                //                 been woken up. Say false for an asynchronous
                //                 stop, or true for a synchronous stop.


        struct TimeNode {
                emUInt64 SigTime;
                TimeNode * Prev;
                TimeNode * Next;

        class TimerCentral : public emEngine {
                TimerCentral(emScheduler & scheduler);
                void Insert(TimeNode * node, emUInt64 sigTime);
                int RefCount;
                virtual bool Cycle();
                TimeNode InList;
                TimeNode OutList;
                bool Busy;

        friend class TimerCentral;

        TimerCentral * Central;
        emSignal TimerSignal;
        emUInt64 Period;
        TimeNode Node;

inline emScheduler & emTimer::GetScheduler() const
        return Central->GetScheduler();

inline const emSignal & emTimer::GetSignal() const
        return TimerSignal;

inline bool emTimer::IsRunning() const
        return Node.Prev!=NULL;