lumen icon indicating copy to clipboard operation
lumen copied to clipboard

Adding a `defer` function to sched?

Open lePereT opened this issue 3 years ago • 1 comments

It would be useful to have a way of ensuring that clean up happens in tasks that open files or interact with resources that should be tidied up

I was thinking about implementing this simply, by creating a new function in the sched module called defer and a table field called deferred_tasks for each task. All the code called in a defer function would be added to a task, set to paused, that would be added to the deferred_tasks table of the parent task. When the parent task ends normally or the underlying coroutine crashes, the scheduler would unpause the tasks added to the deferred_tasks table.

Would this work and would you consider a pull request that does this?

lePereT avatar Oct 23 '22 16:10 lePereT

That's a very interesting functionality, but I suspect it is possible to implement with an auxiliary function without modifying the scheduler.

Something like

function defer( task, f ) 
   sched.run( function()
     sched.wait({task.EVENT_DIE, task.EVENT_FINISH})
     f()
   end)
end

If you want to free locals from inside a task, you could set up de defer from the task itself:

sched.run( function()
   local file = io.open(...)
   defer(sched.running_task, function() if file then file:close() end  )
   --rest of the task using file
end)

Does this make sense for you?

xopxe avatar Oct 24 '22 16:10 xopxe

Hi Xopxe, it absolutely does,

I'd simplify the caller of defer like this:

function defer( f ) 
   local task = sched.running_task
   sched.run( function()
     sched.wait({task.EVENT_DIE, task.EVENT_FINISH})
     f()
   end)
end
sched.run( function()
   local file = io.open(...)
   defer( function() if file then file:close() end  )
   --rest of the task using file
end)

This is inspired by Go, whose defer statement has the following shape: https://go.dev/blog/defer-panic-and-recover

Interestingly Go's defer creates a stack of functions whose arguments are evaluated at function call time, and which are executed in LIFO order, and deferred functions may read and assign to the returning function’s named return values. However, these probably apply more to that compiled environment

lePereT avatar Nov 10 '22 22:11 lePereT