Hi all, I'm starting a cute side-project called "Toro" where I adapt Python's and Gevent's synchronization primitives to Tornado. The first primitive is Gevent's AsyncResult<http://www.gevent.org/gevent.event.html#gevent.event.AsyncResult>. My API is like:
class AsyncResult: def get(self, callback, timeout): """Get the value that's been set. If callback provided, execute it with the value after set() is run, or execute it with None after timeout."""
def set(self, value): """Set the value, wake all waiters."""
The idea is for an async function to "block" waiting for another function to set a result:
@gen.engine def get_result(async_result): value = yield gen.Task(async_result.get) do_something_with(value)
Would some Tornado expert like to code-review my implementation so far, *particularly regarding exception-handling*? It's just a 60-line file and a 30-line test:
I'm particularly anxious to know if people think my exception-handling test expects the proper behavior, and if my use of stack_context.wrap() on line 69 is correct:
<ajesseda...@gmail.com> wrote:
> Hi all, I'm starting a cute side-project called "Toro" where I adapt
> Python's and Gevent's synchronization primitives to Tornado. The first
> primitive is Gevent's AsyncResult. My API is like:
> class AsyncResult:
> def get(self, callback, timeout):
> """Get the value that's been set.
> If callback provided, execute it with the value after set() is run,
> or execute it
> with None after timeout."""
> def set(self, value):
> """Set the value, wake all waiters."""
> The idea is for an async function to "block" waiting for another function to
> set a result:
> Would some Tornado expert like to code-review my implementation so far,
> particularly regarding exception-handling? It's just a 60-line file and a
> 30-line test:
> I'm particularly anxious to know if people think my exception-handling test
> expects the proper behavior, and if my use of stack_context.wrap() on line
> 69 is correct:
There's one issue with your stack_context handling.
It's good that you stack_context.wrap() the callback when setting it in
_Waiter.
You'll have to call that callback inside a NullContext() to prevent a
stack_context leak in set().
Take this scenario for example.
set()'s ExceptionStackContext will catch the exception in raise_callback().
---
def set_result():
with
stack_context.ExceptionStackContext(catch_set_result_exception):
result.set('hello')
def callback(value):
outcomes['value'] = value
loop.add_callback(raise_callback)
def raise_callback():
assert False
def catch_set_result_exception(type, value, traceback):
outcomes['set_result_exc'] = type
return True
> wrote:
> Hi all, I'm starting a cute side-project called "Toro" where I adapt
> Python's and Gevent's synchronization primitives to Tornado. The first
> primitive is Gevent's AsyncResult<http://www.gevent.org/gevent.event.html#gevent.event.AsyncResult>.
> My API is like:
> class AsyncResult:
> def get(self, callback, timeout):
> """Get the value that's been set.
> If callback provided, execute it with the value after set() is
> run, or execute it
> with None after timeout."""
> def set(self, value):
> """Set the value, wake all waiters."""
> The idea is for an async function to "block" waiting for another function
> to set a result:
> Would some Tornado expert like to code-review my implementation so far, *particularly
> regarding exception-handling*? It's just a 60-line file and a 30-line
> test:
> I'm particularly anxious to know if people think my exception-handling
> test expects the proper behavior, and if my use of stack_context.wrap() on
> line 69 is correct:
Good catch. This is actually changing in Tornado 3.0, so you won't
need the NullContext in the future. This leak happens when a callback
wrapped with no contexts is run under a StackContext; if both the
calls to get and set had separate contexts the leak wouldn't happen.
On Sat, Oct 13, 2012 at 2:24 AM, Roey Berman <roey.ber...@gmail.com> wrote:
> There's one issue with your stack_context handling.
> It's good that you stack_context.wrap() the callback when setting it in
> _Waiter.
> You'll have to call that callback inside a NullContext() to prevent a
> stack_context leak in set().
> Take this scenario for example.
> set()'s ExceptionStackContext will catch the exception in raise_callback().
> On Fri, Oct 12, 2012 at 6:14 AM, A. Jesse Jiryu Davis
> <ajesseda...@gmail.com> wrote:
>> Hi all, I'm starting a cute side-project called "Toro" where I adapt
>> Python's and Gevent's synchronization primitives to Tornado. The first
>> primitive is Gevent's AsyncResult. My API is like:
>> class AsyncResult:
>> def get(self, callback, timeout):
>> """Get the value that's been set.
>> If callback provided, execute it with the value after set() is
>> run, or execute it
>> with None after timeout."""
>> def set(self, value):
>> """Set the value, wake all waiters."""
>> The idea is for an async function to "block" waiting for another function
>> to set a result:
>> Would some Tornado expert like to code-review my implementation so far,
>> particularly regarding exception-handling? It's just a 60-line file and a
>> 30-line test:
>> I'm particularly anxious to know if people think my exception-handling
>> test expects the proper behavior, and if my use of stack_context.wrap() on
>> line 69 is correct:
On Saturday, October 13, 2012 12:35:54 PM UTC-4, Ben Darnell wrote:
> Good catch. This is actually changing in Tornado 3.0, so you won't > need the NullContext in the future. This leak happens when a callback > wrapped with no contexts is run under a StackContext; if both the > calls to get and set had separate contexts the leak wouldn't happen.
> -Ben
> On Sat, Oct 13, 2012 at 2:24 AM, Roey Berman <roey....@gmail.com<javascript:>> > wrote: > > There's one issue with your stack_context handling.
> > It's good that you stack_context.wrap() the callback when setting it in > > _Waiter. > > You'll have to call that callback inside a NullContext() to prevent a > > stack_context leak in set(). > > Take this scenario for example. > > set()'s ExceptionStackContext will catch the exception in > raise_callback().
> > On Fri, Oct 12, 2012 at 6:14 AM, A. Jesse Jiryu Davis > > <ajess...@gmail.com <javascript:>> wrote:
> >> Hi all, I'm starting a cute side-project called "Toro" where I adapt > >> Python's and Gevent's synchronization primitives to Tornado. The first > >> primitive is Gevent's AsyncResult. My API is like:
> >> class AsyncResult: > >> def get(self, callback, timeout): > >> """Get the value that's been set. > >> If callback provided, execute it with the value after set() is > >> run, or execute it > >> with None after timeout."""
> >> def set(self, value): > >> """Set the value, wake all waiters."""
> >> The idea is for an async function to "block" waiting for another > function > >> to set a result:
> >> Would some Tornado expert like to code-review my implementation so far, > >> particularly regarding exception-handling? It's just a 60-line file and > a > >> 30-line test:
> >> I'm particularly anxious to know if people think my exception-handling > >> test expects the proper behavior, and if my use of stack_context.wrap() > on > >> line 69 is correct: