On Thu, Oct 18, 2012 at 9:49 AM, Greg Ewing greg.ewing@canterbury.ac.nzwrote:
I've converted my tutorial on generator-based tasks for Python 3.3, tidied it up a bit and posted it here:
http://www.cosc.canterbury.ac.**nz/greg.ewing/python/tasks/http://www.cosc.canterbury.ac.nz/greg.ewing/python/tasks/
-- Greg
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?
--Yuval