<html><body>On 01:53 pm, daniel@keystonewood.com wrote:<br />&gt;On Apr 5, 2007, at 5:53 AM, glyph@divmod.com wrote:<br />&gt;&gt; &gt;&gt;I'm afraid that the feature you want doesn't make any sense and &#160;is, &#160;in <br />&gt;&gt;a<br />&gt;&gt; &gt;&gt;broad sense, impossible.<br />&gt;&gt;<br />&gt;&gt; &gt;Maybe it's impossible for you to see things the way I see them &#160; because <br />&gt;&gt;you<br />&gt;&gt; &gt;have become drunk on Twisted Kool-Aide.<br />&gt;&gt;<br />&gt;&gt;You are making it sound like you are bringing a fresh new idea to &#160;the <br />&gt;&gt;discussion here, which I've never heard before and am unwilling &#160;to <br />&gt;&gt;consider because I'm inflexible in my thinking. &#160;That's not &#160;what's <br />&gt;&gt;happening.<br />&gt;<br />&gt;I'm sorry I wrote that...it was inflammatory and did not bring any &#160;value to <br />&gt;the conversation. Please accept my apology.<br /><br />Thank you, I very much appreciate the sentiment! &#160;I'm glad to see you also only quoted the actually useful / productive parts of my response too ;).<br /><br />&gt;The external "blocking" resource is just a shell script that takes &#160;some <br />&gt;time t run. It does not acquire any shared resources that would &#160;result in <br />&gt;dead lock and it will always return (maybe with an error, &#160;but it will <br />&gt;return) unless something terrible happens (e.g. plug is &#160;pulled on server, <br />&gt;fire, etc.).<br /><br />I thought I understood what was going on, but now I'm confused again. &#160;Why do you need mutual exclusion at all if it doesn't acquire any shared resources? &#160;Couldn't you just run it concurrently?<br /><br />&gt;It would be more maintainable because it would look just like normal <br />&gt;sequential python code:<br /><br />Yes, it would *look* like sequential python code. &#160;But it wouldn't be :). &#160;There's a heck of a lot that can happen in acquire(); your whole application could run for ten minutes on that one line of code. &#160;Worst of all, it would only happen in extreme situations, so testing or debugging issues that are caused by it becomes even more difficult.<br /><br />&lt;snip blocking code&gt;<br /><br />&gt;This is very simple and very easy to maintain. It could be written &#160;with <br />&gt;inlineCallbacks fairly easily as well:<br />&gt;<br />&gt;yield lock.acquire()<br />&gt;try:<br />&gt; &#160; &#160; yield process.check_call(...)<br />&gt; &#160; &#160; yeild process.check_call(...)<br />&gt;finally:<br />&gt; &#160; &#160; lock.release()<br />&gt;<br />&gt;That's pretty nice (so nice I might just rewrite my code that way).<br /><br />I'm glad you think so. &#160;I was originally not too happy about inlineCallbacks (its predecessors did not do so well) but I keep seeing examples like this which it makes look much nicer.<br /><br />&gt;My complaint is that the code must have knowledge of the twisted &#160;environment <br />&gt;(why else would it yield the result of process.check_call ()?). I do not <br />&gt;really see the conceptual difference between these two &#160;code blocks except <br />&gt;one yields to and one calls into the reactor event &#160;loop. Is there some <br />&gt;other inherent problem with the first example? Of &#160;course you need to make <br />&gt;sure that the code inside the try/finally &#160;block does not try to acquire the <br />&gt;lock again, but that's a basic &#160;concurrency problem which can even happen in <br />&gt;the next example.<br /><br />This is really the key thing. &#160;If you're running your code in the Twisted environment, and you want it to be correct, it really must know about the Twisted environment. &#160;The simple presence of the 'yield' keyword at every level where a Deferred is being returned forces you to acknowledge, "yes, I know that a context switch may occur here". &#160;Without it, any function could suddenly and radically change the assumptions that all of its callers were allowed to make.<br /><br />&gt;Moving on, in a fully deferred world we have this:<br /><br />&lt;snip ugly stuff&gt;<br /><br />&gt;... you get the picture.<br />&gt;<br />&gt;Notice the code to acquire/release the lock--there are three &#160;different <br />&gt;calls to lock.release() in there, and they all must be &#160;carefully sorted out <br />&gt;to make sure that exactly one of them will be &#160;called in any given scenario <br />&gt;--that's hard to maintain.<br /><br />There are other ways to deal with that. &#160;maybeDeferred, for example, will make sure you always get a Deferred back and that it looks vaguely correct.<br /><br />&gt;Right, that would work and that's exactly what subprocess.check_call () (the <br />&gt;real python built-in version) would do. Unfortunately twisted &#160;does not work <br />&gt;with the subprocess module--spawnProcess() is the only &#160;alternative I found <br />&gt;that actually works and that means I have to use &#160;a deferred.<br /><br />The only thing I have to say about that is:<br />&#160; &#160; http://twistedmatrix.com/trac/ticket/733<br /><br />&gt;&gt;Another solution here would be for Twisted to have a nice &#160;convenience API <br />&gt;&gt;for dispatching tasks to a process pool. &#160;Right now &#160;setting up a process <br />&gt;&gt;pool is conceptually easy but mechanically &#160;difficult; you have to do a lot <br />&gt;&gt;of typing and make a lot of &#160;irrelevant decisions (AMP or PB or pickle? <br />&gt;&gt;stdio or sockets?).<br />&gt;<br />&gt;That sounds nice.<br /><br />Something I'd be doing in my copious spare time, if I had any.<br /><br />&gt;I understand that PB is fully symmetrical. In my case I am only using &#160;half <br />&gt;(client makes request, server responds). Would it make sense to &#160;relax the <br />&gt;constraints when PB is used in this way?<br /><br />I don't know if it would be feasible to do the work required for PB, due to other, less fundamental implementation issues. &#160;However, it was a design goal of AMP that it be possible to implement a "naive", only-a-few-lines-of-Python version for drop-in ease-of-use comparable to XMLRPC while still providing the actual "good" version in Twisted itself. &#160;I have heard rumors to the effect that Eric Mangold actually wrote such a thing, but I don't know where it is.<br /><br />&gt;&gt;#2545.<br />&gt;<br />&gt;This looks very interesting. I'll try to help out with this effort if &#160;I can <br />&gt;find some time.<br /><br />Thanks.<br /><br />&gt;Thanks for taking time to read my ramblings and understand the &#160;problems <br />&gt;that I am having (even if we don't quite agree on the &#160;simplest solutions). <br />&gt;Your input is valuable, and I am indebted to you &#160;for providing free support <br />&gt;in your spare time.<br /><br />Thanks very much for taking the time to acknowledge this. &#160;You leave me here with the impression that writing these emails was time well spent. &#160;And, thanks in advance for working on any of those tickets I gave you links to ;-).<br /><br /></body></html>