/*****************************************************************************
 * $LastChangedDate: 2011-04-09 21:58:06 -0400 (Sat, 09 Apr 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   System-specific time functions.
 *//*
 * LEGAL:   COPYRIGHT (C) 2009 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#ifndef BASE_TIME_CLOCK_HH
#define BASE_TIME_CLOCK_HH 1

#define GET_TIME_CLOCK() (base::TimeClock::GetInstance())

#include "base/singleton.hh"
#include "base/time.hh"  // Milliseconds etc

namespace base {

////////////////////////////////////////////////////////////////////////////////
/// @brief System-specific time functions.
///
/// All we wanted was a C function to read timer ticks.
/// Then that lunatic wrote a dozen design-patterned C++ classes?! :-{
///
/// Elapsed time:
/// -------------
/// This class finds an underlying OS function to measure elapsed time
/// without being affected by possible adjustments to calendar-time.
/// Using hardware counters is preferred.  Using calendar-time is a
/// bad alternative because it is vulnerable to clock skew
/// caused by the user setting the time or syncing with a NTP server.
///
/// UNIX time functions:
/// --------------------
/// UNIX has various functions to measure time.
/// None are perfect, none are guaranteed to exist or be implemented properly,
/// and systems have different hardware clocks.  So this class is complicated
/// by having to find the best of several possible methods.
///
class TimeClock
{
private:
    TimeClock( void );
    ~TimeClock();

//------------------------------------------------------------------------------
// Interface:
public:
                    DEFINE_GetInstance( TimeClock )  // Singleton
    Milliseconds    GetElapsedTime( void );  // throws

//------------------------------------------------------------------------------
// Implementation:
public:
    /// @brief System-specific.
    class ElapsedTimeFunctor : public Shared
    {
    PREVENT_COPYING(ElapsedTimeFunctor)
    public:
                                ElapsedTimeFunctor( void ) { }
        virtual                 ~ElapsedTimeFunctor( void ) { }
        virtual bool            IfAvailable( void ) = 0;
        virtual Milliseconds    GetElapsedTime( void ) = 0;
    };

private:
    CLASS_METHOD shptr<ElapsedTimeFunctor> SelectElapsedTimeFunctor( void );

private:
    CLASS_VAR TimeClock*        msInstance;
    shptr<ElapsedTimeFunctor>   mElapsedTimeFunctor;
};

} // namespace base

#endif // BASE_TIME_CLOCK_HH
