/******************************************************************************* * LRTimer.h * * * * Written by Max Gurdziel 2005 under GNU General Public License * * contact me: max[at]remoteSOS[dot]com * * * * LRTimer is a low resolution timer class with own timing thread. It allows * * an external callback function to be supplied that will be called in * * pre-defined time intervals. * * The smallest timer interval you can use is 1ms. * * * * Tested with gcc mingw & Visual C++ 6.0 under WindowsXP Home and Pro * * * * * * LRTimer timer; // define LRTimer object * * timer.setInterval(100); // set interval of 100ms * * timer.setCallbackProc(&myCallbackFunction, 0); // set callback function * * // it's prototype is: * * // void myCallbackFunction(void* pParam); * * * * timer.start(); // start the timer * * .... * * timer.stop(); // stops the timer * * .... * * timer.start(200); // starts timer with new interval * * * * * * Example code: * * Copy and paste below sample code to test LRTimer * * * ________________________________________________________________________________
#include <stdlib.h> #include "LRTimer.h"
// define callback function // static void myCallback(void* data) { static DWORD cnt = 0; char c; cnt++; switch (cnt % 4) { case 0: c = '|'; break; case 1: c = '/'; break; case 2: c = '-'; break; case 3: c = '\'; } printf("b%c",c); }
int main(int argc, char *argv[]) { LRTimer lrt; lrt.setCallbackProc(&myCallback, NULL); // set the callback function by reference lrt.setInterval(50); // set delay interval in miliseconds lrt.start(); // start the timer getchar(); // let it run for a while - press Enter lrt.stop(); // stop the timer getchar(); // wait to show it's stopped - Enter lrt.start(200); // start with different delay getchar(); lrt.stop(); system("PAUSE"); return 0; }
________________________________________________________________________________ * * * Permission to use, copy, modify, and distribute this software and its * * documentation under the terms of the GNU General Public License is hereby * * granted. No representations are made about the suitability of this software * * for any purpose. It is provided "as is" without express or implied warranty. * * See http://www.gnu.org/copyleft/gpl.html for more details. * * * * All I ask is that if you use LRTimer in your project retain the * * copyright notice. If you have any comments and suggestions please email me * * max[at]remoteSOS[dot]com * * * *******************************************************************************/
#ifndef LRTIMER_H__ #define LRTIMER_H__
#ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0500 #endif
// compile with: /MT /D "_X86_" /c // processor: x86
#include <windows.h> #include <process.h> /* _beginthread, _endthread */ #include <stdio.h> #include <assert.h>
// define a second in terms of 100ns - used with waitable timer API #define _SECOND 10000
typedef VOID (*LRTCallbackEventProc)(VOID*);
class LRTimer { public: // default constructor with 1 second interval LRTimer(DWORD dwInterval=1000);
// default destructor ~LRTimer(); // starts timer by creating new thread. interval must be set earlier VOID start(); // starts timer with given interval in miliseconds VOID start(DWORD _interval_ms); // stops the timer VOID stop(); // sets time interval in miliseconds VOID setInterval(DWORD _interval_ms); // returns time interval in ms DWORD getInterval(); // sets function that will be called on time expiration VOID setCallbackProc( LRTCallbackEventProc pcbEventProc, VOID* pcbParam );
// returns true if LRtimer is currently running BOOL isRunning();
// It should be used if the worker class will use CRT functions static HANDLE CrtCreateThread(LPSECURITY_ATTRIBUTES lpsa, DWORD dwStackSize, LPTHREAD_START_ROUTINE pfnThreadProc, void *pvParam, DWORD dwCreationFlags, DWORD *pdwThreadId) throw() { // sanity check for pdwThreadId assert(sizeof(DWORD) == sizeof(unsigned int));
// _beginthreadex calls CreateThread which will set the last error value before it returns return (HANDLE) _beginthreadex(lpsa, dwStackSize, (unsigned int (__stdcall *)(void *)) pfnThreadProc, pvParam, dwCreationFlags, (unsigned int *) pdwThreadId); }
private: DWORD m_dwInterval; // interval between alarms
LRTCallbackEventProc m_pCallback; // pointer to user callback function VOID *m_pcbParam; // pointer to user callback parameter
BOOL m_bRunning; // timer running state HANDLE m_hTimerThread; // handle to timer thread DWORD m_iID; // timer thread id - added for compatibility with Win95/98
// timer clocking tread runtine virtual DWORD WINAPI timerThread();
// wrapper to thread runtine so it can be used within a class static DWORD WINAPI timerThreadAdapter(PVOID _this) { return ((LRTimer*) _this)->timerThread(); }
// timer callback APC procedure called when timer is signaled virtual VOID CALLBACK TimerAPCProc(LPVOID, DWORD, DWORD);
// wrapper to callback APC procedure so it can be used within a class static VOID CALLBACK TimerAPCProcAdapter(PVOID _this, DWORD a1=0, DWORD a2=0) { ((LRTimer*) _this)->TimerAPCProc( NULL, a1, a2 ); } };
#endif
/******************************************************************************* * LRTimer.cpp * * * * Written by Max Gurdziel 2005 under GNU General Public License * * contact me: max[at]remoteSOS[dot]com * * * * LRTimer is a low resolution timer class with own timing thread. It allows * * an external callback function to be supplied that will be called in * * pre-defined time intervals. The smallest timer interval you can use is 1ms. * * * * See header file for more info, usage information and example * * * * * * * * Permission to use, copy, modify, and distribute this software and its * * documentation under the terms of the GNU General Public License is hereby * * granted. No representations are made about the suitability of this software * * for any purpose. It is provided "as is" without express or implied warranty. * * See http://www.gnu.org/copyleft/gpl.html for more details. * * * * All I ask is that if you use LRTimer in your project you retain the * * copyright notice. If you have any comments and suggestions please email me * * max[at]remoteSOS[dot]com * * * * 2008-6-23 Modified by ZhangLiang * * * *******************************************************************************/ #include "stdafx.h"
#include "LRTimer.h"
#ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0500 #endif
LRTimer::LRTimer(DWORD dwInterval): m_dwInterval(dwInterval), m_bRunning(FALSE), m_pCallback(NULL), m_pcbParam(NULL), m_hTimerThread(0) {}
LRTimer::~LRTimer() {}
VOID CALLBACK LRTimer::TimerAPCProc(LPVOID, DWORD, DWORD) { // call custom callback function if (NULL != m_pCallback) (*m_pCallback)(m_pcbParam);
#ifdef _DEBUG else printf("No callback function setn"); #endif }
DWORD WINAPI LRTimer::timerThread() { HANDLE hTimer; BOOL bSuccess; LARGE_INTEGER liDueTime; CHAR szError[255];
CHAR szTimerName[16]; sprintf_s(szTimerName, "LRT_%x", (DWORD)(DWORD_PTR)this); if ( hTimer = CreateWaitableTimerA( NULL, FALSE, szTimerName ) ) liDueTime.QuadPart=-(LONGLONG)m_dwInterval * _SECOND;
bSuccess = SetWaitableTimer( hTimer, // Handle to the timer object &liDueTime, // When timer will become signaled first time m_dwInterval, // Periodic timer interval TimerAPCProcAdapter, // Completion routine this, // Argument to the completion routine FALSE ); // Do not restore a suspended system if ( bSuccess ) { while (m_bRunning) SleepEx(1, TRUE); // SleepEx(0, TRUE) consumes 100% CPU usage CancelWaitableTimer(hTimer); } else { wsprintfA( szError, "SetWaitableTimer failed with Error %d.", GetLastError() ); #ifdef _DEBUG MessageBoxA( NULL, szError, "Error", MB_ICONEXCLAMATION ); #endif return 1; } CloseHandle(hTimer); return 0; }
VOID LRTimer::start() { m_bRunning = TRUE;
if (m_hTimerThread != 0) stop();
#ifndef _INC_CRTDEFS m_hTimerThread = CreateThread(NULL, 0, timerThreadAdapter, this, 0, &m_iID); #else m_hTimerThread = CrtCreateThread(NULL, 0, timerThreadAdapter, this, 0, &m_iID); #endif
if (m_hTimerThread == NULL) { #ifdef _DEBUG printf( "CreateThread failed (%d)n", GetLastError() ); #endif return; } }
VOID LRTimer::start(DWORD _interval_ms) { setInterval(_interval_ms); start(); }
VOID LRTimer::stop() { m_bRunning = FALSE; CloseHandle(m_hTimerThread); m_hTimerThread = 0; }
VOID LRTimer::setInterval(DWORD _interval_ms) { m_dwInterval = _interval_ms; }
DWORD LRTimer::getInterval() { return m_dwInterval; }
VOID LRTimer::setCallbackProc( LRTCallbackEventProc pcbEventProc, VOID* pcbParam) { m_pCallback = pcbEventProc; m_pcbParam = pcbParam; }
BOOL LRTimer::isRunning() { return m_bRunning; }
|