<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Do Continuations Make Sense?</title>
	<atom:link href="http://www.jeffongames.com/2010/02/do-continuations-make-sense/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jeffongames.com/2010/02/do-continuations-make-sense/</link>
	<description>This is Jeff.  This is Jeff On Games.</description>
	<lastBuildDate>Wed, 04 Aug 2010 05:04:09 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
	<item>
		<title>By: Jeff</title>
		<link>http://www.jeffongames.com/2010/02/do-continuations-make-sense/comment-page-1/#comment-43999</link>
		<dc:creator>Jeff</dc:creator>
		<pubDate>Mon, 01 Mar 2010 15:23:23 +0000</pubDate>
		<guid isPermaLink="false">http://www.jeffongames.com/?p=238#comment-43999</guid>
		<description>@Ben A very good point about invariants, especially related to AI.  A change that requires the actor to change state should probably cancel their co-routines in some way.

@Richard An awesome reply.  I agree, using C#&#039;s generator system as a continuation / co-routine system is a hack on top of a hack in some ways, but only Mono supports actual continuations / co-routines.

I&#039;m thinking, in general, this system just needs a more robust scheduler that can make the connection between a running coroutine and the connected parent object, something I don&#039;t think C# can do by default.</description>
		<content:encoded><![CDATA[<p>@Ben A very good point about invariants, especially related to AI.  A change that requires the actor to change state should probably cancel their co-routines in some way.</p>
<p>@Richard An awesome reply.  I agree, using C#&#8217;s generator system as a continuation / co-routine system is a hack on top of a hack in some ways, but only Mono supports actual continuations / co-routines.</p>
<p>I&#8217;m thinking, in general, this system just needs a more robust scheduler that can make the connection between a running coroutine and the connected parent object, something I don&#8217;t think C# can do by default.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Richard</title>
		<link>http://www.jeffongames.com/2010/02/do-continuations-make-sense/comment-page-1/#comment-43739</link>
		<dc:creator>Richard</dc:creator>
		<pubDate>Sat, 27 Feb 2010 20:29:21 +0000</pubDate>
		<guid isPermaLink="false">http://www.jeffongames.com/?p=238#comment-43739</guid>
		<description>Generator coroutines are only an approximation of microthreads built on an approximation of coroutines built on a programming language primitive that has been extended on a whim in some vaguely suitable fashion.  They are ugly, and using them is ugly.  Just look at &quot;yield return&quot;, it is not natural and is nonsensical to read.

Take a look a Python.  First generators were added, and then someone said, &quot;Hey, look, if we allow values to be sent through the generator to the yielding function, we get coroutines!&quot;  Then someone said, &quot;If we write a scheduler that shoves these coroutines around, and the code written in the coroutines is written in a certain way with the custom boilerplate that allows these coroutines to work, then we have microthreading!&quot;  What you really have, is a situation where you have approximated microthreads that do not have the benefits of proper microthreads.  Whether the creators of the generator coroutines and microthreading framework were ever aware of these benefits, is something that could be questioned.

So, what&#039;s my point?  Firstly that proper coroutines should make code more readable, not less readable.  Secondly, that with a proper microthreading framework you do not need to add these checks in your logic.  I am not familiar with the generator coroutine / microthreading implementation you are using, so you will have to work out how good an approximation it is.

Yes, the checks are cumbersome, but I had game logic that is probably still out there pumping away at the moment doing many steps in a microthread along the lines of &quot;Approach target.. check if in process of being garbage collected, check if dead, check if still on that target, ..  Still focused and alive?  Proceed with next step of the action on that target.&quot;  The only reason these checks are still in place, is not because I could not abstract them away completely, but rather that the microthreading framework I used was not finalised at the time I initially wrote the logic.  It would have been trivial to replace them after it was, if I had deemed worthwhile.  The truth is that there really wasn&#039;t that much entity logic that needed checks like this, most of it was pretty generic, including that generic action performing function that got launched by each entity.

So how would I have gotten rid of these checks on our microthreading framework?  Well in Stackless Python you can kill a microthread.  This reschedules the microthread but rather than continuing execution where it was yielded, instead an exception (TaskletExit) is raised within it.  Nothing catches this exception, it is the natural indicator that the microthread is exiting.  Anyway, it unwinds the call stack and the microthread exits and is garbage collected.  What I would have done (and have done in other projects) is to store a reference to the action performing microthread when it is created.  Then when an entity starts a new action, or gets an event indicating it has been killed, or removed from the game environment, that tasklet can be killed.

Is it possible for you to raise an exception through your generator from your scheduler, and to kill one of your microthreads in this way?  I do not know.</description>
		<content:encoded><![CDATA[<p>Generator coroutines are only an approximation of microthreads built on an approximation of coroutines built on a programming language primitive that has been extended on a whim in some vaguely suitable fashion.  They are ugly, and using them is ugly.  Just look at &#8220;yield return&#8221;, it is not natural and is nonsensical to read.</p>
<p>Take a look a Python.  First generators were added, and then someone said, &#8220;Hey, look, if we allow values to be sent through the generator to the yielding function, we get coroutines!&#8221;  Then someone said, &#8220;If we write a scheduler that shoves these coroutines around, and the code written in the coroutines is written in a certain way with the custom boilerplate that allows these coroutines to work, then we have microthreading!&#8221;  What you really have, is a situation where you have approximated microthreads that do not have the benefits of proper microthreads.  Whether the creators of the generator coroutines and microthreading framework were ever aware of these benefits, is something that could be questioned.</p>
<p>So, what&#8217;s my point?  Firstly that proper coroutines should make code more readable, not less readable.  Secondly, that with a proper microthreading framework you do not need to add these checks in your logic.  I am not familiar with the generator coroutine / microthreading implementation you are using, so you will have to work out how good an approximation it is.</p>
<p>Yes, the checks are cumbersome, but I had game logic that is probably still out there pumping away at the moment doing many steps in a microthread along the lines of &#8220;Approach target.. check if in process of being garbage collected, check if dead, check if still on that target, ..  Still focused and alive?  Proceed with next step of the action on that target.&#8221;  The only reason these checks are still in place, is not because I could not abstract them away completely, but rather that the microthreading framework I used was not finalised at the time I initially wrote the logic.  It would have been trivial to replace them after it was, if I had deemed worthwhile.  The truth is that there really wasn&#8217;t that much entity logic that needed checks like this, most of it was pretty generic, including that generic action performing function that got launched by each entity.</p>
<p>So how would I have gotten rid of these checks on our microthreading framework?  Well in Stackless Python you can kill a microthread.  This reschedules the microthread but rather than continuing execution where it was yielded, instead an exception (TaskletExit) is raised within it.  Nothing catches this exception, it is the natural indicator that the microthread is exiting.  Anyway, it unwinds the call stack and the microthread exits and is garbage collected.  What I would have done (and have done in other projects) is to store a reference to the action performing microthread when it is created.  Then when an entity starts a new action, or gets an event indicating it has been killed, or removed from the game environment, that tasklet can be killed.</p>
<p>Is it possible for you to raise an exception through your generator from your scheduler, and to kill one of your microthreads in this way?  I do not know.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: David Ludwig</title>
		<link>http://www.jeffongames.com/2010/02/do-continuations-make-sense/comment-page-1/#comment-43735</link>
		<dc:creator>David Ludwig</dc:creator>
		<pubDate>Sat, 27 Feb 2010 19:59:13 +0000</pubDate>
		<guid isPermaLink="false">http://www.jeffongames.com/?p=238#comment-43735</guid>
		<description>I have some experience with Lua-based coroutines/microthreads.  Usually, they end up getting attached to a single, parent entity.  When the parent is removed from the game world, the coroutine is paused, and if the parent is deleted, the coroutine is deleted.  This tends to work out in a surprising number of cases, although I&#039;m usually using coroutines to write simple, top-to-bottom scripted animations, not AI.  In cases where things get more complicated, I usually end up writing some kind of higher-level, game-specific controller to oversee synchronization.</description>
		<content:encoded><![CDATA[<p>I have some experience with Lua-based coroutines/microthreads.  Usually, they end up getting attached to a single, parent entity.  When the parent is removed from the game world, the coroutine is paused, and if the parent is deleted, the coroutine is deleted.  This tends to work out in a surprising number of cases, although I&#8217;m usually using coroutines to write simple, top-to-bottom scripted animations, not AI.  In cases where things get more complicated, I usually end up writing some kind of higher-level, game-specific controller to oversee synchronization.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ben Cummings</title>
		<link>http://www.jeffongames.com/2010/02/do-continuations-make-sense/comment-page-1/#comment-43530</link>
		<dc:creator>Ben Cummings</dc:creator>
		<pubDate>Sat, 27 Feb 2010 05:14:23 +0000</pubDate>
		<guid isPermaLink="false">http://www.jeffongames.com/?p=238#comment-43530</guid>
		<description>While I have no experience with continuations or coroutines in C#, I can say that in general, I believe that you only keep calling back into the coroutine so long as its invariants hold. Another way to put it is that we don&#039;t expect coroutines to run to completion and terminate; instead, as soon as the actor has died, you need to stop calling the UpdateAlive coroutine. Actions that depend on a live actor could then throw an exception if you try to MoveToCover with a dead actor, for example, but I probably wouldn&#039;t rely on catching such cases as normal flow control (reserving that exception for truly exceptional cases).

Since we&#039;re specifically talking about using coroutines in a separate thread to execute actions that may take place over several frames (and communicate back to other threads), there are all the usual issues of making sure the invariants truly stay invariant while a function (or in this case coroutine) is running, but between yields, presumably we can get updates that would terminate (or put on hold) coroutines which are no longer valid, such as &quot;this monster just died.&quot; 

I get the feeling I might be misunderstanding the problem. I&#039;m by no means an expert with this stuff, but I hope that helps.</description>
		<content:encoded><![CDATA[<p>While I have no experience with continuations or coroutines in C#, I can say that in general, I believe that you only keep calling back into the coroutine so long as its invariants hold. Another way to put it is that we don&#8217;t expect coroutines to run to completion and terminate; instead, as soon as the actor has died, you need to stop calling the UpdateAlive coroutine. Actions that depend on a live actor could then throw an exception if you try to MoveToCover with a dead actor, for example, but I probably wouldn&#8217;t rely on catching such cases as normal flow control (reserving that exception for truly exceptional cases).</p>
<p>Since we&#8217;re specifically talking about using coroutines in a separate thread to execute actions that may take place over several frames (and communicate back to other threads), there are all the usual issues of making sure the invariants truly stay invariant while a function (or in this case coroutine) is running, but between yields, presumably we can get updates that would terminate (or put on hold) coroutines which are no longer valid, such as &#8220;this monster just died.&#8221; </p>
<p>I get the feeling I might be misunderstanding the problem. I&#8217;m by no means an expert with this stuff, but I hope that helps.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jeff</title>
		<link>http://www.jeffongames.com/2010/02/do-continuations-make-sense/comment-page-1/#comment-43455</link>
		<dc:creator>Jeff</dc:creator>
		<pubDate>Sat, 27 Feb 2010 00:17:27 +0000</pubDate>
		<guid isPermaLink="false">http://www.jeffongames.com/?p=238#comment-43455</guid>
		<description>@jdinolt Ah, i think I see the difference, but my question would still be, how do you solve the problem in co-routines? And is it necessarily bad to implement co-routines this way?

@Yilmaz Unfortunately the MS CLR has no concept of actual co-routines and ownership.  You have to hold on to the enumerator which is essentially the stack information.

@Tomat Not sure Trampolining solves my problem.</description>
		<content:encoded><![CDATA[<p>@jdinolt Ah, i think I see the difference, but my question would still be, how do you solve the problem in co-routines? And is it necessarily bad to implement co-routines this way?</p>
<p>@Yilmaz Unfortunately the MS CLR has no concept of actual co-routines and ownership.  You have to hold on to the enumerator which is essentially the stack information.</p>
<p>@Tomat Not sure Trampolining solves my problem.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Tomat</title>
		<link>http://www.jeffongames.com/2010/02/do-continuations-make-sense/comment-page-1/#comment-43444</link>
		<dc:creator>Tomat</dc:creator>
		<pubDate>Fri, 26 Feb 2010 23:15:27 +0000</pubDate>
		<guid isPermaLink="false">http://www.jeffongames.com/?p=238#comment-43444</guid>
		<description>its better to do this check
          if (!Alive)
               yield break;
a part of action itself not the part of a sequence

In that case action will break sequence if something goes wrong according to action&#039;s logic.

Or even get rid of enumeration style and do pure continuation as explained here &quot;Stackless C# - Trampolining, Continuations and Erlang in .Net&quot; http://refractalize.blogspot.com/2009/02/stackless-c-trampolining-continuations_21.html</description>
		<content:encoded><![CDATA[<p>its better to do this check<br />
          if (!Alive)<br />
               yield break;<br />
a part of action itself not the part of a sequence</p>
<p>In that case action will break sequence if something goes wrong according to action&#8217;s logic.</p>
<p>Or even get rid of enumeration style and do pure continuation as explained here &#8220;Stackless C# &#8211; Trampolining, Continuations and Erlang in .Net&#8221; <a href="http://refractalize.blogspot.com/2009/02/stackless-c-trampolining-continuations_21.html" rel="nofollow">http://refractalize.blogspot.com/2009/02/stackless-c-trampolining-continuations_21.html</a></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Yilmaz Kiymaz</title>
		<link>http://www.jeffongames.com/2010/02/do-continuations-make-sense/comment-page-1/#comment-43412</link>
		<dc:creator>Yilmaz Kiymaz</dc:creator>
		<pubDate>Fri, 26 Feb 2010 21:16:09 +0000</pubDate>
		<guid isPermaLink="false">http://www.jeffongames.com/?p=238#comment-43412</guid>
		<description>I&#039;ve run into the same problem with Continuations (within the context of Unity.) One solution to the &quot;Alive&quot; problem is stopping any continuations running on the current script with a call like StopCoroutines() (which exists in Unity) upon the death of the AI. Still, it doesn&#039;t fully solve the overall problem of irregular interruptions to the regular flow of the state diagram.</description>
		<content:encoded><![CDATA[<p>I&#8217;ve run into the same problem with Continuations (within the context of Unity.) One solution to the &#8220;Alive&#8221; problem is stopping any continuations running on the current script with a call like StopCoroutines() (which exists in Unity) upon the death of the AI. Still, it doesn&#8217;t fully solve the overall problem of irregular interruptions to the regular flow of the state diagram.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: jdinolt</title>
		<link>http://www.jeffongames.com/2010/02/do-continuations-make-sense/comment-page-1/#comment-43410</link>
		<dc:creator>jdinolt</dc:creator>
		<pubDate>Fri, 26 Feb 2010 21:09:35 +0000</pubDate>
		<guid isPermaLink="false">http://www.jeffongames.com/?p=238#comment-43410</guid>
		<description>You&#039;ve described a problem with co-routines, not continuations. Continuations can be used to implement co-routines (in languages that support continuations of course), but that&#039;s not exactly what they&#039;re for.</description>
		<content:encoded><![CDATA[<p>You&#8217;ve described a problem with co-routines, not continuations. Continuations can be used to implement co-routines (in languages that support continuations of course), but that&#8217;s not exactly what they&#8217;re for.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
