mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2025-12-14 16:34:49 +08:00
optimize and cleanup the timer module to fix the bad update of tick counter
This commit is contained in:
@@ -258,7 +258,7 @@ struct _MSGQUEUE
|
||||
int loop_depth; // message loop depth, for dialog boxes
|
||||
|
||||
int idle_counter; // the idle connter for MSG_IDLE
|
||||
DWORD last_ticks_desktop; // the last tick count for desktop timer
|
||||
DWORD last_ticks; // the last tick count saved; since 5.0.14
|
||||
|
||||
/* Since 5.0.0, MiniGUI provides support for timers per message thread */
|
||||
int nr_timers; // the number of active timers
|
||||
|
||||
@@ -74,7 +74,7 @@ typedef struct _MSGQUEUE MSGQUEUE;
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void __mg_update_tick_count (void* data);
|
||||
DWORD __mg_update_tick_count (MSGQUEUE* msg_queue);
|
||||
int __mg_check_expired_timers (MSGQUEUE* msg_queue, DWORD inter);
|
||||
void __mg_remove_timers_by_msg_queue (MSGQUEUE* msg_queue);
|
||||
void __mg_remove_timer (MSGQUEUE* msg_queue, int slot);
|
||||
|
||||
@@ -145,7 +145,7 @@ static IDLEHANDLER std_idle_handler;
|
||||
|
||||
static BOOL idle_handler_for_desktop_thread (MSGQUEUE *msg_queue, BOOL wait)
|
||||
{
|
||||
__mg_update_tick_count (NULL);
|
||||
__mg_update_tick_count (msg_queue);
|
||||
return std_idle_handler (msg_queue, wait);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
* <http://www.minigui.com/blog/minigui-licensing-policy/>.
|
||||
*/
|
||||
/*
|
||||
** timer.c: The Timer module for MiniGUI-Threads.
|
||||
** timer.c: The Timer module for MiniGUI.
|
||||
**
|
||||
** Current maintainer: Wei Yongming.
|
||||
**
|
||||
@@ -79,139 +79,44 @@
|
||||
|
||||
DWORD __mg_tick_counter = 0;
|
||||
|
||||
/* update timer count for desktop thread */
|
||||
void __mg_update_tick_count (void *data)
|
||||
/* update timer count for message and desktop thread */
|
||||
DWORD __mg_update_tick_count (MSGQUEUE* msg_queue)
|
||||
{
|
||||
DWORD ticks;
|
||||
|
||||
#if defined(_MGRM_PROCESSES)
|
||||
if (mgIsServer) {
|
||||
__mg_tick_counter = __mg_os_get_time_ticks ();
|
||||
SHAREDRES_TIMER_COUNTER = __mg_tick_counter;
|
||||
ticks = __mg_os_get_time_ticks ();
|
||||
SHAREDRES_TIMER_COUNTER = ticks;
|
||||
}
|
||||
else {
|
||||
__mg_tick_counter = SHAREDRES_TIMER_COUNTER;
|
||||
ticks = SHAREDRES_TIMER_COUNTER;
|
||||
}
|
||||
#else /* defined _MGRM_PROCESSES */
|
||||
__mg_tick_counter = __mg_os_get_time_ticks ();
|
||||
ticks = __mg_os_get_time_ticks ();
|
||||
#endif /* not defined _MGRM_PROCESSES */
|
||||
|
||||
/* Since 5.0.0, the desktop only handles caret blinking in MSG_TIMEOUT
|
||||
message, and the interval for the timer of desktop changes to 0.05s. */
|
||||
if (__mg_tick_counter >
|
||||
__mg_dsk_msg_queue->last_ticks_desktop + DESKTOP_TIMER_INERTVAL) {
|
||||
__mg_dsk_msg_queue->dwState |= QS_DESKTIMER;
|
||||
if (msg_queue && ticks != msg_queue->last_ticks) {
|
||||
/* Since 5.0.0, the desktop only handles caret blinking in MSG_TIMEOUT
|
||||
message, and the interval for the timer of desktop changes to 0.05s.
|
||||
*/
|
||||
if (msg_queue == __mg_dsk_msg_queue) {
|
||||
if (ticks > __mg_dsk_msg_queue->last_ticks +
|
||||
DESKTOP_TIMER_INERTVAL) {
|
||||
__mg_dsk_msg_queue->dwState |= QS_DESKTIMER;
|
||||
#ifdef _MGRM_THREADS /* only wake up desktop for threads mode */
|
||||
POST_MSGQ (__mg_dsk_msg_queue);
|
||||
POST_MSGQ (__mg_dsk_msg_queue);
|
||||
#endif
|
||||
__mg_dsk_msg_queue->last_ticks_desktop = __mg_tick_counter;
|
||||
}
|
||||
}
|
||||
|
||||
msg_queue->last_ticks = ticks;
|
||||
}
|
||||
|
||||
#if 0 /* deprecated code */
|
||||
#if defined(_MGRM_PROCESSES)
|
||||
if (mgIsServer) {
|
||||
DWORD elapsed_ticks;
|
||||
|
||||
/* Since 5.0.0, we use elapsed time in ms to count the ticks */
|
||||
elapsed_ticks = __mg_os_get_elapsed_ms ();
|
||||
elapsed_ticks = (elapsed_ticks + 5) / 10;
|
||||
|
||||
__mg_tick_counter += elapsed_ticks;
|
||||
SHAREDRES_TIMER_COUNTER = __mg_tick_counter;
|
||||
}
|
||||
else {
|
||||
__mg_tick_counter = SHAREDRES_TIMER_COUNTER;
|
||||
}
|
||||
#else /* defined _MGRM_PROCESSES */
|
||||
DWORD elapsed_ticks;
|
||||
|
||||
/* Since 5.0.0, we use elapsed time in ms to count the ticks */
|
||||
elapsed_ticks = __mg_os_get_elapsed_ms ();
|
||||
elapsed_ticks = (elapsed_ticks + 5) / 10;
|
||||
__mg_tick_counter += elapsed_ticks;
|
||||
#endif /* not defined _MGRM_PROCESSES */
|
||||
|
||||
/* Since 5.0.0, the desktop only handles caret blinking in MSG_TIMEOUT
|
||||
message, and the interval for the timer of desktop changes to 0.05s. */
|
||||
if (__mg_tick_counter >
|
||||
__mg_dsk_msg_queue->last_ticks_desktop + DESKTOP_TIMER_INERTVAL) {
|
||||
__mg_dsk_msg_queue->dwState |= QS_DESKTIMER;
|
||||
#ifdef _MGRM_THREADS /* only wake up desktop for threads mode */
|
||||
POST_MSGQ (__mg_dsk_msg_queue);
|
||||
#endif
|
||||
__mg_dsk_msg_queue->last_ticks_desktop = __mg_tick_counter;
|
||||
}
|
||||
#endif /* deprecated code */
|
||||
__mg_tick_counter = ticks;
|
||||
return ticks;
|
||||
}
|
||||
|
||||
#ifdef __NOUNIX__
|
||||
|
||||
static BOOL install_system_timer (void)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL unintall_system_timer (void)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#else /* defined __NOUNIX__ */
|
||||
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
static struct sigaction old_alarm_handler;
|
||||
static struct itimerval old_timer;
|
||||
|
||||
static BOOL install_system_timer (void)
|
||||
{
|
||||
struct itimerval timerv;
|
||||
struct sigaction siga;
|
||||
|
||||
sigaction (SIGALRM, NULL, &old_alarm_handler);
|
||||
|
||||
siga = old_alarm_handler;
|
||||
siga.sa_handler = (void(*)(int))__mg_update_tick_count;
|
||||
#ifndef _MGRM_STANDALONE
|
||||
siga.sa_flags = 0;
|
||||
#else
|
||||
siga.sa_flags = SA_RESTART;
|
||||
#endif
|
||||
sigaction (SIGALRM, &siga, NULL);
|
||||
|
||||
timerv.it_interval.tv_sec = 0;
|
||||
#if defined(__uClinux__) && defined(_MGRM_STANDALONE)
|
||||
timerv.it_interval.tv_usec = 100000; /* 100 ms */
|
||||
#else
|
||||
timerv.it_interval.tv_usec = 10000; /* 10 ms */
|
||||
#endif
|
||||
timerv.it_value = timerv.it_interval;
|
||||
|
||||
if (setitimer (ITIMER_REAL, &timerv, &old_timer) == -1) {
|
||||
TIMER_ERR_SYS ("setitimer call failed!\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL unintall_system_timer (void)
|
||||
{
|
||||
if (setitimer (ITIMER_REAL, &old_timer, 0) == -1) {
|
||||
TIMER_ERR_SYS ("setitimer call failed!\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (sigaction (SIGALRM, &old_alarm_handler, NULL) == -1) {
|
||||
TIMER_ERR_SYS ("sigaction call failed!\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif /* not defined __NOUNIX__ */
|
||||
|
||||
BOOL mg_InitTimer (BOOL use_sys_timer)
|
||||
{
|
||||
__mg_tick_counter = 0;
|
||||
@@ -219,7 +124,8 @@ BOOL mg_InitTimer (BOOL use_sys_timer)
|
||||
__mg_os_start_time();
|
||||
|
||||
if (use_sys_timer) {
|
||||
install_system_timer ();
|
||||
// Since 5.0.14, do nothing.
|
||||
// install_system_timer ();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -227,8 +133,10 @@ BOOL mg_InitTimer (BOOL use_sys_timer)
|
||||
|
||||
void mg_TerminateTimer (BOOL use_sys_timer)
|
||||
{
|
||||
if (use_sys_timer)
|
||||
unintall_system_timer ();
|
||||
if (use_sys_timer) {
|
||||
// Since 5.0.14, do nothing.
|
||||
// unintall_system_timer ();
|
||||
}
|
||||
}
|
||||
|
||||
/************************* Functions run in message thread *******************/
|
||||
@@ -247,34 +155,21 @@ int __mg_check_expired_timers (MSGQUEUE* msg_queue, DWORD inter)
|
||||
int i;
|
||||
TIMER** timer_slots = msg_queue->timer_slots;
|
||||
|
||||
__mg_update_tick_count (msg_queue);
|
||||
|
||||
for (i = 0; i < DEF_NR_TIMERS; i++) {
|
||||
if (timer_slots[i]) {
|
||||
if (__mg_tick_counter >= timer_slots[i]->ticks_expected) {
|
||||
if (msg_queue->last_ticks >= timer_slots[i]->ticks_expected) {
|
||||
/* setting timer flag is simple, we do not need to lock
|
||||
msgq, or else we may encounter dead lock here */
|
||||
msg_queue->expired_timer_mask |= (0x01UL << i);
|
||||
POST_MSGQ (msg_queue);
|
||||
|
||||
timer_slots[i]->ticks_expected += timer_slots[i]->interv;
|
||||
timer_slots[i]->ticks_fired = __mg_tick_counter;
|
||||
timer_slots[i]->ticks_expected =
|
||||
msg_queue->last_ticks + timer_slots[i]->interv;
|
||||
timer_slots[i]->ticks_fired = msg_queue->last_ticks;
|
||||
nr++;
|
||||
}
|
||||
#if 0 /* deprecated code */
|
||||
timer_slots[i]->count += inter;
|
||||
if (timer_slots[i]->count >= timer_slots[i]->interv) {
|
||||
#ifdef _MGRM_PROCESSES
|
||||
timer_slots[i]->ticks_current = SHAREDRES_TIMER_COUNTER;
|
||||
#else
|
||||
timer_slots[i]->ticks_current = __mg_tick_counter;
|
||||
#endif
|
||||
/* setting timer flag is simple, we do not need to lock msgq,
|
||||
or else we may encounter dead lock here */
|
||||
msg_queue->expired_timer_mask |= (0x01UL << i);
|
||||
POST_MSGQ (msg_queue);
|
||||
timer_slots[i]->count -= timer_slots[i]->interv;
|
||||
nr++;
|
||||
}
|
||||
#endif /* deprecated code */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -291,12 +186,7 @@ BOOL GUIAPI SetTimerEx (HWND hWnd, LINT id, DWORD interv,
|
||||
int i;
|
||||
int slot = -1;
|
||||
TIMER** timer_slots;
|
||||
PMSGQUEUE pMsgQueue;
|
||||
|
||||
#ifndef _MGRM_THREADS
|
||||
/* Force to update tick count */
|
||||
GetTickCount();
|
||||
#endif
|
||||
PMSGQUEUE msg_queue;
|
||||
|
||||
if (id == 0) {
|
||||
_WRN_PRINTF ("bad identifier (%ld).\n", id);
|
||||
@@ -307,12 +197,14 @@ BOOL GUIAPI SetTimerEx (HWND hWnd, LINT id, DWORD interv,
|
||||
interv = 1;
|
||||
}
|
||||
|
||||
timer_slots = getTimerSlotsForThisThread (&pMsgQueue);
|
||||
timer_slots = getTimerSlotsForThisThread (&msg_queue);
|
||||
if (MG_UNLIKELY (timer_slots == NULL)) {
|
||||
_WRN_PRINTF ("called for non message thread\n");
|
||||
goto badret;
|
||||
}
|
||||
|
||||
__mg_update_tick_count (msg_queue);
|
||||
|
||||
/* Since 5.0.0: only check hWnd if timer_proc is NULL */
|
||||
if (MG_UNLIKELY (timer_proc == NULL &&
|
||||
!getMainWinIfWindowInThisThread (hWnd))) {
|
||||
@@ -331,7 +223,7 @@ BOOL GUIAPI SetTimerEx (HWND hWnd, LINT id, DWORD interv,
|
||||
/* Since 5.0.0: we reset timer parameters for duplicated call of
|
||||
this function */
|
||||
timer_slots[i]->interv = interv;
|
||||
timer_slots[i]->ticks_expected = __mg_tick_counter + interv;
|
||||
timer_slots[i]->ticks_expected = msg_queue->last_ticks + interv;
|
||||
timer_slots[i]->ticks_fired = 0;
|
||||
timer_slots[i]->proc = timer_proc;
|
||||
return TRUE;
|
||||
@@ -348,14 +240,14 @@ BOOL GUIAPI SetTimerEx (HWND hWnd, LINT id, DWORD interv,
|
||||
timer_slots[slot]->hWnd = hWnd;
|
||||
timer_slots[slot]->id = id;
|
||||
timer_slots[slot]->interv = interv;
|
||||
timer_slots[slot]->ticks_expected = __mg_tick_counter + interv;
|
||||
timer_slots[slot]->ticks_expected = msg_queue->last_ticks + interv;
|
||||
timer_slots[slot]->ticks_fired = 0;
|
||||
timer_slots[slot]->proc = timer_proc;
|
||||
|
||||
_DBG_PRINTF ("ticks_expected (%d): %lu, tick_counter: %lu\n",
|
||||
slot, timer_slots[slot]->ticks_expected, __mg_tick_counter);
|
||||
slot, timer_slots[slot]->ticks_expected, msg_queue->last_ticks);
|
||||
|
||||
pMsgQueue->nr_timers++;
|
||||
msg_queue->nr_timers++;
|
||||
|
||||
return TRUE;
|
||||
|
||||
@@ -363,24 +255,6 @@ badret:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#if 0 /* deprected code */
|
||||
#ifdef _MGRM_PROCESSES
|
||||
static void reset_select_timeout (TIMER** timer_slots)
|
||||
{
|
||||
int i;
|
||||
|
||||
unsigned int interv = 0;
|
||||
for (i = 0; i < DEF_NR_TIMERS; i++) {
|
||||
if (timer_slots[i]) {
|
||||
if (interv == 0 || timer_slots[i]->interv < interv)
|
||||
interv = timer_slots[i]->interv;
|
||||
}
|
||||
}
|
||||
__mg_set_select_timeout (USEC_10MS * interv);
|
||||
}
|
||||
#endif
|
||||
#endif /* deprecated code */
|
||||
|
||||
void __mg_remove_timer (MSGQUEUE* msg_queue, int slot)
|
||||
{
|
||||
TIMER** timer_slots;
|
||||
@@ -470,13 +344,14 @@ BOOL GUIAPI ResetTimerEx (HWND hWnd, LINT id, DWORD interv,
|
||||
if (MG_LIKELY (msg_queue)) {
|
||||
TIMER** timer_slots = msg_queue->timer_slots;
|
||||
|
||||
__mg_update_tick_count (msg_queue);
|
||||
for (i = 0; i < DEF_NR_TIMERS; i++) {
|
||||
if (timer_slots[i] &&
|
||||
timer_slots[i]->hWnd == hWnd && timer_slots[i]->id == id) {
|
||||
/* Should clear old timer flags */
|
||||
msg_queue->expired_timer_mask &= ~(0x01UL << i);
|
||||
timer_slots[i]->interv = interv;
|
||||
timer_slots[i]->ticks_expected = __mg_tick_counter + interv;
|
||||
timer_slots[i]->ticks_expected = msg_queue->last_ticks + interv;
|
||||
timer_slots[i]->ticks_fired = 0;
|
||||
if (timer_proc != (TIMERPROC)INV_PTR)
|
||||
timer_slots[i]->proc = timer_proc;
|
||||
@@ -548,20 +423,6 @@ BOOL GUIAPI HaveFreeTimer (void)
|
||||
|
||||
DWORD GUIAPI GetTickCount (void)
|
||||
{
|
||||
#if defined(_MGRM_PROCESSES)
|
||||
if (mgIsServer) {
|
||||
__mg_tick_counter = __mg_os_get_time_ticks ();
|
||||
SHAREDRES_TIMER_COUNTER = __mg_tick_counter;
|
||||
}
|
||||
else {
|
||||
__mg_tick_counter = SHAREDRES_TIMER_COUNTER;
|
||||
}
|
||||
#elif defined(_MGRM_STANDALONE)
|
||||
__mg_tick_counter = __mg_os_get_time_ticks ();
|
||||
#else /* not defined _MGRM_PROCESSES and _MGRM_PROCESSES */
|
||||
/* do nothing here because the desktop thread updates the tick count */
|
||||
#endif /* not defined _MGRM_PROCESSES and _MGRM_PROCESSES */
|
||||
|
||||
return __mg_tick_counter;
|
||||
return __mg_update_tick_count(getMsgQueueForThisThread ());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user