CComponentsTimer: rework timer class

Origin commit data
------------------
Commit: 4904279fd5
Author: Thilo Graf <dbt@novatux.de>
Date: 2016-04-25 (Mon, 25 Apr 2016)
This commit is contained in:
2016-04-25 10:26:32 +02:00
parent 7211a3e7fa
commit f5932d9cd8
5 changed files with 144 additions and 61 deletions

View File

@@ -316,15 +316,15 @@ bool CComponentsFrmClock::startClock()
} }
if (cl_timer == NULL){ if (cl_timer == NULL){
cl_timer = new CComponentsTimer(); cl_timer = new CComponentsTimer(0);
if (cl_timer->OnTimer.empty()){ if (cl_timer->OnTimer.empty()){
dprintf(DEBUG_INFO,"\033[33m[CComponentsFrmClock]\t[%s] init slot...\033[0m\n", __func__); dprintf(DEBUG_INFO,"\033[33m[CComponentsFrmClock]\t[%s] init slot...\033[0m\n", __func__);
cl_timer->OnTimer.connect(cl_sl); cl_timer->OnTimer.connect(cl_sl);
} }
} }
cl_timer->setTimerIntervall(cl_interval); cl_timer->setTimerInterval(cl_interval);
if (cl_timer->isRun()) if (cl_timer->startTimer())
return true; return true;
return false; return false;

View File

@@ -147,7 +147,7 @@ class CComponentsFrmClock : public CComponentsForm, public CCTextScreen
///returns true, if clock is running ///returns true, if clock is running
virtual bool isRun() const {return cl_timer ? true : false;}; virtual bool isRun() const {return cl_timer ? true : false;};
///set refresh interval in seconds, default value=1 (=1 sec) ///set refresh interval in seconds, default value=1 (=1 sec)
virtual void setClockIntervall(const int& seconds){cl_interval = seconds;}; virtual void setClockInterval(const int& seconds){cl_interval = seconds;};
///show clock on screen ///show clock on screen
virtual void paint(bool do_save_bg = CC_SAVE_SCREEN_YES); virtual void paint(bool do_save_bg = CC_SAVE_SCREEN_YES);

View File

@@ -3,7 +3,7 @@
Copyright (C) 2001 by Steffen Hehn 'McClean' Copyright (C) 2001 by Steffen Hehn 'McClean'
Generic Timer. Generic Timer.
Copyright (C) 2013, Thilo Graf 'dbt' Copyright (C) 2013-2016, Thilo Graf 'dbt'
License: GPL License: GPL
@@ -36,66 +36,72 @@
using namespace std; using namespace std;
CComponentsTimer::CComponentsTimer( const int& interval) CComponentsTimer::CComponentsTimer(const int& interval)
{ {
tm_thread = 0; tm_thread = 0;
tm_interval = interval; tm_interval = interval;
sl_stop_timer = sigc::mem_fun(*this, &CComponentsTimer::stopTimer);
sl = sigc::mem_fun(*this, &CComponentsTimer::stopTimer);
if (interval > 0) if (interval > 0)
startTimer(); startTimer();
} }
CComponentsTimer::~CComponentsTimer() CComponentsTimer::~CComponentsTimer()
{ {
if (stopTimer()) stopTimer();
dprintf(DEBUG_INFO,"[CComponentsTimer] [%s] timer stopped\n", __func__); }
void CComponentsTimer::runSharedTimerAction()
{
//start loop
while(tm_enable && tm_interval > 0) {
tm_mutex.lock();
OnTimer();
mySleep(tm_interval);
tm_mutex.unlock();
}
if (tm_thread)
stopThread();
} }
//thread handle //thread handle
void* CComponentsTimer::initTimerThread(void *arg) void* CComponentsTimer::initThreadAction(void *arg)
{ {
CComponentsTimer *timer = static_cast<CComponentsTimer*>(arg); CComponentsTimer *timer = static_cast<CComponentsTimer*>(arg);
//start loop timer->runSharedTimerAction();
while(timer) {
timer->mutex.lock();
timer->OnTimer();
timer->mutex.unlock();
mySleep(timer->tm_interval);
}
return 0; return 0;
} }
//start up running timer with own thread, return true on succses //start up running timer with own thread, return true on succses
bool CComponentsTimer::startTimer() void CComponentsTimer::initThread()
{ {
void *ptr = static_cast<void*>(this); if (!tm_enable)
return;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,0);
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS,0);
if(!tm_thread) { if(!tm_thread) {
int res = pthread_create (&tm_thread, NULL, initTimerThread, ptr) ; void *ptr = static_cast<void*>(this);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,0);
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS,0);
int res = pthread_create (&tm_thread, NULL, initThreadAction, ptr);
if (res != 0){ if (res != 0){
dprintf(DEBUG_NORMAL,"\033[33m[CComponentsTimer] [%s - %d] ERROR! pthread_create\033[0m\n", __func__, __LINE__); dprintf(DEBUG_NORMAL,"\033[33m[CComponentsTimer] [%s - %d] ERROR! pthread_create\033[0m\n", __func__, __LINE__);
return false; return;
}
if (res == 0){
if (!sl.empty()){
dprintf(DEBUG_INFO,"\033[33m[CComponentsTimer] [%s - %d] timer thread [%lu] created with interval = %d\033[0m\n", __func__, __LINE__, pthread_self(), tm_interval);
CNeutrinoApp::getInstance()->OnBeforeRestart.connect(sl);
}
}else{
dprintf(DEBUG_NORMAL, "\033[33m[CComponentsTimer] [%s - %d] ERROR! pthread_create\033[0m\n", __func__, __LINE__);
} }
if (res == 0)
CNeutrinoApp::getInstance()->OnBeforeRestart.connect(sl_stop_timer);
} }
return true;
} }
//stop ticking timer and kill thread, return true on succses void CComponentsTimer::stopThread()
bool CComponentsTimer::stopTimer()
{ {
if(tm_thread) { if(tm_thread) {
int thres = pthread_cancel(tm_thread); int thres = pthread_cancel(tm_thread);
@@ -109,14 +115,37 @@ bool CComponentsTimer::stopTimer()
if (thres == 0){ if (thres == 0){
tm_thread = 0; tm_thread = 0;
dprintf(DEBUG_INFO,"\033[33m[CComponentsTimer] [%s] timer thread terminated ...\033[0m\n", __func__);
//ensure disconnect of unused slot //ensure disconnect of unused slot
if (!sl.empty()){ while (!sl_stop_timer.empty())
dprintf(DEBUG_INFO,"\033[33m[CComponentsTimer][%s] disconnect timer slot ...\033[0m\n", __func__); sl_stop_timer.disconnect();
sl.disconnect();
}
return true;
} }
} }
}
bool CComponentsTimer::startTimer()
{
tm_enable = true;
initThread();
if(tm_thread)
return true;
return false; return false;
} }
bool CComponentsTimer::stopTimer()
{
tm_enable = false;
stopThread();
if(tm_thread == 0)
return true;
return false;
}
void CComponentsTimer::setTimerInterval(const int& seconds)
{
if (tm_interval == seconds)
return;
tm_interval = seconds;
}

View File

@@ -34,42 +34,96 @@
#include <OpenThreads/Thread> #include <OpenThreads/Thread>
#include <OpenThreads/Condition> #include <OpenThreads/Condition>
//! Member of CComponents. Provides a generic timer class /**CComponentsTimer
/*! * Member of CComponents. Provides a generic timer class
* @see
* CComponentsTimer()
*/ */
class CComponentsTimer : public sigc::trackable class CComponentsTimer : public sigc::trackable
{ {
private: private:
///thread ///thread
pthread_t tm_thread; pthread_t tm_thread;
///refresh interval in seconds ///refresh interval in seconds
int tm_interval; int tm_interval;
///init function to start timer in own thread
static void* initTimerThread(void *arg);
///mutex for timer
OpenThreads::Mutex mutex;
///slot for signals
sigc::slot0<bool> sl;
///init function to init shared timer action
static void* initThreadAction(void *arg);
///init function to start/stop timer in own thread
void initThread();
void stopThread();
///runs shared timer action provided inside OnTimer() signal
void runSharedTimerAction();
///flag to control thread state
bool tm_enable;
///mutex for timer
OpenThreads::Mutex tm_mutex;
///slot for restart signals
sigc::slot0<bool> sl_stop_timer;
public: public:
///class constructor, parameter interval sets the interval in seconds, default value=1 (1 sec) /**Constructor for timer class
*
* @param[in] interval
* @li int interval in seconds, default value=1 (1 sec)
* If init value for interval > 0, timer starts immediately
* @see
* setTimerInterval();
*/
CComponentsTimer(const int& interval = 1); CComponentsTimer(const int& interval = 1);
~CComponentsTimer(); ~CComponentsTimer();
///start timer thread, returns true on success, if false causes log output /**Starts timer thread
* @return
* bool
* returns true, if timer is running in thread
* @see
* stopTimer()
*/
bool startTimer(); bool startTimer();
///stop timer thread, returns true on success, if false causes log output
/**Stops timer thread
* @return
* bool
* returns true, if timer thread stopped
* @see
* startTimer()
*/
bool stopTimer(); bool stopTimer();
///returns true, if timer is running in thread /**get current timer status
* @return
* bool
* returns true, if timer is running in thread
* @see
* startTimer()
* stopTimer()
*/
bool isRun() const {return tm_thread;}; bool isRun() const {return tm_thread;};
///set another interval in seconds
void setTimerIntervall(const int& seconds){tm_interval = seconds;};
///signal for timer event, use this in your class where ever you need time controled actions /**set interval in seconds
///for more details see also CComponentsSignals for similar handlings * @param[in] seconds
* @li int
* @return
* void
* @see
* tm_interval
*/
void setTimerInterval(const int& seconds);
/**Provides a signal handler to receive any function or methode.
* Use this in your class where ever you need time controled actions.
*
* @param[in] seconds
* @li int
* @see
* CComponentsSignals for similar handlings.
* CComponentsFrmClock::startClock()
*/
sigc::signal<void> OnTimer; sigc::signal<void> OnTimer;
}; };

View File

@@ -679,7 +679,7 @@ int CTestMenu::exec(CMenuTarget* parent, const std::string &actionKey)
if (clock_r == NULL){ if (clock_r == NULL){
clock_r = new CComponentsFrmClock(100, 50, NULL, "%H.%M:%S", NULL, true); clock_r = new CComponentsFrmClock(100, 50, NULL, "%H.%M:%S", NULL, true);
clock_r->setClockFont(g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_CHANNAME]); clock_r->setClockFont(g_Font[SNeutrinoSettings::FONT_TYPE_INFOBAR_CHANNAME]);
clock_r->setClockIntervall(1); clock_r->setClockInterval(1);
// clock_r->doPaintBg(false); // clock_r->doPaintBg(false);
} }