// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ // // Timer.cpp // // Shared timer implementation. // // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- #include "concrtinternal.h" #pragma warning (disable : 4702) namespace Concurrency { namespace details { /// /// A stub class that is friends with _Timer in order to avoid pulling in too many windows.h definitions into agents.h. /// class _TimerStub { public: /// /// Timer callback for Vista and above (except MSDK) /// static void CALLBACK FireTimer(PTP_CALLBACK_INSTANCE, void* context, PTP_TIMER) { FireTimerXP(context, true); } /// /// Timer callback for XP and MSDK /// static void CALLBACK FireTimerXP(PVOID pContext, BOOLEAN) { _Timer* pTimer = reinterpret_cast<_Timer *>(pContext); pTimer->_Fire(); // Do not delete the timer - it will be deleted in the destructor } }; /// /// Constructs a new timer. /// /// /// The duration and period of the timer in milliseconds. /// /// /// An indication of whether the timer is repeating (periodic) or not. /// _Timer::_Timer(unsigned int _Ms, bool _FRepeating) : _M_hTimer(NULL) , _M_ms(_Ms) , _M_fRepeating(_FRepeating) { } /// /// Starts the timer. /// void _Timer::_Start() { if (_M_hTimer == NULL) { if ((_M_hTimer = RegisterAsyncTimerAndLoadLibrary(_M_ms, &_TimerStub::FireTimer, this, _M_fRepeating)) == nullptr) { throw std::bad_alloc(); } } } /// /// Destroys the timer. /// _Timer::~_Timer() { if (_M_hTimer != NULL) _Stop(); } /// /// Stops the timer. /// void _Timer::_Stop() { DeleteAsyncTimerAndUnloadLibrary(static_cast(_M_hTimer)); _M_hTimer = NULL; } } // namespace details /// /// Wait for a specified number of milliseconds /// _CONCRTIMP void __cdecl wait(unsigned int milliseconds) { if (milliseconds < 1) { Context::Yield(); } else { class TimerObj : public _Timer { public: TimerObj(unsigned int mS) : _Timer(mS, false) { m_pContext = Context::CurrentContext(); _Start(); Context::Block(); } private: virtual void _Fire() { m_pContext->Unblock(); } Context *m_pContext; } _t(milliseconds); } } } // namespace Concurrency