[LUA]taskMaid——多線程任務管理器(支持異步)

--先上一個實例,再附源代碼啦~

--日常使用本taskMaid的完整操作

taskMaid:onInit()    --初始化任務管理器

--小任務:數蘋果

--任務失敗的回調函數
local function f_callback(n_delta)
	print(n_delta)
end
--數一個蘋果
local function f_task(t_cache)
	 t_cache[1]=t_cache[1]+1 
	return true                --這條任務成功完成
end
local apple={0}

--註冊一個任務
local order=taskMaid:requestNewTaskOrder("calculate_the_number_of_apples",f_callback,apple,1)

--爲這個任務添加若干任務函數。在任務執行時,每一幀會執行一次任務
taskMaid:pushTask(order,f_task,1,"failed to calculate the number of apple!")
taskMaid:pushTask(order,function (t_cache)
	t_cache[1]=t_cache[1]+5
	return true
end,"failed to calculate the number of apple!")
--taskMaid:pushTask...
taskMaid:pushTask(order,function (t_cache)
	chiefMaid:printLog("We have got %d apples!",t_cache[1])
end)


--開始啓動這個任務
taskMaid:startTask(order)

--注意:taskMaid的任務並不是即時執行的,而是以一幀一步的方式執行的。在這一幀啓動或終止任務,意爲從下一幀開始執行或清理該任務。

while(true) do
	taskMaid:onUpdate()
end

這是一個近寫的lua多線程任務管理器。

接口簡潔,功能實用,我**吹爆!(乛◡乛)

這個管理器的特殊處在於需要調用taskMaid:onUpdate來進行刷新,故支持異步處理任務,非常適合在遊戲項目中接入(比如搞一個進度條)。

作者爲lua鮮肉一隻,歡迎各位不吝賜教、提問

local tasks
taskMaid={}
--[[
--任務的狀態
TaskStatus=
{
	"suspended",
	"running",
	"dead",
	"failed",
}

--task類型的數據結構
Task={
    [1]={
        name="",
        speed=1,
        dirty=false,
        routine=coroutine.create(),
        status="suspended",
        callback=nil,
        cache=nil,
        totalProgress=...,只有運行任務隊列後totalProgress纔會被更新
        currentProgress=...,
        [1]=f_task_1,
        [2]=...
    }
}
--]]

--初始化taskMaid
function taskMaid:onInit()
	tasks={}
	return true
end

--刷新taskMaid
function taskMaid:onUpdate()
	for order,task in pairs(tasks) do
		taskMaid:updateTask(order)
	end
end

--查看當前幀是否存在需要執行的任務
function taskMaid:hasTaskRunning()
	for _,v in pairs(tasks) do
		if(v.status=="running") then return true end
	end
	return false
end


local f_coroutineFuntion=function (task)
	local least=task.speed
	for _,t in ipairs(task) do
		if(t[1](task.cache)) then
			if(task.callback) then 
				task.callback(t[2]/task.totalProgress) 
			end
			task.currentProgress=task.currentProgress+t[2]
		else
			task.status="failed"
			if(type(t[3])=="function") then 
				t[3](task.cache)
			elseif(type(t[3]=="string")) then
				--fixme_str
			end
		end
		least=least-1
		if(least<=0 or task.status~="running") then
			coroutine.yield()
		end
	end
	task.status="dead"
end
--申請得到一個新的任務指令,接下來可以通過這條指令來下達、執行、暫停或終止某項任務;f_onProgressChange=function(n_deltaPercent) end:在進度變化時的回調函數,輸入參數爲進度變化的分數(0.0~1.0),每執行一條任務函數都會導致任務進度變化;t_cache內容由開發者自定,作爲輔助數據,將作爲參數傳入任務函數中;i_speed爲執行速度,即每步(每幀)執行的任務函數數量,必須爲一個正數
function taskMaid:requestNewTaskOrder(s_name --[[nilable]],f_onProgressChange--[[nilable]],t_cache --[[nilable]],i_speed--[[nilable]])
	i_speed=i_speed and i_speed>0 and math.ceil(i_speed) or 1
	local task={speed=i_speed,dirty=false,status="suspended",callback=f_onProgressChange,name=s_name,currentProgress=0,cache=t_cache}
	task.routine=coroutine.create(f_coroutineFuntion)
	local ret=#tasks+1
	table.insert(tasks,task)
	return ret
end

function taskMaid:getTaskOrderByName(s_name)
	for order,task in pairs(tasks) do
		if(task.name==s_name) then
			return order
		end
	end
end


--根據任務指令,在任務尾部新添一條分任務。注意,不可以對一個正在運行中的任務進行以下操作!f_task =function(t_cache) return true --[[success]] end:任務函數。n_taskAmount:這一條任務函數所佔的任務量。sf_onFail=function (t_cache) end or "message":這條分任務出錯時的回調函數
function taskMaid:pushTask(n_order,f_task,n_taskAmount --[[nilable]],sf_onFail --[[nilable]]) 
	local task=tasks[n_order]
	if(not task) then return end --fixme_str
	if(task.status=="running") then return end --fixme_str
	task.dirty=true
	table.insert(task,{f_task,n_taskAmount or 1,sf_onFail})
end

function taskMaid:refreshTask(n_order)
	local task=tasks[n_order]
	if(not task) then return end --fixme_str
	if(not task.dirty) then return end
	local totalTaskNum=0
	for _,t in ipairs(task) do
		totalTaskNum=totalTaskNum+t[2]
	end
	task.totalProgress=totalTaskNum
	task.dirty=false 
end

--直接設置某項任務的狀態。謹慎調用。框架在每條任務函數結束完成後,都會檢查一次任務狀態,來判斷該任務是否需要暫停、結束等。框架在每幀開始時都會檢查一次任務狀態,來判斷該任務是否需要執行、銷燬等。
function taskMaid:setTaskStatus(n_order,s_status)
	local task=tasks[n_order]
	if(task) then
		task.status=s_status
	end
end

--執行或恢復執行某任務。(會重新計算totalProgress的值)
function taskMaid:startTask(n_order) 
	taskMaid:setTaskStatus(n_order,"running")
end

--暫停某項任務
function taskMaid:suspendTask(n_order)
	taskMaid:setTaskStatus(n_order,"suspended")
end

--終止某項任務
function taskMaid:stopTask(n_order)
	taskMaid:setTaskStatus(n_order,"dead")
end

--根據指令獲取某任務的數據,將允許對數據內容直接操作,謹慎調用
function taskMaid:getTaskData(n_order)
	return tasks[n_order]
end

--獲取某項任務的狀態
function taskMaid:getTaskStatus(n_order) 
	local task=tasks[n_order]
	if(task) then return task.status end
end

--刷新某項任務,系統在每一幀都會爲所有任務調用一次
function taskMaid:updateTask(n_order)
	taskMaid:refreshTask(n_order)
	local task=tasks[n_order]
	if(not task) then return end
	if(task.status=="running") then
			--do task
			coroutine.resume(task.routine,task)
		elseif(task.status=="dead") then
			--release task
			tasks[n_order]=nil
		elseif(task.status=="failed") then
			--show information
			--fixme
	end
end 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章