[Stackless] stacklesslib.async

Kristján Valur Jónsson kristjan at ccpgames.com
Mon Sep 9 13:41:22 CEST 2013


Hm, I had another look at
http://docs.python.org/3.2/library/concurrent.futures.html
This is actually quite similar to the stuff I had done.  Since it exists, we also avoid bikeshedding about names :)
I'll start by modifying my code to fit this model, then we can think about what to do for 3.2.  Perhaps backporting the concurrent.futures stuff to 2.7stackless makes sense .
K

From: stackless-bounces at stackless.com [mailto:stackless-bounces at stackless.com] On Behalf Of Kristján Valur Jónsson
Sent: 9. september 2013 10:42
To: The Stackless Python Mailing List
Subject: Re: [Stackless] stacklesslib.async

weeeeelll
What actually led me on this path was this excellent blog post showing what is wrong with JS and how C#Async makes things human readable again :)

http://tirania.org/blog/archive/2013/Aug-15.html

I'm still working on the " Task based" model, takin into account some of Richard's previous comments here,
and experinmenting with the "Async and await" thing at the same time.  I'll show you something soon, hopefully even with useful code.

Then, Python 3 already has "futures".  One of the things I wanted to do was to create a "tasklet" future plugin to that, and port the future module back to 2.7
There were some issues with that, I think I arrived at the conclusion that the futures model was too complicated, or something....



From: stackless-bounces at stackless.com<mailto:stackless-bounces at stackless.com> [mailto:stackless-bounces at stackless.com] On Behalf Of lars van Gemerden
Sent: 7. september 2013 08:06
To: The Stackless Python Mailing List
Subject: Re: [Stackless] stacklesslib.async

without examining the details, i am not sure if this achieves the same thing but this reminds me somewhat of the promises and deferreds in the javascript dojo library: http://dojotoolkit.org/reference-guide/1.9/dojo/Deferred.html.

e.g. i use this in:

        getObject: function(way, path, callback){
            return xhr.get("/object/"+way+"/"+path, {
                handleAs:"json"
            }).then(function(json_object){
                callback(json_object);
            }, function(err){
                console.error(err);
            });
        },

xhr.get() is an AJAX call and the result of the call is handeled async in the then() method. I have no idea how this is implemented in js, but i like the api as being intuitive.

You can also chain these so called promises: some_func_returning_promise().then().then().then()

Cheers, Lars

On Wed, Sep 4, 2013 at 12:52 AM, Richard Tew <richard.m.tew at gmail.com<mailto:richard.m.tew at gmail.com>> wrote:
I think that unless you are intentionally presenting an identical API,
using classes as a namespacing extension as they do in C# and Java is
probably avoided.  When I program in C# and Java, I often get the
feeling that they do things some ways because they have to, because
they don't have better fitting alternatives.

I do not find function names beginning with "when" intuitive, and find
it hard to suggest better alternatives as they just confuse me and I
am not quite sure what they are supposed to do.

Whether you are polling to see if things are ready, or getting what
they have made ready, deciding on the best function name seems like
something best considered with  all things in mind.  Like whether you
want the call to wait with a timeout.  Whether exceptions are raised
or returned.

The C# exception wrapping has always seemed like an approach they have
adopted because of architectural limitations.

I would rather the following was done:

  for task in tasks:
    try:
        result = task.invoke_result()
    except:
        # handle

I chose invoke rather than get, because it is more evocative of the
result also reasonably being an exception.

Other approaches could force complexity in order to be able to provide
"helper" methods, when it might be worth considering whether it is
possible to avoid them in the first place.

Or:

  try:
    result = async.invoke_one_result_picked_out_at_random(tasks)
  except:
    # handle

.. where a task with a result or error returns or raises respectively,
as a successful result of a call choosing that task.

Then there are your decorators in your original post.  I look at them,
and I don't quite feel they are the right approach.  Firstly, when you
wrap a function with them, if that function is general purpose, then
isn't it now locked into the async system and no longer suitable for
calls made from outside of it?  And secondly, the functions they wrap
look like synchronous functions when actually called, despite now
being magicked into some magical task creation that works on in the
background while returning to the original function.

I'm still not clear on why indexes are returned, rather than tasks directly.

For a lot of this, I think that best choices can be made in view of a
complete list of intended functionality.  Something like:

Lists of tasks:
- Get all results for a list of tasks, whether returned or exceptions raised.
- Get one result from a list of tasks, whether returned or exceptions raised.
- Get the set of completed tasks from a list of tasks.

Per-task:
- Get the result, whether returned or exception raised.

Does there have to be timeout functionality for these calls?  I think
there does.  How is that handled?


On Wed, Sep 4, 2013 at 1:25 AM, Kristján Valur Jónsson
<kristjan at ccpgames.com<mailto:kristjan at ccpgames.com>> wrote:
> Thanks for your feedback.
> The original "Task" interface in C# is perhaps not something we need to closely follow.
> As I understand it, "task based asynchronous programming" came before the "await" semantics.
> It makes a distinction between waiting for a result, and returning its value.  Although Wait will throw an exception if task execution throws an exception....
> So anyway, I _think_ that in C# you
> t.Wait()
> return t.Result
>
> which separates these things awkwardly.
>
> In my implementation of async.Task, I added a get_result() which combines the two.
>
> I think it makes sense to create a module function, get_all_results() which operates on an iterable of Tasks. and returns a list of actual values, or raises an exception
> This can be augmented with a "when_all_results()" function which returns a Task object.
> Simlilarly "get_any_result()" returning an index and value, and "when_any_result"
>
> This could then be used in preference to the Task-like WaitAll or WaitAny et al.
>
> I also think I prefer module global functions to class methods, what do you think?
>
> One interesting thing that .NET does, and these functions, is that they throw "AggregateException" wrapping the original error.  "await" does not.
> Do you have any thought on that?
>
> See:
>
> http://stackoverflow.com/questions/18314961/i-want-await-to-throw-aggregateexception-not-just-the-first-exception
>
>
>
>> -----Original Message-----
>> From: stackless-bounces at stackless.com<mailto:stackless-bounces at stackless.com> [mailto:stackless-<mailto:stackless->
>> bounces at stackless.com<mailto:bounces at stackless.com>] On Behalf Of Richard Tew
>> Sent: 2. september 2013 23:06
>> To: The Stackless Python Mailing List
>> Subject: Re: [Stackless] stacklesslib.async
>>
>> I think this general sort of functionality has long been needed in Stackless,
>> and it brings up the old sawhorse of why are we not including stacklesslib in
>> Stackless distribution.  But let's ignore that for now.
>>
>> I like the idea of having a standard well received API from another popular
>> language, that people can just pick up and use with approximately same
>> namespace - even if the coding standards for this specific API conflict with
>> the rest of the package.
>>
>> That said I don't get the API.  It seems badly designed.
>>
>> To me, not having looked at the C# API much, I expect waitAll and waitAny
>> should return the result of the tasks that completed with the index of each in
>> the list.
>>
>> [ (0, text), ] = x.waitAny([ t1, t2 ])
>>
>> And whenAll and whenAny should imply there's a result, but not pull it.
>>
>> [ 0 ] = async.whenAny([ t1, t2 ])
>>
>> Then again, why return indexes.  That just means you have to waste time
>> holding onto the original list, if you do not have a permanent one.
>>
>> But I think that this should not just handle tasklet completion, it should also
>> handle tasklets producing results via channels.  In that case, it is useful to poll
>> whether any tasklets have results, rather than waitX with a minimum
>> timeout.
>>
>> I think that this should be in, but there surely can be a more natural fit.  And
>> this might mean a requirement for lower level support.
>>
>> And having written all this, the elephant in the room is that I believe CSP,
>> which Andrew Francis has long been advocating, is closer to what I think we
>> need.  However, I've long had problems with using it ad hoc, as I think it is not
>> that user friendly and is more theoretically balanced than functionally
>> balanced.
>>
>> Cheers,
>> Richard.
>>
>> _______________________________________________
>> Stackless mailing list
>> Stackless at stackless.com<mailto:Stackless at stackless.com>
>> http://www.stackless.com/mailman/listinfo/stackless
>
>
>
> _______________________________________________
> Stackless mailing list
> Stackless at stackless.com<mailto:Stackless at stackless.com>
> http://www.stackless.com/mailman/listinfo/stackless

_______________________________________________
Stackless mailing list
Stackless at stackless.com<mailto:Stackless at stackless.com>
http://www.stackless.com/mailman/listinfo/stackless



--
====================================
Lars van Gemerden
lars at rational-it.com<mailto:lars at rational-it.com>
+31 6 26 88 55 39
====================================
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.stackless.com/pipermail/stackless/attachments/20130909/9d98f358/attachment-0001.html>


More information about the Stackless mailing list