On Thu, Oct 18, 2012 at 9:49 AM, Greg Ewing <greg.ewing@canterbury.ac.nz> wrote:
I've converted my tutorial on generator-based tasks
for Python 3.3, tidied it up a bit and posted it here:



Thanks for writing this. I've used threads all my life so this coroutine/yield-from paradigm is hard for me to grok even after reading this quite a few times.

I can't wrap my head around the block and unblock functions.

block() removes the current task from the ready_list, but is the current task guaranteed to be my task? If so, then I'd never run again after the yield in acquire(), that is unless a gracious other player unblocks me.

block() in acquire() is the philosopher or fork avoiding the scheduler?
yield in acquire() is the philosopher relinquishing control or the fork?

I think I finally figured it out after staring at it for long enough. 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[0], forks[2]), "Socrates")
schedule(philosopher("Euclid", 5, 1, 4, forks[2], forks[0]), "Euclid")

Which may be really hard to debug.

Is there a coroutine strategy for tackling these challenges? Or will I just get better at overcoming them with practice?