2
2
3
3
There is often a need to provide synchronisation between coros. A common
4
4
example is to avoid what are known as "race conditions" where multiple coros
5
- compete to access a single resource. An example is provided in the `` aswitch.py ` `
5
+ compete to access a single resource. An example is provided in the ` aswitch.py `
6
6
program and discussed in [ the docs] ( ./DRIVERS.md ) . Another hazard is the "deadly
7
7
embrace" where two coros wait on the other's completion.
8
8
9
9
In simple applications these are often addressed with global flags. A more
10
- elegant approach is to use synchronisation primitives. The module `` asyn.py ` `
11
- offers "micro" implementations of `` Lock `` , `` Event `` , `` Barrier `` and `` Semaphore ` `
10
+ elegant approach is to use synchronisation primitives. The module ` asyn.py `
11
+ offers "micro" implementations of ` Lock ` , ` Event ` , ` Barrier ` and ` Semaphore `
12
12
primitives.
13
13
14
14
Another synchronisation issue arises with producer and consumer coros. The
15
- producer generates data which the consumer uses. Asyncio provides the `` Queue ` `
15
+ producer generates data which the consumer uses. Asyncio provides the ` Queue `
16
16
object. The producer puts data onto the queue while the consumer waits for its
17
- arrival (with other coros getting scheduled for the duration). The `` Queue ` `
17
+ arrival (with other coros getting scheduled for the duration). The ` Queue `
18
18
guarantees that items are removed in the order in which they were received. As
19
19
this is a part of the uasyncio library its use is described in the [ tutorial] ( ./TUTORIAL.md ) .
20
20
@@ -23,13 +23,13 @@ this is a part of the uasyncio library its use is described in the [tutorial](./
23
23
# 2. Modules
24
24
25
25
The following modules are provided:
26
- * `` asyn.py ` ` The main library.
27
- * `` asyntest.py ` ` Test/demo programs for the library.
26
+ * ` asyn.py ` The main library.
27
+ * ` asyntest.py ` Test/demo programs for the library.
28
28
29
29
These modules support CPython 3.5 and MicroPython on Unix and microcontroller
30
- targets. The library is for use only with asyncio. They are `` micro ` ` in design
30
+ targets. The library is for use only with asyncio. They are ` micro ` in design
31
31
and are presented as simple, concise examples of asyncio code. They are not
32
- thread safe. Hence they are incompatible with the `` _thread ` ` module and with
32
+ thread safe. Hence they are incompatible with the ` _thread ` module and with
33
33
interrupt handlers.
34
34
35
35
# 3. asyn.py
@@ -41,9 +41,9 @@ args. If the function is a callback it is executed with the supplied argumets.
41
41
If it is a coro, it is scheduled for execution.
42
42
43
43
args:
44
- * `` func ` ` Mandatory. a function or coro. These are provided 'as-is' i.e. not
44
+ * ` func ` Mandatory. a function or coro. These are provided 'as-is' i.e. not
45
45
using function call syntax.
46
- * `` tup_args `` Optional. A tuple of arguments, default `` () ` ` . The args are
46
+ * ` tup_args ` Optional. A tuple of arguments, default ` () ` . The args are
47
47
upacked when provided to the function.
48
48
49
49
## 3.2 Lock
@@ -52,12 +52,12 @@ This has now been superceded by the more efficient official version. See the
52
52
[ test program] ( https://github.com/micropython/micropython-lib/blob/master/uasyncio.synchro/example_lock.py ) .
53
53
For an example of how to use the preferred official version see [ this] ( ./TUTORIAL.md#31-lock ) .
54
54
55
- I have retained this version in `` asyn.py ` ` merely as an example of uasyncio
55
+ I have retained this version in ` asyn.py ` merely as an example of uasyncio
56
56
coding. The remainder of this section applies to this version.
57
57
58
58
This guarantees unique access to a shared resource. The preferred way to use it
59
- is via an asynchronous context manager. In the following code sample a `` Lock ` `
60
- instance `` lock ` ` has been created and is passed to all coros wishing to access
59
+ is via an asynchronous context manager. In the following code sample a ` Lock `
60
+ instance ` lock ` has been created and is passed to all coros wishing to access
61
61
the shared resource. Each coro issues the following:
62
62
63
63
``` python
@@ -66,30 +66,30 @@ async def bar(lock):
66
66
# Access resource
67
67
```
68
68
69
- While the coro `` bar ` ` is accessing the resource, other coros will pause at the
70
- `` async with lock `` statement until the context manager in `` bar() ` ` is
69
+ While the coro ` bar ` is accessing the resource, other coros will pause at the
70
+ ` async with lock ` statement until the context manager in ` bar() ` is
71
71
complete.
72
72
73
73
### 3.2.1 Definition
74
74
75
- Constructor: Optional argument `` delay_ms ` ` default 0. Sets a delay between
75
+ Constructor: Optional argument ` delay_ms ` default 0. Sets a delay between
76
76
attempts to acquire the lock. In applications with coros needing frequent
77
77
scheduling a nonzero value will facilitate this at the expense of latency.
78
78
Methods:
79
79
80
- * `` locked `` No args. Returns `` True ` ` if locked.
81
- * `` release ` ` No args. Releases the lock.
82
- * `` acquire ` ` No args. Coro which pauses until the lock has been acquired. Use
83
- by executing `` await lock.acquire() ` ` .
80
+ * ` locked ` No args. Returns ` True ` if locked.
81
+ * ` release ` No args. Releases the lock.
82
+ * ` acquire ` No args. Coro which pauses until the lock has been acquired. Use
83
+ by executing ` await lock.acquire() ` .
84
84
85
85
## 3.3 Event
86
86
87
87
This provides a way for one or more coros to pause until another one flags them
88
- to continue. An `` Event ` ` object is instantiated and passed to all coros using
89
- it. Coros waiting on the event issue `` await event ` ` . Execution pauses
90
- until a coro issues `` event.set() `` . `` event.clear() ` ` must then be issued. An
91
- optional data argument may be passed to `` event.set() ` ` and retrieved by
92
- `` event.value() ` ` .
88
+ to continue. An ` Event ` object is instantiated and passed to all coros using
89
+ it. Coros waiting on the event issue ` await event ` . Execution pauses
90
+ until a coro issues ` event.set() ` . ` event.clear() ` must then be issued. An
91
+ optional data argument may be passed to ` event.set() ` and retrieved by
92
+ ` event.value() ` .
93
93
94
94
In the usual case where a single coro is awaiting the event this can be done
95
95
immediately after it is received:
@@ -111,7 +111,7 @@ async def foo(event):
111
111
event.set()
112
112
```
113
113
114
- If multiple coros are to wait on a single event, consider using a `` Barrier ` `
114
+ If multiple coros are to wait on a single event, consider using a ` Barrier `
115
115
object described below. This is because the coro which raised the event has no
116
116
way to determine whether all others have received it; determining when to clear
117
117
it down requires further synchronisation. One way to achieve this is with an
@@ -123,49 +123,49 @@ async def eventwait(event, ack_event):
123
123
ack_event.set()
124
124
```
125
125
126
- Example of this are in `` event_test `` and `` ack_test ` ` in asyntest.py.
126
+ Example of this are in ` event_test ` and ` ack_test ` in asyntest.py.
127
127
128
128
### 3.3.1 Definition
129
129
130
130
Constructor: takes one optional boolean argument, defaulting False.
131
- * `` lp `` If `` True ` ` and the experimental low priority core.py is installed,
131
+ * ` lp ` If ` True ` and the experimental low priority core.py is installed,
132
132
low priority scheduling will be used while awaiting the event. If the standard
133
133
version of uasyncio is installed the arg will have no effect.
134
134
135
135
Synchronous Methods:
136
- * `` set `` Initiates the event. Optional arg `` data ` ` : may be of any type,
137
- sets the event's value. Default `` None ` ` .
138
- * `` clear `` No args. Clears the event, sets the value to `` None ` ` .
139
- * `` is_set `` No args. Returns `` True ` ` if the event is set.
140
- * `` value `` No args. Returns the value passed to `` set ` ` .
136
+ * ` set ` Initiates the event. Optional arg ` data ` : may be of any type,
137
+ sets the event's value. Default ` None ` .
138
+ * ` clear ` No args. Clears the event, sets the value to ` None ` .
139
+ * ` is_set ` No args. Returns ` True ` if the event is set.
140
+ * ` value ` No args. Returns the value passed to ` set ` .
141
141
142
142
The optional data value may be used to compensate for the latency in awaiting
143
- the event by passing `` loop.time() ` ` .
143
+ the event by passing ` loop.time() ` .
144
144
145
145
## 3.4 Barrier
146
146
147
147
This enables multiple coros to rendezvous at a particular point. For example
148
148
producer and consumer coros can synchronise at a point where the producer has
149
149
data available and the consumer is ready to use it. At that point in time the
150
- `` Barrier ` ` can optionally run a callback before releasing the barrier and
150
+ ` Barrier ` can optionally run a callback before releasing the barrier and
151
151
allowing all waiting coros to continue.
152
152
153
153
Constructor.
154
154
Mandatory arg:
155
- `` participants ` ` The number of coros which will wait on the barrier.
155
+ ` participants ` The number of coros which will wait on the barrier.
156
156
Optional args:
157
- `` func `` Callback to run. Default `` None ` ` .
158
- `` args `` Tuple of args for the callback. Default `` () ` ` .
157
+ ` func ` Callback to run. Default ` None ` .
158
+ ` args ` Tuple of args for the callback. Default ` () ` .
159
159
160
160
The callback can be a function or a coro. In most applications a function is
161
161
likely to be used: this can be guaranteed to run to completion beore the
162
162
barrier is released.
163
163
164
- The `` Barrier ` ` has no properties or methods for user access. Participant
165
- coros issue `` await my_barrier ` ` whereupon execution pauses until all other
164
+ The ` Barrier ` has no properties or methods for user access. Participant
165
+ coros issue ` await my_barrier ` whereupon execution pauses until all other
166
166
participants are also waiting on it. At this point any callback will run and
167
- then each participant will re-commence execution. See `` barrier_test ` ` and
168
- `` semaphore_test ` ` in asyntest.py for example usage.
167
+ then each participant will re-commence execution. See ` barrier_test ` and
168
+ ` semaphore_test ` in asyntest.py for example usage.
169
169
170
170
A special case of ` Barrier ` usage is where some coros are allowed to pass the
171
171
barrier, registering the fact that they have done so. At least one coro must
@@ -204,14 +204,14 @@ used to limit the number of instances of a particular coro which can run
204
204
concurrently. It performs this using an access counter which is initialised by
205
205
the constructor and decremented each time a coro acquires the semaphore.
206
206
207
- Constructor: Optional arg `` value ` ` default 1. Number of permitted concurrent
207
+ Constructor: Optional arg ` value ` default 1. Number of permitted concurrent
208
208
accesses.
209
209
210
210
Synchronous method:
211
- * `` release ` ` No args. Increments the access counter.
211
+ * ` release ` No args. Increments the access counter.
212
212
213
213
Asynchronous method:
214
- * `` acquire ` ` No args. If the access counter is greater than 0, decrements it
214
+ * ` acquire ` No args. If the access counter is greater than 0, decrements it
215
215
and terminates. Otherwise waits for it to become greater than 0 before
216
216
decrementing it and terminating.
217
217
@@ -223,25 +223,27 @@ async def foo(sema):
223
223
# Limited access here
224
224
```
225
225
226
- There is a difference between a `` Semaphore `` and a `` Lock `` . A `` Lock ` `
226
+ There is a difference between a ` Semaphore ` and a ` Lock ` . A ` Lock `
227
227
instance is owned by the coro which locked it: only that coro can release it. A
228
- `` Semaphore ` ` can be released by any coro which acquired it.
228
+ ` Semaphore ` can be released by any coro which acquired it.
229
229
230
230
### 3.5.1 BoundedSemaphore
231
231
232
- This works identically to the `` Semaphore `` class except that if the `` release ` `
233
- method causes the access counter to exceed its initial value, a `` ValueError ` `
232
+ This works identically to the ` Semaphore ` class except that if the ` release `
233
+ method causes the access counter to exceed its initial value, a ` ValueError `
234
234
is raised.
235
235
236
236
## 3.6 NamedCoro
237
237
238
238
This provides for coros to be readily identified by associating them with a
239
239
user-defined name, to enable them to be cancelled or to have an exception
240
- thrown to them. The `` NamedCoro ` ` class maintains a dict of coros indexed by
240
+ thrown to them. The ` NamedCoro ` class maintains a dict of coros indexed by
241
241
the name.
242
242
243
+ The ` NamedCoro ` class is an awaitable class.
244
+
243
245
Constructor mandatory args:
244
- * `` task ` ` A coro.
246
+ * ` task ` A coro.
245
247
* ` name ` Names may be any valid dictionary index. A ` ValueError ` will be
246
248
raised if the name already exists.
247
249
@@ -251,6 +253,7 @@ Class methods:
251
253
scheduled. The coro should trap this and quit ASAP. ` cancel ` will return
252
254
` True ` if the coro was cancelled or if it had already terminated. It will
253
255
return ` False ` if the coro is not in the dict or has already been killed.
256
+ * ` cancel_all ` No args. Cancel all running ` NamedCoro ` instances.
254
257
* ` pend_throw ` Args: 1. A coro name 2. An exception.
255
258
The named coro will receive the exception the next time it is scheduled.
256
259
@@ -266,15 +269,15 @@ existing applications but it will soon be removed.
266
269
267
270
# 4 asyntest.py
268
271
269
- This provides the following test/demo programs. Because `` uasyncio ` ` retains
272
+ This provides the following test/demo programs. Because ` uasyncio ` retains
270
273
state between runs, a soft reset (ctrl-D) should be issued after running a test
271
274
and before running another.
272
275
273
- * `` ack_test() `` Use of `` Event ` ` objects. Runs for 10s.
274
- * `` event_test() `` Use of `` Lock `` and `` Event ` ` objects.
275
- * `` barrier_test() `` Use of the `` Barrier ` ` class.
276
- * `` semaphore_test() `` Use of `` Semaphore `` objects. Call with a `` True ` ` arg
277
- to demonstrate the `` BoundedSemaphore ` ` error exception.
278
- * `` cancel_test1() ` ` Basic task cancellation.
279
- * `` cancel_test2() `` Task cacellation with a `` Barrier ` ` .
280
- * `` cancel_test3() ` ` Cancellation of a task which has terminated.
276
+ * ` ack_test() ` Use of ` Event ` objects. Runs for 10s.
277
+ * ` event_test() ` Use of ` Lock ` and ` Event ` objects.
278
+ * ` barrier_test() ` Use of the ` Barrier ` class.
279
+ * ` semaphore_test() ` Use of ` Semaphore ` objects. Call with a ` True ` arg
280
+ to demonstrate the ` BoundedSemaphore ` error exception.
281
+ * ` cancel_test1() ` Basic task cancellation.
282
+ * ` cancel_test2() ` Task cacellation with a ` Barrier ` .
283
+ * ` cancel_test3() ` Cancellation of a task which has terminated.
0 commit comments