123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- /*
- This software is subject to the license described in the License.txt file
- included with this software distribution. You may not use this file except
- in compliance with this license.
- Copyright (c) Dynastream Innovations Inc. 2016
- All rights reserved.
- */
- #include "types.h"
- #include "dsi_timer.hpp"
- #include <stdio.h>
- //////////////////////////////////////////////////////////////////////////////////
- // Public Class Functions
- //////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////
- /*
- DSITimer::DSITimer()
- {
- }
- */
- DSITimer::DSITimer(DSI_THREAD_RETURN (*fnTimerFunc_)(void *), void *pvTimerFuncParameter_, ULONG ulInterval_, BOOL bRecurring_)
- {
- fnTimerFunc = fnTimerFunc_;
- pvTimerFuncParameter = pvTimerFuncParameter_;
- ulInterval = ulInterval_;
- bRecurring = bRecurring_;
- bClosing = FALSE;
- hTimerThread = (DSI_THREAD_ID)NULL;
- if (DSIThread_MutexInit(&stMutexCriticalSection) != DSI_THREAD_ENONE)
- {
- fnTimerFunc = (void*(*)(void*))NULL;
- return;
- }
- if (DSIThread_CondInit(&stCondTimerThreadExit) != DSI_THREAD_ENONE)
- {
- DSIThread_MutexDestroy(&stMutexCriticalSection);
- fnTimerFunc = (void*(*)(void*))NULL;
- return;
- }
- if (DSIThread_CondInit(&stCondTimerWait) != DSI_THREAD_ENONE)
- {
- DSIThread_MutexDestroy(&stMutexCriticalSection);
- DSIThread_CondDestroy(&stCondTimerThreadExit);
- fnTimerFunc = (void*(*)(void*))NULL;
- return;
- }
- hTimerThread = DSIThread_CreateThread(&DSITimer::TimerThreadStart, this);
- if (hTimerThread == NULL)
- {
- DSIThread_MutexDestroy(&stMutexCriticalSection);
- DSIThread_CondDestroy(&stCondTimerThreadExit);
- DSIThread_CondDestroy(&stCondTimerWait);
- fnTimerFunc = (void*(*)(void*))NULL;
- }
- }
- ///////////////////////////////////////////////////////////////////////
- DSITimer::~DSITimer()
- {
- if (hTimerThread)
- {
- DSIThread_MutexLock(&stMutexCriticalSection);
- bClosing = TRUE; //Set the exit flag
- DSIThread_CondSignal(&stCondTimerWait); //Wake up the timer thread early if it is "sleeping"
- if (fnTimerFunc != NULL) //This means the timer thread is still active
- {
- if (DSIThread_CondTimedWait(&stCondTimerThreadExit, &stMutexCriticalSection, 3000) != DSI_THREAD_ENONE)
- {
- // We were unable to stop the thread normally, so kill it.
- DSIThread_DestroyThread(hTimerThread);
- }
- }
- DSIThread_MutexUnlock(&stMutexCriticalSection);
- DSIThread_ReleaseThreadID(hTimerThread);
- hTimerThread = (DSI_THREAD_ID)NULL;
- DSIThread_MutexDestroy(&stMutexCriticalSection);
- DSIThread_CondDestroy(&stCondTimerThreadExit);
- DSIThread_CondDestroy(&stCondTimerWait);
- }
- }
- ///////////////////////////////////////////////////////////////////////
- BOOL DSITimer::NoError()
- {
- if ((fnTimerFunc != NULL) && (bClosing == FALSE)) //There was an error if the function pointer is set to NULL and we havent tried to close yet.
- return TRUE;
- return FALSE;
- }
- ///////////////////////////////////////////////////////////////////////
- DSI_THREAD_RETURN DSITimer::TimerThreadStart(void *pvParameter_)
- {
- DSITimer *This = (DSITimer *) pvParameter_;
- This->TimerThread();
- return 0;
- }
- ///////////////////////////////////////////////////////////////////////
- void DSITimer::TimerThread(void)
- {
- ULONG ulWaitTime;
- ULONG ulTargetTime = DSIThread_GetSystemTime();
- while(1) //We break on bClosing, but need to check it within the critical section
- {
- DSIThread_MutexLock(&stMutexCriticalSection);
- if (bClosing)
- {
- DSIThread_MutexUnlock(&stMutexCriticalSection);
- break;
- }
- ulTargetTime += ulInterval; //set the new target time
- ulWaitTime = ulTargetTime - DSIThread_GetSystemTime(); //figure out how long it is from now
- if (ulWaitTime && ulWaitTime < MAX_ULONG/2) //check if it we need to wait
- {
- if (DSIThread_CondTimedWait(&stCondTimerWait, &stMutexCriticalSection, ulWaitTime) != DSI_THREAD_ETIMEDOUT) //wait till our next interval
- {
- //If we get anything other than a timeout we will exit right away
- bClosing = TRUE;
- DSIThread_MutexUnlock(&stMutexCriticalSection);
- break;
- }
- }
- DSIThread_MutexUnlock(&stMutexCriticalSection);
- fnTimerFunc(pvTimerFuncParameter); //Call the timer interval function
- if (bRecurring == FALSE)
- bClosing = TRUE;
- }
- DSIThread_MutexLock(&stMutexCriticalSection);
- fnTimerFunc = (void*(*)(void*))NULL;
- DSIThread_CondSignal(&stCondTimerThreadExit); // Set an event to alert the main process that the timer thread is finished.
- DSIThread_MutexUnlock(&stMutexCriticalSection);
- }
|