- /*******************************************************************************
- * 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 set/n");
- #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;
- }