2017-07-23 14:51:20 +02:00
-- Threading simulation module
2018-01-27 17:49:55 +02:00
-- Task.sleep()
2017-07-23 14:51:20 +02:00
-- @author Valansch
-- github: https://github.com/Valansch/RedMew
-- ======================================================= --
2018-01-26 01:31:47 +02:00
local Queue = require " utils.Queue "
2018-01-31 22:30:32 +02:00
local PriorityQueue = require " utils.PriorityQueue "
2017-07-23 14:51:20 +02:00
2018-01-27 17:49:55 +02:00
local Task = { }
2017-07-23 14:51:20 +02:00
2018-01-31 22:30:32 +02:00
global.callbacks = global.callbacks or PriorityQueue.new ( )
2017-07-23 14:51:20 +02:00
global.next_async_callback_time = - 1
2018-01-31 22:30:32 +02:00
global.task_queue = global.task_queue or Queue.new ( )
2018-01-28 20:33:25 +02:00
global.total_task_weight = 0
2018-01-31 22:30:32 +02:00
global.task_queue_speed = 1
local function comp ( a , b )
return a.time < b.time
end
2017-07-23 14:51:20 +02:00
local function on_tick ( )
2018-01-27 17:49:55 +02:00
local queue = global.task_queue
for i = 1 , get_task_per_tick ( ) do
local task = Queue.peek ( queue )
if task ~= nil then
local success , result = pcall ( _G [ task.func_name ] , task.params ) -- result is error if not success else result is a boolean for if the task should stay in the queue.
2018-01-15 19:24:48 +02:00
if not success then
log ( result )
2018-01-28 20:33:25 +02:00
Queue.pop ( queue )
global.total_task_weight = global.total_task_weight - task.weight
2018-01-15 19:24:48 +02:00
elseif not result then
2018-01-28 20:33:25 +02:00
Queue.pop ( queue )
global.total_task_weight = global.total_task_weight - task.weight
2018-01-15 19:24:48 +02:00
end
2017-10-23 13:24:05 +02:00
end
2017-10-06 02:13:56 +02:00
end
2018-01-31 22:30:32 +02:00
local callbacks = global.callbacks
local callback = PriorityQueue.peek ( callbacks )
while callback ~= nil and game.tick >= callback.time do
local success , error = pcall ( _G [ callback.func_name ] , callback.params )
if not success then
log ( error )
end
PriorityQueue.pop ( callbacks , comp )
callback = PriorityQueue.peek ( callbacks )
end
2017-07-23 14:51:20 +02:00
end
2018-02-02 01:37:08 +02:00
global.tpt = global.task_queue_speed
2018-01-27 17:49:55 +02:00
function get_task_per_tick ( )
2018-02-02 01:37:08 +02:00
if game.tick % 300 == 0 then
local size = global.total_task_weight
global.tpt = math.floor ( math.log10 ( size + 1 ) ) * global.task_queue_speed
if global.tpt < 1 then
global.tpt = 1
end
2017-10-25 13:00:45 +02:00
end
2018-02-02 01:37:08 +02:00
return global.tpt
2017-10-23 13:24:05 +02:00
end
2018-01-31 22:30:32 +02:00
function Task . set_timeout_in_ticks ( ticks , func_name , params )
local time = game.tick + ticks
local callback = { time = time , func_name = func_name , params = params }
PriorityQueue.push ( global.callbacks , callback , comp )
2017-07-23 14:51:20 +02:00
end
2018-01-31 22:30:32 +02:00
function Task . set_timeout ( sec , func_name , params )
Task.set_timeout_in_ticks ( 60 * sec , func_name , params )
2017-10-06 02:13:56 +02:00
end
2018-01-28 20:33:25 +02:00
function Task . queue_task ( func_name , params , weight )
weight = weight or 1
global.total_task_weight = global.total_task_weight + weight
Queue.push ( global.task_queue , { func_name = func_name , params = params , weight = weight } )
2017-10-06 02:13:56 +02:00
end
2017-07-23 14:51:20 +02:00
Event.register ( defines.events . on_tick , on_tick )
2018-01-27 17:49:55 +02:00
return Task