42
42
class ASetByte :
43
43
def __init__ (self ):
44
44
self ._ba = bytearray (32 )
45
- self ._eve = asyncio .Event ()
46
- self ._eve .set () # Empty event initially set
47
45
self ._evdis = asyncio .Event () # Discard event
48
46
49
47
def __bool__ (self ):
@@ -53,17 +51,11 @@ def __contains__(self, i):
53
51
return (self ._ba [i >> 3 ] & 1 << (i & 7 )) > 0
54
52
55
53
def add (self , i ):
56
- self ._eve .clear ()
57
54
self ._ba [i >> 3 ] |= 1 << (i & 7 )
58
55
59
56
def discard (self , i ):
60
57
self ._ba [i >> 3 ] &= ~ (1 << (i & 7 ))
61
58
self ._evdis .set ()
62
- if not any (self ._ba ):
63
- self ._eve .set ()
64
-
65
- async def wait_empty (self ): # Pause until empty
66
- await self ._eve .wait ()
67
59
68
60
async def has_not (self , i ): # Pause until i not in set
69
61
while i in self :
@@ -140,6 +132,7 @@ def inner(feed=WDT_CB):
140
132
self ._evfail = asyncio .Event () # Set by any comms failure
141
133
self ._evok = asyncio .Event () # Set by 1st successful read
142
134
self ._s_lock = asyncio .Lock () # For internal send conflict.
135
+ self ._w_lock = asyncio .Lock () # For .write rate limit
143
136
self ._last_wr = utime .ticks_ms ()
144
137
self ._lineq = Queue (20 ) # 20 entries
145
138
self .connects = 0 # Connect count for test purposes/app access
@@ -162,15 +155,19 @@ async def readline(self):
162
155
163
156
async def write (self , buf , qos = True , wait = True ):
164
157
if qos and wait : # Disallow concurrent writes
165
- await self ._acks_pend .wait_empty ()
166
- # Prepend message ID to a copy of buf
167
- fstr = '{:02x}{}' if buf .endswith ('\n ' ) else '{:02x}{}\n '
168
- mid = next (getmid )
169
- self ._acks_pend .add (mid )
170
- buf = fstr .format (mid , buf )
171
- await self ._write (buf )
172
- if qos : # Return when an ACK received
173
- await self ._do_qos (mid , buf )
158
+ await self ._w_lock .acquire ()
159
+ try : # In case of cancellation/timeout
160
+ # Prepend message ID to a copy of buf
161
+ fstr = '{:02x}{}' if buf .endswith ('\n ' ) else '{:02x}{}\n '
162
+ mid = next (getmid )
163
+ self ._acks_pend .add (mid )
164
+ buf = fstr .format (mid , buf )
165
+ await self ._write (buf )
166
+ if qos : # Return when an ACK received
167
+ await self ._do_qos (mid , buf )
168
+ finally :
169
+ if qos and wait :
170
+ self ._w_lock .release ()
174
171
175
172
def close (self ):
176
173
self ._close () # Close socket and WDT
0 commit comments