SmartOS/Task.cpp

144 lines
3.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "Task.h"
/*
*/
Task::Task(TaskScheduler* scheduler)
{
_Scheduler = scheduler;
}
/*Task::~Task()
{
if(ID) _Scheduler->Remove(ID);
}*/
TaskScheduler::TaskScheduler(string name)
{
Name = name;
_gid = 1;
Running = false;
Count = 0;
}
TaskScheduler::~TaskScheduler()
{
_Tasks.DeleteAll().Clear();
}
// 创建任务返回任务编号。dueTime首次调度时间usperiod调度间隔us-1表示仅处理一次
uint TaskScheduler::Add(Action func, void* param, ulong dueTime, long period)
{
Task* task = new Task(this);
task->ID = _gid++;
task->Callback = func;
task->Param = param;
task->Period = period;
task->NextTime = Time.Current() + dueTime;
Count++;
_Tasks.Add(task);
#if DEBUG
// 输出长整型%ld无符号长整型%llu
//debug_printf("%s添加任务%d 0x%08x FirstTime=%lluus Period=%ldus\r\n", Name, task->ID, func, dueTime, period);
if(period >= 1000)
{
uint dt = dueTime / 1000;
int pd = period > 0 ? period / 1000 : period;
debug_printf("%s::添加任务%d 0x%08x FirstTime=%ums Period=%dms\r\n", Name, task->ID, func, dt, pd);
}
else
debug_printf("%s::添加任务%d 0x%08x FirstTime=%uus Period=%dus\r\n", Name, task->ID, func, (uint)dueTime, (int)period);
#endif
return task->ID;
}
void TaskScheduler::Remove(uint taskid)
{
int i = -1;
while(_Tasks.MoveNext(i))
{
Task* task = _Tasks[i];
if(task->ID == taskid)
{
_Tasks.RemoveAt(i);
debug_printf("%s::删除任务%d 0x%08x\r\n", Name, task->ID, task->Callback);
// 首先清零ID避免delete的时候再次删除
task->ID = 0;
delete task;
break;
}
}
}
void TaskScheduler::Start()
{
if(Running) return;
#if DEBUG
//AddTask(ShowTime, NULL, 2000000, 2000000);
#endif
debug_printf("%s::准备就绪 开始循环处理%d个任务\r\n\r\n", Name, Count);
Running = true;
while(Running)
{
ulong now = Time.Current() - Sys.StartTime; // 当前时间。减去系统启动时间,避免修改系统时间后导致调度停摆
ulong min = UInt64_Max; // 最小时间,这个时间就会有任务到来
int i = -1;
while(_Tasks.MoveNext(i))
{
Task* task = _Tasks[i];
if(task && task->NextTime <= now)
{
// 先计算下一次时间
//task->NextTime += task->Period;
// 不能通过累加的方式计算下一次时间,因为可能系统时间被调整
task->NextTime = now + task->Period;
if(task->NextTime < min) min = task->NextTime;
task->Callback(task->Param);
// 如果只是一次性任务,在这里清理
//if(task->Period < 0) delete task;
if(task->Period < 0) Remove(task->ID);
}
}
// 如果有最小时间,睡一会吧
now = Time.Current(); // 当前时间
if(min != UInt64_Max && min > now)
{
min -= now;
// 最大只允许睡眠1秒避免Sys.Delay出现设计错误同时也更人性化
if(min > 1000000) min = 1000000;
Sys.Delay(min);
}
}
debug_printf("%s停止调度共有%d个任务\r\n", Name, Count);
}
void TaskScheduler::Stop()
{
debug_printf("%s停止\r\n", Name);
Running = false;
}
Task* TaskScheduler::operator[](int taskid)
{
int i = -1;
while(_Tasks.MoveNext(i))
{
Task* task = _Tasks[i];
if(task && task->ID == taskid) return task;
}
return NULL;
}