These days I am trying to implement a digital clock thread using C++ in my embedded linux platform, its kernel version is 2.4. My purpose is to display a clock at the corner of OSD page, of course it will change its time every second.
We use class gui object to draw OSD UI and currently our implementation is below:
Code:
class gui
{
public:
void Start_timer_thread()
{
pthread_t clock_thread_id;
int ret = -1;
/* create an external thread to deal with it */
ret = pthread_create(&clock_thread_id, NULL, gui::digital_clock_thread, this);
if (ret != 0)
{
fprintf (stderr, "Cannot spawn thread. err = %d\n", ret);
return RM_ERROR;
}
}
static void* digital_clock_thread(void *ptr)
{
/*
* Since it shoud be a static function according to C++ designing principle,
* we need to do static cast in order to use the following non-static functions
* and variables, it seems be a common thread to use in this occasion, I will learn
* it from linuxquestion and thanks very much.
*
**/
(static_cast<gui*>(ptr))->real_digital_clock_thread();
return NULL;
}
void real_digital_clock_thread()
{
RMuint32 page_id = 0;
RMstatus status = RM_ERROR;
struct sigaction new_act, old_act;
struct itimerval itv, oldtv;
/*
* Using sigaction instead of signal in order that signal handler can be restored.
*
**/
/* signal(SIGALRM, SigAlarmHandler); */
new_act.sa_handler = SigAlarmHandler;
sigaction(SIGALRM, &new_act, &old_act);
/* set time interval */
itv.it_interval.tv_sec = 1;
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = 1;
itv.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &itv, &oldtv);
while (1)
{
if(thread_exit_flag)
{
/* it has changed to another page */
signal(SIGALRM, old_act.sa_handler);
exit(0);
}
pause();
}
}
static void SigAlarmHandler(int signal)
{
/*
* I try to use the former method to do non-static cast, but compiling error.
* For static function, it doesn't have idea of this pointer, it is globle.
*
**/
/* SigAlarmHandler_StaticCast(this); */
/* (static_cast<gui*>(this))->real_SigAlarmHandler(); */
this->real_SigAlarmHandler();
}
void SigAlarmHandler_StaticCast(gui* ptr)
{
(static_cast<gui*>(ptr))->real_SigAlarmHandler();
}
void real_SigAlarmHandler()
{
time_t t;
struct tm *st;
time(&t);
printf("timer signal..\n");
st = localtime(&t);
/*
* there are many non static functions and variables which are already existed and I want to use them
* to draw on OSD.
*/
draw_timer_numbers_on_OSD(st);
}
private:
void draw_timer_numbers_on_OSD(struct tm *st)
{
printf("class gui. draw_timer_numbers_on_OSD.....\n");
......
}
};
Thanks for your patient to read over my source code. Inside source code it includes my design principle and my whole program structure, also my difficulty which compiling error, signal handler function is static, but I want to use those non static functions and variables to draw on OSD. This is my troublesome and what do I turn for help. Thanks very much in advance.
I have also tried the following methods to accomplish my goal.
1. Since in current step I am trying to find a non-static function to do signal dealing with issue, manage to implement its signal handler out of class gui, using "extern "C" to write a global function, but the problem is that in this function we can't use the methods and variables inside class gui or if you know how to use it, please let me know and thanks very much in advance.
2. Search in google and find that it is possible to change signal to expection and then to catch it. It seems some difficult and don't know whether it is really workable.
3. Instead of using signal SIGALRM and its signal handler difficult, we try to use sleep function, sleep 1 second every time and then to update timer, you know uClinux isn't real time and drawing liquid timer number will be also need some time, after all it is embedded, so its precision is also not good.
I am not very good at C++ programming, maybe this program can be solved out nicely on my current program design framework, or I need to rewrite it completely. Please give me some advise and discussion are also welcome.
Thanks very much for your entire kind patient.