I spent today learning about asynchronous programming and these are my notes related to it.
So, there are two kinds of systems -> synchronous and asynchronous.
In a synchronous system, you wait for a task to finish COMPLETELY before you move on to some other task
In an asynchronous system, you move on to some other task before it finishes. This allows more parallelism.
- If we want to do something asynchronously in programming language, we use event loop
- Event loop can do following things:
- register tasks to be executed
- execute the tasks
- delay execution of tasks
- cancel tasks
- Every event is attached to event listener or else the event gets lost
- The main purpose of an event loop is:
- run first function
- while that function waits for IO, event loop pauses it and runs another function
- when the first function returns result then it resumes it
- used to create iterators
- generators return multiple items but NOT as a list. They return items one by one
Difference between a normal callback function and a generator:
|Normal callback function approach||Generator approach|
|After collecting ALL the results, it displays them altogether|| It displays result as it finds them.
A function becomes a generator when it uses “yield”
Difference between a normal return statement and yield statement:
|In a function which uses return statement,
||In a function which uses a yield statement,
- Coroutine is basically used to allow to execute several tasks at once through non-preemptive multitasking
- It passes control to each subroutine, wait for it until it finishes off, we can re-enter the routine later and continue
- Coroutine can suspend itself. But once it actually exits/returns, then it cannot be resumed.
- There is no need to add a yield statement in a coroutine but the function called by a coroutine can have a yield statement
This is the most interesting concept.
- Future is one way to write asynchronous code
- Future is result of work that has not been completed yet
- future() method does not return a result, but returns a future object. When the task completes, the result is returned eventually. Meanwhile, next code is executed.
- When do we know that state of future has changed?
- when set_result() is called
- How to check that the task taken by future has been completed?
- by using event loop -> it watches state of future object to indicate that its done
- Future is a way of performing many tasks in parallel, in efficient, non-blocking way
- There are two cases:
- When computation of task does not complete -> future does not complete.
- When computation of task completes and returns either a result or exception -> future completes
- The result of returned by future() can be:
- value -> future completes successfully
- exception -> future has failed with an exception
- Future has an important property.
- It can be assigned only once
- Once it has been given a value, it becomes immutable and can never be over-written
- a subclass of future
- wraps a coroutine
- when coroutine is finished, it returns result then task is finished
- For asynchronous programming, we need event loop
- We register our tasks/ futures in the event loop
- The event loop schedules them and executes them
- Callbacks are used so that we are notified when tasks/ future return results
- Coroutines are wrapped in tasks/ futures
- when yield is finding, coroutine is paused
- when yield gets a value, coroutine continues
- If coroutine doesnot return a value but returns an exception, then task fails.
This is a simple program i tried with Python’s asyncio module:
Python asyncio module
basically defines a coroutine
loop = asyncio.get_event_loop()
creates an event loop
runs a loop until stop() method is called