/** 更新定时器在定时器列表中的位置 */ static void TimerList_UpdateTimerPos( LCUI_Queue *timer_list, timer_data *p_timer ) { int n, src_i=-1, des_i=-1; int64_t time_left, tmp_time_left; timer_data *p_tmp_timer; /* 计算该定时器的剩余定时时长 */ time_left = LCUI_GetTicks( p_timer->start_time ); time_left -= p_timer->pause_ms; time_left = p_timer->total_ms - time_left; /* 锁上定时器列表 */ Queue_Lock( &global_timer_list ); n = Queue_GetTotal( &global_timer_list ); while(n--) { p_tmp_timer = (timer_data*)Queue_Get( &global_timer_list, n ); if( !p_tmp_timer ) { continue; } /* 若找到自己的位置,则记录 */ if( p_tmp_timer->id == p_timer->id ) { src_i = n; /* 如果已经找到目标位置,则退出循环 */ if( des_i != -1 ) { break; } continue; } tmp_time_left = LCUI_GetTicks( p_tmp_timer->start_time ); tmp_time_left -= p_tmp_timer->pause_ms; tmp_time_left = p_tmp_timer->total_ms - tmp_time_left; /* 若该定时器的剩余定时时长不大于当前定时器,则记录 */ if( des_i == -1 && time_left >= tmp_time_left ) { DEBUG_MSG("src timer: %d, pos: %d, , cur_ms: %I64dms, des timer: %d, pos: %d, cur_ms: %I64dms\n", p_timer->id, src_i, LCUI_GetTicks(p_timer->start_time), p_tmp_timer->id, des_i, LCUI_GetTicks(p_tmp_timer->start_time) ); des_i = n; /* 如果已经找到源位置,则退出循环 */ if( src_i != -1 ) { break; } } } /* 若目标位置无效,则将末尾作为目标位置 */ if( des_i == -1 ) { DEBUG_MSG("tip\n"); des_i = Queue_GetTotal( &global_timer_list )-1; } /* 若源位置和目标位置有效,则开始移动 */ if( src_i != -1 ) { DEBUG_MSG("src: %d, des: %d\n", src_i, des_i ); Queue_Move( &global_timer_list, des_i, src_i ); } Queue_Unlock( &global_timer_list ); }
/** * 继续定时器的倒计时 * @param timer_id * 目标定时器的标识符 * @return * 正常返回0,指定ID的定时器不存在则返回-1. * */ LCUI_API int LCUITimer_Continue( int timer_id ) { timer_data *timer; LCUISleeper_BreakSleep( &timer_sleeper ); Queue_Lock( &global_timer_list ); timer = TimerList_Find( timer_id ); if( timer ) { /* 计算处于暂停状态的时长 */ timer->pause_ms += (long int)LCUI_GetTicks( timer->pause_time ); timer->state = STATE_RUN; Queue_Unlock( &global_timer_list ); return 0; } Queue_Unlock( &global_timer_list ); return -1; }
/** 打印列表中的定时器信息 */ static void TimerList_Print( LCUI_Queue *timer_list ) { int i, total; timer_data *timer; total = Queue_GetTotal( timer_list ); _DEBUG_MSG("timer list(%d) start:\n", total); for(i=0; i<total; ++i) { timer = (timer_data*)Queue_Get( timer_list , i); if( !timer ) { continue; } _DEBUG_MSG("[%02d] %d, cur_ms: %dms, total_ms: %dms\n", i, timer->id, timer->total_ms - (long int)LCUI_GetTicks(timer->start_time), timer->total_ms ); } _DEBUG_MSG("timer list end\n\n"); }
/** * 设置定时器 * 定时器的作用是让一个任务在经过指定时间后才执行 * @param n_ms * 等待的时间,单位为毫秒 * @param callback_func * 用于响应定时器的回调函数 * @param reuse * 指示该定时器是否重复使用,如果要用于循环定时处理某些 * 任务,可将它置为 TRUE,否则置于 FALSE。 * @return * 该定时器的标识符 * */ LCUI_API int LCUITimer_Set( long int n_ms, void (*callback_func)(void*), void *arg, LCUI_BOOL reuse ) { int n; int64_t time_left; timer_data timer, *p_timer; static int id = 100; /* 打断定时器睡眠者的睡眠 */ LCUISleeper_BreakSleep( &timer_sleeper ); Queue_Lock( &global_timer_list ); n = Queue_GetTotal( &global_timer_list ); while(n--) { p_timer = (timer_data*)Queue_Get( &global_timer_list, n ); if( !p_timer ) { continue; } time_left = LCUI_GetTicks( p_timer->start_time ); time_left -= p_timer->pause_ms; time_left = p_timer->total_ms - time_left; if( time_left <= n_ms ) { break; } } timer.id = ++id; timer.app_id = LCUIApp_GetSelfID(); timer.state = STATE_RUN; timer.reuse = reuse; timer.total_ms = n_ms; timer.pause_ms = 0; timer.start_time = LCUI_GetTickCount(); timer.callback_func = callback_func; timer.arg = arg; Queue_Insert( &global_timer_list, n+1, &timer ); Queue_Unlock( &global_timer_list ); DEBUG_MSG("set timer, id: %d, total_ms: %d,app_id: %lu\n", timer.id, timer.total_ms, timer.app_id); return timer.id; }
/** 让当前帧停留一定时间 */ void FrameControl_Remain( FrameCtrlCtx ctx ) { unsigned int n_ms, lost_ms; int64_t current_time; if( ctx->state == FRAME_CTRL_STATE_QUIT ) { return; } current_time = LCUI_GetTickCount(); n_ms = (int)(current_time - ctx->prev_frame_start_time); if( n_ms > ctx->one_frame_remain_time ) { goto normal_exit; } n_ms = ctx->one_frame_remain_time - n_ms; if( n_ms < 1 ) { goto normal_exit; } /* 进行睡眠,直到需要暂停为止 */ LCUICond_TimedWait( &ctx->wait_pause, &ctx->mutex, n_ms ); /* 睡眠结束后,如果当前状态不为PAUSE,则说明睡眠不是因为要暂停而终止的 */ if( ctx->state != FRAME_CTRL_STATE_PAUSE ) { goto normal_exit; } current_time = LCUI_GetTickCount(); /* 需要暂停,进行睡眠,直到需要继续为止 */ LCUICond_Wait( &ctx->wait_continue, &ctx->mutex ); lost_ms = (unsigned int)LCUI_GetTicks( current_time ); ctx->pause_time = lost_ms; ctx->prev_frame_start_time += lost_ms; return; normal_exit:; current_time = LCUI_GetTickCount(); if( current_time - ctx->prev_fps_update_time >= 1000 ) { ctx->current_fps = ctx->temp_fps; ctx->prev_fps_update_time = current_time; ctx->temp_fps = 0; } ctx->prev_frame_start_time = current_time; ++ctx->temp_fps; }
/** 定时器线程,用于处理列表中各个定时器 */ static void TimerThread( void *arg ) { int i, n; long int n_ms; LCUI_Func func_data; LCUI_Queue *timer_list; timer_data *timer = NULL; int64_t lost_ms; timer_list = (LCUI_Queue*)arg; func_data.arg[0] = NULL; func_data.arg[1] = NULL; while( !LCUI_Active() ) { LCUI_MSleep(10); } while( timer_thread_active ) { Queue_Lock( timer_list ); n = Queue_GetTotal( timer_list ); for(i=0; i<n; ++i) { timer = (timer_data*)Queue_Get( timer_list , i); if( !timer ) { continue; } if( timer->state == STATE_RUN ) { break; } } Queue_Unlock( timer_list ); /* 没有要处理的定时器,停留一段时间再进行下次循环 */ if(i >= n || !timer ) { LCUI_MSleep(10); continue; } lost_ms = LCUI_GetTicks( timer->start_time ); /* 减去处于暂停状态的时长 */ lost_ms -= timer->pause_ms; /* 若流失的时间未达到总定时时长 */ if( lost_ms < timer->total_ms ) { Queue_Lock( timer_list ); n_ms = timer->total_ms - lost_ms; /* 开始睡眠 */ LCUISleeper_StartSleep( &timer_sleeper, n_ms ); Queue_Unlock( timer_list ); lost_ms = LCUI_GetTicks( timer->start_time ); lost_ms -= timer->pause_ms; if( lost_ms < timer->total_ms ) { continue; } } DEBUG_MSG("timer: %d, start_time: %I64dms, cur_time: %I64dms, cur_ms: %I64d, total_ms: %ld\n", timer->id, timer->start_time, LCUI_GetTickCount(), timer->total_ms-lost_ms, timer->total_ms); /* 准备任务数据 */ func_data.id = timer->app_id; func_data.func = (CallBackFunc)timer->callback_func; func_data.arg[0] = timer->arg; func_data.destroy_arg[0] = FALSE; /* 添加该任务至指定程序的任务队列,添加模式是覆盖 */ AppTasks_CustomAdd( ADD_MODE_REPLACE | AND_ARG_F, &func_data ); Queue_Lock( timer_list ); /* 若需要重复使用,则重置剩余等待时间 */ if( timer->reuse ) { timer->start_time = LCUI_GetTickCount(); timer->pause_ms = 0; TimerList_UpdateTimerPos( timer_list, timer ); } else { /* 否则,释放该定时器 */ LCUITimer_Free( timer->id ); } Queue_Unlock( timer_list ); } LCUIThread_Exit(NULL); }