Documentation for pulsar 0.9.2. For development docs, go here.

Asynchronous Components

There are three, closely related, ways to create asynchronous components in pulsar:

  • Directly create a of Future:

    import asyncio
    
    o = asyncio.Future()
    

    or, equivalently:

    import pulsar
    
    o = pulsar.Future()
    
  • A coroutine, a generator which consumes values. For example:

    from pulsar import coroutine_return
    
    def my_async_generator(...):
        yield something_but_dont_care_what_it_returns()
        ...
        bla = yield something_and_care_what_it_returns()
        result = yield do_something(bla)
        coroutine_return(result)
    

    a coroutine is obtained by calling the generator function:

    o = my_async_generator()
    

    Note that o is coroutine which has not yet started.

  • An asyncio.Task, is a component which has been added to pulsar asynchronous engine. It is created via the async() function when applied to a generator function or, equivalently, by the in_loop() and task() decorators:

    from pulsar import async
    
    def my_async_generator1(...):
        yield something_but_dont_care_what_it_returns()
        ...
        bla = yield something_and_care_what_it_returns()
        yield do_something(bla)
    
    task = async(my_async_generator2())
    

    A Task is a subclass of Future and therefore it has the same API, for example, you can add callbacks to a task:

    task.add_done_callback(...)
    

Coroutines

As mentioned above, a coroutine is a generator which consumes values. A pulsar coroutine can consume synchronous values as well as Future and other coroutines. Let’s consider the following code:

d = Future()

def do_something(...):
      yield something_but_dont_care_what_it_returns()
      ...
      bla = yield something_and_care_what_it_returns()
      result = yield do_something(bla)
      coroutine_return(result)

def my_async_generator():
      result = yield d
      yield do_something(result)

Then we create a coroutine by calling the my_async_generator generator function:

o = my_async_generator()

o is has not yet started. To use it, it must be added to pulsar asynchronous engine via the async() function:

task = async(o)

task is a Task instance.

Coroutines can return values via the coroutine_return() function. Otherwise they always return None (unless exceptions occur).

Task

A Task is a specialised Future which consumes coroutines. A coroutine is transformed into a Task via the async() function or the in_loop() and task() decorators.

A task consumes a coroutine until the coroutine yield an asynchronous component not yet done. When this appends, the task pauses and returns the control of execution. Before it returns, it adds a callback to the Future on which the coroutine is blocked to resume the coroutine once the future is called. A task in this state is said to be suspended.

Collections

When dealing with several asynchronous components in a collection such as a list, tuple, set or even a dictionary (values only, keys must be synchronous python types), one can use the multi_async() function to create an asynchronous component which will be ready once all the components are ready.



Table Of Contents

Previous topic

The Arbiter

Next topic

Actor messages

This Page