#ifndef __UTILITY_ITIMEOUT_H_ #define __UTILITY_ITIMEOUT_H_ #pragma once //================================================================================================== // version control #define __ITIMERBASE_VERSION_CRTL (0x0120) //================================================================================================== //================================================================================================== //================================================================================================== //================================================================================================== #if __ITIMERBASE_VERSION_CRTL < 0x0120 //================================================================================================== //================================================================================================== //================================================================================================== namespace util { namespace nsOldVer { #pragma pack(push) #pragma pack() //================================================================================================== // // ´Ü¼ø Timeout 󸮸¦ ¸ñÀûÀ¸·Î ÇÑ´Ù. // // // ITimeout timeout; // timeout.IsExpired() ==> ÀÌ ½ÃÁ¡¿¡¼­´Â Ç×»ó FALSE (¹«ÇѰªÀ¸·Î ¼³Á¤) // timeout.SetNextTimeout( GetTickCount() + 3000 ) ==> 3ÃÊ µÚ IsExpired() == TRUE // timeout.SetNextTimeoutByCurTickBased( 3000 ) ==> 3ÃÊ µÚ IsExpired() == TRUE // timeout.Instance() ==> ¹Ù·Î IsExpired() ÇØµµ TRUE // timeout.Disabled() ==> ½Ã½ºÅÛ Á¡°Ë ±â°£³» Ç×»ó IsExpired() == FALSE class ITimeout_v01xx { public: static const DWORD UNLIMITED = (DWORD)(-1); static const DWORD INSTANCE = 0; ITimeout_v01xx() : m_dwTimeoutTick(UNLIMITED) {} //================================================================================ // public: inline BOOL IsExpired() { DWORD dwCurTick = GetTickCount(); if( !(dwCurTick < TimeoutTick()) ) return TRUE; return FALSE; } inline BOOL IsDisabled() { return (BOOL)( ITimeout_v01xx::UNLIMITED == TimeoutTick() ); } inline VOID Disabled() { TimeoutTick() = ITimeout_v01xx::UNLIMITED; } inline VOID Instance() { TimeoutTick() = ITimeout_v01xx::INSTANCE; } inline VOID SetNextTimeout( DWORD dwTimeoutTick ) { m_dwTimeoutTick = dwTimeoutTick; } inline VOID SetNextTimeoutByCurTickBased( DWORD dwTimeoutTick ) { m_dwTimeoutTick = GetTickCount() + dwTimeoutTick; } inline DWORD& TimeoutTick() { return m_dwTimeoutTick; } private: DWORD m_dwTimeoutTick; }; //================================================================================================== // 9Byte // ±âÁ¸ »ç¿ë ÁßÀÎ Timer Refactoring Áß... // À̰÷ Àú°÷¿¡ Èð¾îÁ® ÀÖ´Â ´Ù¾çÇÑ ÇüÅÂÀÇ Timerµéµµ Á¤¸®ÇÒ ¿¹Á¤ class ITimerBase_v01xx : public ITimeout_v01xx { public: enum eTIMER_CONTROL { #if __ITIMERBASE_VERSION_CRTL == 0x0100 CLEAR = 0x00000000, START = 0x40000000, STOP = 0x80000000, CONTROL_MASK = 0xC0000000, #elif __ITIMERBASE_VERSION_CRTL == 0x0110 START = 0x1, STOP = 0x0/*Toggle START*/, CONTROL_MASK = 0x1, #endif }; enum eTIMER_MODE { #if __ITIMERBASE_VERSION_CRTL == 0x0100 NONE = 0x00000000, ONETIME = 0x10000000, LOOP = 0x20000000, MODE_MASK = 0x30000000, #elif __ITIMERBASE_VERSION_CRTL == 0x0110 LOOP = 0x2, ONETIME = 0x0/*Toggle LOOP*/, MODE_MASK = 0x2, #endif }; #if __ITIMERBASE_VERSION_CRTL == 0x0100 static const DWORD INTERVAL_FIELD = 0x0FFFFFFF; // 268435455 static const DWORD CONTROL_FIELD = 0xF0000000; #elif __ITIMERBASE_VERSION_CRTL == 0x0110 static const DWORD CONTROL_FIELD = CONTROL_MASK|MODE_MASK; static const DWORD INTERVAL_FIELD = ~CONTROL_FIELD; // 4294967292 #endif ITimerBase_v01xx() : ITimeout_v01xx(), m_Interval(0) { ClearTimer(); } //================================================================================ // public: inline VOID ClearTimer() { Disabled(); SetInterval( 0 ); ClearControlField(); } inline VOID ResetTimer() { if( LOOP == GetTimerMode() ) { SetNextTimeoutByCurTickBased( GetInterval() ); return; } //case ONETIME: //case NONE: if( START == GetTimerControl() ) { Disabled(); SetTimerControl( STOP ); } else { SetNextTimeoutByCurTickBased( GetInterval() ); SetTimerControl( START ); } } inline BOOL Configure( eTIMER_MODE eMode, DWORD dwInterval, BOOL bStart = TRUE ) { switch( eMode ) { case ONETIME: case LOOP: SetInterval( dwInterval ); SetTimerMode( eMode ); SetTimerControl( STOP ); if( bStart ) StartTimer(); else StopTimer(); return TRUE; }; ClearTimer(); return FALSE; } inline VOID SetTimer( DWORD dwIntervalTime ) // ITimer Correspond Interface : auto LOOP timer { Configure( ITimerBase_v01xx::LOOP, dwIntervalTime ); } inline BOOL IsStarted() { return (BOOL)(START == GetTimerControl()); } inline BOOL IsStopped() { return (BOOL)(STOP == GetTimerControl()); } inline BOOL StartTimer() { if( IsStopped() ) { ResetTimer(); SetTimerControl( START ); return TRUE; } return FALSE; } inline VOID StopTimer() { ResetTimer(); SetTimerControl( STOP ); } inline BOOL ResumeTimer() { eTIMER_MODE eMode = GetTimerMode(); if( LOOP == eMode ) return StartTimer(); StopTimer(); return FALSE; } inline eTIMER_MODE GetTimerMode() { return (eTIMER_MODE)(MODE_MASK&m_Interval); } inline eTIMER_CONTROL GetTimerControl() { return (eTIMER_CONTROL)(CONTROL_MASK&m_Interval); } inline BOOL IsExpired() { BOOL bRet = (!IsStopped() && ITimeout_v01xx::IsExpired()); if( bRet ) ResetTimer(); return bRet; } inline DWORD GetInterval() { return INTERVAL_FIELD&m_Interval ; } inline VOID SetInterval( DWORD interval ) { #if __ITIMERBASE_VERSION_CRTL == 0x0100 m_Interval = (CONTROL_FIELD&m_Interval) | (INTERVAL_FIELD&interval) ; #elif __ITIMERBASE_VERSION_CRTL == 0x0110 const DWORD interval_ip = interval & (~CONTROL_FIELD); m_Interval = (CONTROL_FIELD&m_Interval) | ( interval&CONTROL_FIELD ? (interval_ip)+(CONTROL_FIELD+1) : (interval_ip) ) ; #endif } //================================================================================ // protected: inline VOID SetTimerMode( eTIMER_MODE eMode ) { m_Interval = (m_Interval&CONTROL_MASK) | (eMode&MODE_MASK) | GetInterval(); } inline VOID SetTimerControl( eTIMER_CONTROL eControl ) { m_Interval = (eControl&CONTROL_MASK) | (m_Interval&MODE_MASK) | GetInterval(); } inline VOID ClearControlField() { m_Interval = GetInterval(); } private: DWORD m_Interval; }; #pragma pack(pop) }}; //end of namespace //================================================================================================== //================================================================================================== //================================================================================================== #elif __ITIMERBASE_VERSION_CRTL == 0x0120 //================================================================================================== //================================================================================================== //================================================================================================== namespace util { namespace internal { #pragma pack(push) #pragma pack() //------------------------------------------------------------------------------ // () // - 09/12/12 : migration (version 0x0120->0x0121) // @name TimeBaseInfo // @code struct TimeBaseInfo { enum { }; enum eCtrl { eCtrl_Start = 0x1, // opp. Stop eCtrl_Stop = 0x0, eCtrl_Mask = 0x1, }; enum eMode { eMode_None = 0, eMode_ManualReset = 0, eMode_AutoReset = 2, // opp. ManualReset eMode_Mask = 2, }; static const ulong Version = 0x0121; static const ulong ControlField = eCtrl_Mask | eMode_Mask ; static const ulong IntervalField = ~ControlField; }; #pragma pack(pop) }}; //end of namespace //============================================================================== // @WxNote (util::ITimeout) // @Author : Waverix // @Date : 2008-12-04 // @Reference // @History // - 07/08/12 : version 0100 update // - 08/07/09 : version 0110 update, timeout interval bitfield modification //for ITimerBase // - 08/12/04 : migration (ITimeout -> Timeout) and revision // - 09/11/02 : change timeout_tick_ time accuracy (4ms>error) // - 09/12/12 : migrate Timeout to ITimeout for SUN utility (version 0x0120->0x0121) //============================================================================== namespace util { #pragma pack(push) #pragma pack() //------------------------------------------------------------------------------ // () // @name ITimeout // @brief // elapsed timer by 'IsExpired' // @code class ITimeout : public internal::TimeBaseInfo { public: static const ulong Version = 0x0121; static const ulong UNLIMITED = ULONG_MAX; static const ulong INSTANCE = 0; ITimeout(); // (Check) bool IsDisabled() const; bool IsExpired() const; // (Control Action) void Disabled(); void Instance(); // (timeout value control) void SetNextTimeout(ulong next_timeout); void SetNextTimeoutByCurTickBased(ulong interval); ulong GetTimeoutTicks() const; private: // spec. timeout_tick_count = timeout_tick_ << 2 // timeout_tick = (GetTickCount() + next_interval) >> 2; ulong timeout_tick_; }; //============================================================================== inline ITimeout::ITimeout() : timeout_tick_(UNLIMITED) { } // (Check) inline bool ITimeout::IsDisabled() const { return UNLIMITED == timeout_tick_; } inline bool ITimeout::IsExpired() const { ulong current = GetTickCount(); current >>= 2; if (timeout_tick_ < current) { return true; } return false; } // (Control Action) inline void ITimeout::Disabled() { timeout_tick_ = UNLIMITED; } inline void ITimeout::Instance() { timeout_tick_ = INSTANCE; } // (timeout value control) inline void ITimeout::SetNextTimeout(ulong next_timeout) { //if ((next_timeout & 3) == next_timeout) // next_timeout = 4; next_timeout >>= 2; timeout_tick_ = next_timeout; } inline void ITimeout::SetNextTimeoutByCurTickBased(ulong interval) { if ((interval & 3) == interval) { interval = 4; } interval >>= 2; ulong current = GetTickCount(); timeout_tick_ = (current >> 2) + interval; } inline ulong ITimeout::GetTimeoutTicks() const { return timeout_tick_ << 2; } #pragma pack(pop) }; //end of namespace //============================================================================== // @WxNote (util::ITimerBase) // @Author : waverix // @Date : 2008-12-04 // @Reference // @History // - 07/08/12 : version 0100 update // - 08/07/09 : version 0110 update, timeout interval bitfield modification for ITimerBase // - 08/12/04 : migration (ITimerBase -> TimerBase) and revision // - 09/11/02 : update to v0120, GetTickCount overflow tolerant algorithm // - 09/12/12 : migrate TimerBase to ITimerBase for SUN utility (version 0x0120->0x0121) //============================================================================== namespace util { #pragma pack(push) #pragma pack() //------------------------------------------------------------------------------ // () // @name ITimerBase // spec: 8 bytes object // @brief // elapsed timer by 'IsExpired' // @accuracy // min: 4ms // @code class ITimerBase : public internal::TimeBaseInfo { public: static const ulong Version = 0x0121; ITimerBase(); void Clear(); void Reset() const; bool SetTimer(ulong interval, bool start = true, bool auto_reset = true); // CHANGES: f110216.4L, add the interface to support cool time concept. void ChangeToInstantExpiration(); bool IsAutoReset() const; bool IsStarted() const; bool IsStopped() const; bool Start(); bool Stop(); bool Resume(); bool IsExpired() const; ulong GetRemainTicks() const; ulong GetTicks() const; ulong GetTimeoutTicks() const; ulong GetInterval() const; // interfaces to support a game timer float GetProgressRatio() const; ulong GetRemaindTime() const; ulong GetProcessTime() const; void SetInterval(ulong interval); protected: void ClearControlField(); private: #pragma warning(push) #pragma warning(disable:4201) union { ulong data_; struct { ulong is_start_ : 1; ulong is_auto_ : 1; // interval section : data >> 2 // interval : ((data >> 2) << 4) or (interval_ << 2) ulong interval_ : 30; }; }; #pragma warning(pop) ulong checked_; }; //============================================================================== inline ITimerBase::ITimerBase() : data_(0) , checked_(0) { } inline bool ITimerBase::IsAutoReset() const { return (is_auto_ != 0); } inline bool ITimerBase::IsStarted() const { return is_start_; } inline bool ITimerBase::IsStopped() const { return is_start_ == 0; } inline ulong ITimerBase::GetTicks() const { return checked_; } inline ulong ITimerBase::GetTimeoutTicks() const { const ulong next_timeout = checked_ + interval_; ulong modified = next_timeout << 2; if ((modified >> 2) == next_timeout) { return modified; } return ULONG_MAX; } inline ulong ITimerBase::GetInterval() const { ulong interval = interval_; return interval << 2; } inline void ITimerBase::SetInterval(ulong interval) { if ((interval & 3) == interval) { interval = 4; } interval >>= 2; interval_ = interval; } // interfaces to support a game timer inline ulong ITimerBase::GetRemaindTime() const { return GetRemainTicks(); } inline void ITimerBase::Clear() { // don't action anymore data_ = 0; // -> is_start_ == 0, is_auto_ == 0 checked_ = 0; }; inline void ITimerBase::Reset() const { // LOOP ¸ðµåÀÏ °æ¿ì ´ÙÀ½ ŸÀӾƿô ¼³Á¤, // INSTANCEÀÏ °æ¿ì´Â START ¿©ºÎ¿¡ µû¶ó¼­ ´Þ¸® ¼³Á¤µÊ. // eMode_AutoReset ? set next_timeout // instance -> variation setup by Start state if (is_auto_ || is_start_ == 0) { ulong current = GetTickCount(); const_cast(this)->checked_ = current >> 2; } else if (is_start_ != 0) { const_cast(this)->is_start_ = 0; } } // CHANGES: f110216.4L, add the interface to support cool time concept. inline void ITimerBase::ChangeToInstantExpiration() { checked_ = 0; } inline bool ITimerBase::Start() { if (is_start_) { return false; } Reset(); is_start_ = true; return true; } inline bool ITimerBase::Stop() { Reset(); is_start_ = false; return true; } inline bool ITimerBase::Resume() { if (is_auto_) { return Start(); } Stop(); return false; } inline void ITimerBase::ClearControlField() { data_ = (data_ >> 2) << 2; } #pragma pack(pop) }; //end of namespace //================================================================================================== //================================================================================================== //================================================================================================== #endif //__ITIMERBASE_VERSION_CRTL == 0x0120 //================================================================================================== //================================================================================================== //================================================================================================== //================================================================================================== //================================================================================================== //================================================================================================== #if __ITIMERBASE_VERSION_CRTL < 0x0120 typedef util::nsOldVer::ITimeout_v01xx ITimeout; typedef util::nsOldVer::ITimerBase_v01xx ITimerBase; #elif __ITIMERBASE_VERSION_CRTL == 0x0120 using util::ITimeout; using util::ITimerBase; #endif #endif //__UTILITY_ITIMEOUT_H_