On 2008-01-17 12:02, Jason Tackaberry wrote: > cb = kaa.ThreadCallback('thumbnailer', generate_thumbnail) > cb('file.jpg').connect(handle_thumbnail_done) >
I still like this API but I see a race condition here: if the thread executes and completes before connect() is called, handle_thumbnail_done will never see the result. This isn't a problem for coroutines since it's all confined to a single thread. This is fixable by attaching an internal handler that caches the result, and next time something connects to the InProgress returned by __call__ it emits the cached result. In fact, this functionality could be pushed down to the Signal class. Have a new method Signal.emit_deferred or something which will cache the args and emit them after the next handler is attached. On a related note, I'd like to update the yield_execution() decorator so that it returns an InProgress in every case. I recently updated it to just return the result if the decorated function doesn't yield anything (rather than before where it assumed there was a next member and if there wasn't raised an exception), but on second thought I think this is a bad idea. I think yield_execution should return an InProgress object no matter what, so that the caller is guaranteed to be able to connect to its return value. Here we can again use the Signal.emit_deferred method. I would also like it so that if the decorated function yields _anything_ (including None) it is automatically continued. I guess I never understood why it should be necessary to yield YieldContinue? If I have a function decorated with yield_execution and I yield something, when would I _not_ want it to be continued? So I'd like it that if it yields nothing (None), it behaves like YieldContinue, and if it yields a result, the InProgress signal is emitted with the result, and then it behaves like YieldContinue. In other words, I want to deprecate YieldContinue. So: @kaa.yield_execution() def foo(): return 42 @kaa.yield_execution() def bar(): yield 42 @kaa.yield_execution() def baz(): for i in range(10): yield i @kaa.yield_execution() def zap(): result = [] while do_some_work(result): yield yield result def handler(result): print "Result", result foo().connect(handler) bar().connect(handler) baz().connect(handler) zap().connect(handler) In the foo and bar cases, handler is called with the value 42, even though the functions actually complete before the handler is connected. (So Signal.emit_deferred will accomplish this.) In the baz case, handler is called 10 times, for each value. In the zap case, the function yields execution a number of times and the notifier loop periodically reenters it, until finally it yields result, and handler gets invoked with the result. (zap.next would be called once more after that, but it will immediately raise StopExecution and then it will not be called again.) Thoughts? ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ _______________________________________________ Freevo-devel mailing list Freevo-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/freevo-devel