static int do_check_waiting(ScheduleContext *pContext) { ScheduleArray *pScheduleArray; ScheduleEntry *newEntries; ScheduleEntry *pWaitingEntry; ScheduleEntry *pWaitingEnd; ScheduleEntry *pSchedEntry; ScheduleEntry *pSchedEnd; int allocCount; int newCount; int result; int deleteCount; pScheduleArray = &(pContext->scheduleArray); deleteCount = 0; if (waiting_del_id >= 0) { pSchedEnd = pScheduleArray->entries + pScheduleArray->count; for (pSchedEntry=pScheduleArray->entries; \ pSchedEntry<pSchedEnd; pSchedEntry++) { if (pSchedEntry->id == waiting_del_id) { break; } } if (pSchedEntry < pSchedEnd) { pSchedEntry++; while (pSchedEntry < pSchedEnd) { memcpy(pSchedEntry - 1, pSchedEntry, \ sizeof(ScheduleEntry)); pSchedEntry++; } deleteCount++; pScheduleArray->count--; logDebug("file: "__FILE__", line: %d, " \ "delete task id: %d, " \ "current schedule count: %d", __LINE__, \ waiting_del_id, pScheduleArray->count); } waiting_del_id = -1; } if (waiting_schedule_array.count == 0) { if (deleteCount > 0) { sched_make_chain(pContext); return 0; } return ENOENT; } allocCount = pScheduleArray->count + waiting_schedule_array.count; newEntries = (ScheduleEntry *)malloc(sizeof(ScheduleEntry) * allocCount); if (newEntries == NULL) { result = errno != 0 ? errno : ENOMEM; logError("file: "__FILE__", line: %d, " \ "malloc %d bytes failed, " \ "errno: %d, error info: %s", \ __LINE__, (int)sizeof(ScheduleEntry) * allocCount, \ result, STRERROR(result)); if (deleteCount > 0) { sched_make_chain(pContext); } return result; } if (pScheduleArray->count > 0) { memcpy(newEntries, pScheduleArray->entries, \ sizeof(ScheduleEntry) * pScheduleArray->count); } newCount = pScheduleArray->count; pWaitingEnd = waiting_schedule_array.entries + waiting_schedule_array.count; for (pWaitingEntry=waiting_schedule_array.entries; \ pWaitingEntry<pWaitingEnd; pWaitingEntry++) { pSchedEnd = newEntries + newCount; for (pSchedEntry=newEntries; pSchedEntry<pSchedEnd; \ pSchedEntry++) { if (pWaitingEntry->id == pSchedEntry->id) { memcpy(pSchedEntry, pWaitingEntry, \ sizeof(ScheduleEntry)); break; } } if (pSchedEntry == pSchedEnd) { memcpy(pSchedEntry, pWaitingEntry, \ sizeof(ScheduleEntry)); newCount++; } } logDebug("file: "__FILE__", line: %d, " \ "schedule add entries: %d, replace entries: %d", __LINE__, newCount - pScheduleArray->count, \ waiting_schedule_array.count - (newCount - pScheduleArray->count)); if (pScheduleArray->entries != NULL) { free(pScheduleArray->entries); } pScheduleArray->entries = newEntries; pScheduleArray->count = newCount; free(waiting_schedule_array.entries); waiting_schedule_array.count = 0; waiting_schedule_array.entries = NULL; sched_make_chain(pContext); return 0; }
static void *sched_thread_entrance(void *args) { ScheduleContext *pContext; ScheduleEntry *pPrevious; ScheduleEntry *pCurrent; ScheduleEntry *pSaveNext; ScheduleEntry *pNode; ScheduleEntry *pUntil; int exec_count; int i; pContext = (ScheduleContext *)args; if (sched_init_entries(&(pContext->scheduleArray)) != 0) { free(pContext); return NULL; } sched_make_chain(pContext); g_schedule_flag = true; while (*(pContext->pcontinue_flag)) { g_current_time = time(NULL); sched_deal_delay_tasks(pContext); sched_check_waiting_more(pContext); if (pContext->scheduleArray.count == 0) //no schedule entry { sleep(1); continue; } while (pContext->head->next_call_time > g_current_time && *(pContext->pcontinue_flag)) { sleep(1); g_current_time = time(NULL); sched_deal_delay_tasks(pContext); if (sched_check_waiting_more(pContext) == 0) { break; } } if (!(*(pContext->pcontinue_flag))) { break; } exec_count = 0; pCurrent = pContext->head; while (*(pContext->pcontinue_flag) && (pCurrent != NULL \ && pCurrent->next_call_time <= g_current_time)) { //logInfo("exec task id: %d", pCurrent->id); if (!pCurrent->new_thread) { pCurrent->task_func(pCurrent->func_args); } else { pthread_t tid; int result; pCurrent->thread_running = false; if ((result=pthread_create(&tid, NULL, sched_call_func, pCurrent)) != 0) { logError("file: "__FILE__", line: %d, " \ "create thread failed, " \ "errno: %d, error info: %s", \ __LINE__, result, STRERROR(result)); } else { usleep(1*1000); for (i=1; !pCurrent->thread_running && i<100; i++) { logDebug("file: "__FILE__", line: %d, " "task_id: %d, waiting thread ready, count %d", __LINE__, pCurrent->id, i); usleep(1*1000); } } } do { pCurrent->next_call_time += pCurrent->interval; } while (pCurrent->next_call_time <= g_current_time); pCurrent = pCurrent->next; exec_count++; } if (exec_count == 0 || pContext->scheduleArray.count == 1) { continue; } if (exec_count > pContext->scheduleArray.count / 2) { sched_make_chain(pContext); continue; } pNode = pContext->head; pContext->head = pCurrent; //new chain head for (i=0; i<exec_count; i++) { if (pNode->next_call_time >= pContext->tail->next_call_time) { pContext->tail->next = pNode; pContext->tail = pNode; pNode = pNode->next; pContext->tail->next = NULL; continue; } pPrevious = NULL; pUntil = pContext->head; while (pUntil != NULL && \ pNode->next_call_time > pUntil->next_call_time) { pPrevious = pUntil; pUntil = pUntil->next; } pSaveNext = pNode->next; if (pPrevious == NULL) { pContext->head = pNode; } else { pPrevious->next = pNode; } pNode->next = pUntil; pNode = pSaveNext; } } g_schedule_flag = false; logDebug("file: "__FILE__", line: %d, " \ "schedule thread exit", __LINE__); free(pContext); return NULL; }
static void *sched_thread_entrance(void *args) { ScheduleContext *pContext; ScheduleEntry *pPrevious; ScheduleEntry *pCurrent; ScheduleEntry *pSaveNext; ScheduleEntry *pNode; ScheduleEntry *pUntil; int exec_count; int i; pContext = (ScheduleContext *)args; if (sched_init_entries(&(pContext->scheduleArray)) != 0) { free(pContext); return NULL; } sched_make_chain(pContext); g_schedule_flag = true; while (*(pContext->pcontinue_flag)) { sched_check_waiting(pContext); if (pContext->scheduleArray.count == 0) //no schedule entry { sleep(1); g_current_time = time(NULL); continue; } g_current_time = time(NULL); while (pContext->head->next_call_time > g_current_time && *(pContext->pcontinue_flag)) { sleep(1); g_current_time = time(NULL); if (sched_check_waiting(pContext) == 0) { break; } } if (!(*(pContext->pcontinue_flag))) { break; } exec_count = 0; pCurrent = pContext->head; while (*(pContext->pcontinue_flag) && (pCurrent != NULL \ && pCurrent->next_call_time <= g_current_time)) { //fprintf(stderr, "exec task id=%d\n", pCurrent->id); pCurrent->task_func(pCurrent->func_args); do { pCurrent->next_call_time += pCurrent->interval; } while (pCurrent->next_call_time <= g_current_time); pCurrent = pCurrent->next; exec_count++; } if (exec_count == 0 || pContext->scheduleArray.count == 1) { continue; } if (exec_count > pContext->scheduleArray.count / 2) { sched_make_chain(pContext); continue; } pNode = pContext->head; pContext->head = pCurrent; //new chain head for (i=0; i<exec_count; i++) { if (pNode->next_call_time >= pContext->tail->next_call_time) { pContext->tail->next = pNode; pContext->tail = pNode; pNode = pNode->next; pContext->tail->next = NULL; continue; } pPrevious = NULL; pUntil = pContext->head; while (pUntil != NULL && \ pNode->next_call_time > pUntil->next_call_time) { pPrevious = pUntil; pUntil = pUntil->next; } pSaveNext = pNode->next; if (pPrevious == NULL) { pContext->head = pNode; } else { pPrevious->next = pNode; } pNode->next = pUntil; pNode = pSaveNext; } } g_schedule_flag = false; logDebug("file: "__FILE__", line: %d, " \ "schedule thread exit", __LINE__); free(pContext); return NULL; }