// // Copyright @ 2014 Hangzhou Topzen Ltd. // Author: Tang (tang@hztopzen.com) @ 2014-12 // #ifndef __ACTION_H #define __ACTION_H #include "BaseTypes.h" #include "BaseHeaders.h" #include "Thread.h" #include "Logger.h" namespace tzc { typedef TZ_Uint64 ActionTime; typedef TZ_Uint64 ActionTick; typedef TZ_Int32 (* ActionCallback) (void * pData); class DECLDLL Action { public: Action(const std::string & sName = "Action"); ~Action(); enum __ACTION_STATE { STATE_INVALID, STATE_WAITING, // waiting to be scheduled STATE_SCHEDULED, // active, will execute soon STATE_NOTSCHEDULED, // initialized state, nothing to do STATE_POLL_WAITING, // has been polled, next will be active STATE_TOBEDELETED, STATE_UNKNOWN }; typedef enum __ACTION_STATE State; void Execute(); void Reset(); void Wait4Detachable(); void SetDetachable(bool flag); bool GetDetachable() const; void SetProcessor(ActionCallback callback, void * pData); void SetState(const State eState); State GetState() const; void SetSchedTick(const ActionTick iTick); ActionTick GetSchedTick() const; void SetDelayTicks(const ActionTick iTicks); ActionTick GetDelayTicks() const; const std::string & Name() const; private: volatile State m_eState; volatile bool m_bDetachable; ActionTick m_tickSched; // when to be scheduled ActionTick m_tickDelay; // when to be waked up void * m_pData; ActionCallback m_callback; std::string m_sName; }; // // inlines // inline void Action::Execute() { m_callback(m_pData); } inline void Action::SetDetachable(bool flag) { m_bDetachable = flag; } inline bool Action::GetDetachable() const { return m_bDetachable; } inline void Action::SetProcessor(ActionCallback callback, void * pData) { m_callback = callback; m_pData = pData; } inline void Action::SetState(const State eState) { m_eState = eState; } inline Action::State Action::GetState() const { return m_eState; } inline void Action::SetSchedTick(const ActionTick iTick) { m_tickSched = iTick; } inline ActionTick Action::GetSchedTick() const { return m_tickSched; } inline void Action::SetDelayTicks(const ActionTick iTicks) { m_tickDelay = iTicks; } inline ActionTick Action::GetDelayTicks() const { return m_tickDelay; } inline const std::string & Action::Name() const { return m_sName; } } // namespace tzc #include "Locks.h" namespace tzc { class DECLDLL ActionMgr : public OSThread { #ifdef ACTION_SINGLETON private: ActionMgr(); virtual ~ActionMgr(); #else public: ActionMgr(TZ_Int32 iResolution = 250, TZ_Uint32 iMaxLoops = 1); virtual ~ActionMgr(); #endif public: #ifdef ACTION_SINGLETON static ActionMgr * Instance(); static void DestroyInstance(); #endif void Initialize(); void Poll(); void Schedule(Action * pAction); void ScheduleHead(Action * pAction); void DeleteAction(Action * pAction); void NewAction(Action * pAction, ActionTime timeout); TZ_Int32 ModActionTime(Action * pAction, ActionTime newTimeout); void SetResolution(const TZ_Int32 iResolution); TZ_Int32 GetResolution() const; void SetMaxLoops(const TZ_Uint32 iMax); TZ_Uint32 GetMaxLoops() const; void SetCompInterval(const TZ_Uint32 interval); TZ_Uint32 GetCompInterval() const; protected: virtual void Entry(); private: ActionTick actionTime2Ticks(const ActionTime atime); ActionTick actionTickDiff(const Action * pAction, const ActionTick currentTick); void checkAction(const ActionTick currentTick); TZ_BOOL isTickAfter(const ActionTick tick1, const ActionTick tick2); TZ_Int32 findAndEraseAction(std::list & rActionList, const Action * pAction); void scheduleImp(Action * pAction, ActionTime time2Sched, const TZ_BOOL bHead = FALSE); private: std::list m_listPend; std::list m_listPoll; std::list m_listActive; volatile TZ_BOOL m_bInProgress; volatile TZ_Uint32 m_iSchedLoops; ActionTick m_atPreTicks; ActionTick m_atTicks; TZ_Int32 m_iResolution; // in milliseconds TZ_Uint32 m_iMaxLoops; TZ_Uint32 m_iCompInterval; // resolution compensate interval Mutex m_mtxLock; #ifdef ACTION_SINGLETON private: static Mutex _mutex; static ActionMgr * _instance; #endif }; // // inlines // inline void ActionMgr::SetResolution(const TZ_Int32 iResolution) { m_iResolution = iResolution; } inline TZ_Int32 ActionMgr::GetResolution() const { return m_iResolution; } inline void ActionMgr::SetMaxLoops(const TZ_Uint32 iMax) { m_iMaxLoops = iMax; } inline TZ_Uint32 ActionMgr::GetMaxLoops() const { return m_iMaxLoops; } inline void ActionMgr::SetCompInterval(const TZ_Uint32 interval) { m_iCompInterval = interval; } inline TZ_Uint32 ActionMgr::GetCompInterval() const { return m_iCompInterval; } inline ActionTick ActionMgr::actionTime2Ticks(const ActionTime atime) { return (atime / m_iResolution); } // check whether tick1 > tick2 or not inline TZ_BOOL ActionMgr::isTickAfter(const ActionTick tick1, const ActionTick tick2) { return !((tick1 - tick2) & (1ULL << 63)); } #ifdef ACTION_SINGLETON #define ACTION_RESOLUTION ActionMgr::Instance()->GetResolution() #define ACTION_MAXLOOPS ActionMgr::Instance()->GetMaxLoops() #define ACTION_EVENTLOOP() ActionMgr::Instance()->Poll() #endif } // namespace tzc #endif /* ----- #ifndef __ACTION_H ----- */