Yuval Greenfield wrote:
block() removes the current task from the ready_list, but is the current task guaranteed to be my task?
Yes, block() always operates on the currently running task.
If so, then I'd never run again after the yield in acquire(), that is unless a gracious other player unblocks me.
Yes, the unblocking needs to be done by another task, or by something outside the task system such as an I/O callback.
I'm not sure it makes sense for scheduler functions to store waiting tasks in a queue owned by the app and invisible from the scheduler. This can cause *invisible deadlocks* such as:
schedule(philosopher("Socrates", 8, 3, 1, forks, forks), "Socrates") schedule(philosopher("Euclid", 5, 1, 4, forks, forks), "Euclid")
Deadlocks are a potential problem in any system involving concurrency, and have to be dealt with on a case-by-case basis.
Simply having the scheduler know where all the tasks are will not prevent deadlocks. It might make it possible for the scheduler to *detect* deadlocks, but you still have to do something about them.
Having said that, I'm thinking about writing a more elaborate version of my scheduler that does keep track of which queue a task is waiting on, mainly so that tasks can be cancelled cleanly.
Is there a coroutine strategy for tackling these challenges? Or will I just get better at overcoming them with practice?
If you've been using threads all your life as you say, then you're probably already pretty good at dealing with them. All of the same techniques apply.