Skip to content

Commit ce55a2b

Browse files
committed
Threading, Coroutines
1 parent e4a3870 commit ce55a2b

File tree

3 files changed

+38
-38
lines changed

3 files changed

+38
-38
lines changed

README.md

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,15 +2258,15 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
22582258

22592259
### Lock
22602260
```python
2261-
<lock> = Lock/RLock() # RLock can only be released by acquirer.
2262-
<lock>.acquire() # Waits for the lock to be available.
2263-
<lock>.release() # Makes the lock available again.
2261+
<lock> = Lock/RLock() # RLock can only be released by acquirer thread.
2262+
<lock>.acquire() # Blocks (waits) until lock becomes available.
2263+
<lock>.release() # It makes the acquired lock available again.
22642264
```
22652265

22662266
#### Or:
22672267
```python
2268-
with <lock>: # Enters the block by calling acquire() and
2269-
... # exits it with release(), even on error.
2268+
with <lock>: # Enters the block by calling method acquire().
2269+
... # Exits by calling release(), even on error.
22702270
```
22712271

22722272
### Semaphore, Event, Barrier
@@ -2278,24 +2278,24 @@ with <lock>: # Enters the block by calling acq
22782278

22792279
### Queue
22802280
```python
2281-
<Queue> = queue.Queue(maxsize=0) # A thread-safe first-in-first-out queue.
2282-
<Queue>.put(<el>) # Blocks until queue stops being full.
2283-
<Queue>.put_nowait(<el>) # Raises queue.Full exception if full.
2284-
<el> = <Queue>.get() # Blocks until queue stops being empty.
2285-
<el> = <Queue>.get_nowait() # Raises queue.Empty exception if empty.
2281+
<Queue> = queue.Queue(maxsize=0) # A first-in-first-out queue. It's thread safe.
2282+
<Queue>.put(<obj>) # Call blocks until queue stops being full.
2283+
<Queue>.put_nowait(<obj>) # Raises queue.Full exception if queue is full.
2284+
<obj> = <Queue>.get() # Call blocks until queue stops being empty.
2285+
<obj> = <Queue>.get_nowait() # Raises queue.Empty exception if it's empty.
22862286
```
22872287

22882288
### Thread Pool Executor
22892289
```python
22902290
<Exec> = ThreadPoolExecutor(max_workers=None) # Also `with ThreadPoolExecutor() as <name>: …`.
22912291
<iter> = <Exec>.map(<func>, <args_1>, ...) # Multithreaded and non-lazy map(). Keeps order.
22922292
<Futr> = <Exec>.submit(<func>, <arg_1>, ...) # Creates a thread and returns its Future obj.
2293-
<Exec>.shutdown() # Waits for all submitted threads to finish.
2293+
<Exec>.shutdown() # Waits for all threads to finish executing.
22942294
```
22952295

22962296
```python
22972297
<bool> = <Future>.done() # Checks if the thread has finished executing.
2298-
<obj> = <Future>.result(timeout=None) # Waits for thread to finish and returns result.
2298+
<obj> = <Future>.result(timeout=None) # Raises TimeoutError after 'timeout' seconds.
22992299
<bool> = <Future>.cancel() # Cancels or returns False if running/finished.
23002300
<iter> = as_completed(<coll_of_Futures>) # `next(<iter>)` returns next completed Future.
23012301
```
@@ -2306,8 +2306,8 @@ with <lock>: # Enters the block by calling acq
23062306

23072307
Coroutines
23082308
----------
2309-
* **Coroutines have a lot in common with threads, but unlike threads, they only give up control when they call another coroutine and they don’t use as much memory.**
2310-
* **Coroutine definition starts with `'async'` and its call with `'await'`.**
2309+
* **Coroutines have a lot in common with threads, but unlike threads, they only give up control when they call another coroutine and they don’t consume as much memory.**
2310+
* **Coroutine definition starts with `'async'` and its call with `'await'` keyword.**
23112311
* **Use `'asyncio.run(<coroutine>)'` to start the first/main coroutine.**
23122312

23132313
```python
@@ -2316,7 +2316,7 @@ import asyncio as aio
23162316

23172317
```python
23182318
<coro> = <async_function>(<args>) # Creates a coroutine by calling async def function.
2319-
<obj> = await <coroutine> # Starts the coroutine and waits for its result.
2319+
<obj> = await <coroutine> # Starts the coroutine. Returns its result or None.
23202320
<task> = aio.create_task(<coroutine>) # Schedules it for execution. Always keep the task.
23212321
<obj> = await <task> # Returns coroutine's result. Also <task>.cancel().
23222322
```
@@ -2344,7 +2344,7 @@ async def main_coroutine(screen):
23442344
moves = asyncio.Queue()
23452345
state = {'*': P(0, 0)} | {id_: P(W//2, H//2) for id_ in range(10)}
23462346
ai = [random_controller(id_, moves) for id_ in range(10)]
2347-
mvc = [human_controller(screen, moves), model(moves, state), view(state, screen)]
2347+
mvc = [controller(screen, moves), model(moves, state), view(state, screen)]
23482348
tasks = [asyncio.create_task(coro) for coro in ai + mvc]
23492349
await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
23502350

@@ -2354,7 +2354,7 @@ async def random_controller(id_, moves):
23542354
moves.put_nowait((id_, d))
23552355
await asyncio.sleep(random.triangular(0.01, 0.65))
23562356

2357-
async def human_controller(screen, moves):
2357+
async def controller(screen, moves):
23582358
while True:
23592359
key_mappings = {258: D.s, 259: D.n, 260: D.w, 261: D.e}
23602360
if d := key_mappings.get(screen.getch()):

index.html

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656

5757
<body>
5858
<header>
59-
<aside>July 31, 2025</aside>
59+
<aside>September 4, 2025</aside>
6060
<a href="https://gto76.github.io" rel="author">Jure Šorn</a>
6161
</header>
6262

@@ -1863,35 +1863,35 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
18631863
<li><strong>Use <code class="python hljs"><span class="hljs-string">'kwargs=&lt;dict&gt;'</span></code> to pass keyword arguments to the function.</strong></li>
18641864
<li><strong>Use <code class="python hljs"><span class="hljs-string">'daemon=True'</span></code>, or the program won't be able to exit while the thread is alive.</strong></li>
18651865
</ul>
1866-
<div><h3 id="lock">Lock</h3><pre><code class="python language-python hljs">&lt;lock&gt; = Lock/RLock() <span class="hljs-comment"># RLock can only be released by acquirer.</span>
1867-
&lt;lock&gt;.acquire() <span class="hljs-comment"># Waits for the lock to be available.</span>
1868-
&lt;lock&gt;.release() <span class="hljs-comment"># Makes the lock available again.</span>
1866+
<div><h3 id="lock">Lock</h3><pre><code class="python language-python hljs">&lt;lock&gt; = Lock/RLock() <span class="hljs-comment"># RLock can only be released by acquirer thread.</span>
1867+
&lt;lock&gt;.acquire() <span class="hljs-comment"># Blocks (waits) until lock becomes available.</span>
1868+
&lt;lock&gt;.release() <span class="hljs-comment"># It makes the acquired lock available again.</span>
18691869
</code></pre></div>
18701870

1871-
<div><h4 id="or-1">Or:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">with</span> &lt;lock&gt;: <span class="hljs-comment"># Enters the block by calling acquire() and</span>
1872-
... <span class="hljs-comment"># exits it with release(), even on error.</span>
1871+
<div><h4 id="or-1">Or:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">with</span> &lt;lock&gt;: <span class="hljs-comment"># Enters the block by calling method acquire().</span>
1872+
... <span class="hljs-comment"># Exits by calling release(), even on error.</span>
18731873
</code></pre></div>
18741874

18751875
<div><h3 id="semaphoreeventbarrier">Semaphore, Event, Barrier</h3><pre><code class="python language-python hljs">&lt;Semaphore&gt; = Semaphore(value=<span class="hljs-number">1</span>) <span class="hljs-comment"># Lock that can be acquired by 'value' threads.</span>
18761876
&lt;Event&gt; = Event() <span class="hljs-comment"># Method wait() blocks until set() is called.</span>
18771877
&lt;Barrier&gt; = Barrier(n_times) <span class="hljs-comment"># Wait() blocks until it's called n times.</span>
18781878
</code></pre></div>
18791879

1880-
<div><h3 id="queue">Queue</h3><pre><code class="python language-python hljs">&lt;Queue&gt; = queue.Queue(maxsize=<span class="hljs-number">0</span>) <span class="hljs-comment"># A thread-safe first-in-first-out queue.</span>
1881-
&lt;Queue&gt;.put(&lt;el&gt;) <span class="hljs-comment"># Blocks until queue stops being full.</span>
1882-
&lt;Queue&gt;.put_nowait(&lt;el&gt;) <span class="hljs-comment"># Raises queue.Full exception if full.</span>
1883-
&lt;el&gt; = &lt;Queue&gt;.get() <span class="hljs-comment"># Blocks until queue stops being empty.</span>
1884-
&lt;el&gt; = &lt;Queue&gt;.get_nowait() <span class="hljs-comment"># Raises queue.Empty exception if empty.</span>
1880+
<div><h3 id="queue">Queue</h3><pre><code class="python language-python hljs">&lt;Queue&gt; = queue.Queue(maxsize=<span class="hljs-number">0</span>) <span class="hljs-comment"># A first-in-first-out queue. It's thread safe.</span>
1881+
&lt;Queue&gt;.put(&lt;obj&gt;) <span class="hljs-comment"># Call blocks until queue stops being full.</span>
1882+
&lt;Queue&gt;.put_nowait(&lt;obj&gt;) <span class="hljs-comment"># Raises queue.Full exception if queue is full.</span>
1883+
&lt;obj&gt; = &lt;Queue&gt;.get() <span class="hljs-comment"># Call blocks until queue stops being empty.</span>
1884+
&lt;obj&gt; = &lt;Queue&gt;.get_nowait() <span class="hljs-comment"># Raises queue.Empty exception if it's empty.</span>
18851885
</code></pre></div>
18861886

18871887
<div><h3 id="threadpoolexecutor">Thread Pool Executor</h3><pre><code class="python language-python hljs">&lt;Exec&gt; = ThreadPoolExecutor(max_workers=<span class="hljs-keyword">None</span>) <span class="hljs-comment"># Also `with ThreadPoolExecutor() as &lt;name&gt;: …`.</span>
18881888
&lt;iter&gt; = &lt;Exec&gt;.map(&lt;func&gt;, &lt;args_1&gt;, ...) <span class="hljs-comment"># Multithreaded and non-lazy map(). Keeps order.</span>
18891889
&lt;Futr&gt; = &lt;Exec&gt;.submit(&lt;func&gt;, &lt;arg_1&gt;, ...) <span class="hljs-comment"># Creates a thread and returns its Future obj.</span>
1890-
&lt;Exec&gt;.shutdown() <span class="hljs-comment"># Waits for all submitted threads to finish.</span>
1890+
&lt;Exec&gt;.shutdown() <span class="hljs-comment"># Waits for all threads to finish executing.</span>
18911891
</code></pre></div>
18921892

18931893
<pre><code class="python language-python hljs">&lt;bool&gt; = &lt;Future&gt;.done() <span class="hljs-comment"># Checks if the thread has finished executing.</span>
1894-
&lt;obj&gt; = &lt;Future&gt;.result(timeout=<span class="hljs-keyword">None</span>) <span class="hljs-comment"># Waits for thread to finish and returns result.</span>
1894+
&lt;obj&gt; = &lt;Future&gt;.result(timeout=<span class="hljs-keyword">None</span>) <span class="hljs-comment"># Raises TimeoutError after 'timeout' seconds.</span>
18951895
&lt;bool&gt; = &lt;Future&gt;.cancel() <span class="hljs-comment"># Cancels or returns False if running/finished.</span>
18961896
&lt;iter&gt; = as_completed(&lt;coll_of_Futures&gt;) <span class="hljs-comment"># `next(&lt;iter&gt;)` returns next completed Future.</span>
18971897
</code></pre>
@@ -1901,15 +1901,15 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
19011901
<li><strong>ProcessPoolExecutor provides true parallelism but: everything sent to/from workers must be <a href="#pickle">pickable</a>, queues must be sent using executor's 'initargs' and 'initializer' parameters, and executor should only be reachable via <code class="python hljs"><span class="hljs-string">'if __name__ == "__main__": ...'</span></code>.</strong></li>
19021902
</ul>
19031903
<div><h2 id="coroutines"><a href="#coroutines" name="coroutines">#</a>Coroutines</h2><ul>
1904-
<li><strong>Coroutines have a lot in common with threads, but unlike threads, they only give up control when they call another coroutine and they don’t use as much memory.</strong></li>
1905-
<li><strong>Coroutine definition starts with <code class="python hljs"><span class="hljs-string">'async'</span></code> and its call with <code class="python hljs"><span class="hljs-string">'await'</span></code>.</strong></li>
1904+
<li><strong>Coroutines have a lot in common with threads, but unlike threads, they only give up control when they call another coroutine and they don’t consume as much memory.</strong></li>
1905+
<li><strong>Coroutine definition starts with <code class="python hljs"><span class="hljs-string">'async'</span></code> and its call with <code class="python hljs"><span class="hljs-string">'await'</span></code> keyword.</strong></li>
19061906
<li><strong>Use <code class="python hljs"><span class="hljs-string">'asyncio.run(&lt;coroutine&gt;)'</span></code> to start the first/main coroutine.</strong></li>
19071907
</ul><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> asyncio <span class="hljs-keyword">as</span> aio
19081908
</code></pre></div>
19091909

19101910

19111911
<pre><code class="python language-python hljs">&lt;coro&gt; = &lt;async_function&gt;(&lt;args&gt;) <span class="hljs-comment"># Creates a coroutine by calling async def function.</span>
1912-
&lt;obj&gt; = <span class="hljs-keyword">await</span> &lt;coroutine&gt; <span class="hljs-comment"># Starts the coroutine and waits for its result.</span>
1912+
&lt;obj&gt; = <span class="hljs-keyword">await</span> &lt;coroutine&gt; <span class="hljs-comment"># Starts the coroutine. Returns its result or None.</span>
19131913
&lt;task&gt; = aio.create_task(&lt;coroutine&gt;) <span class="hljs-comment"># Schedules it for execution. Always keep the task.</span>
19141914
&lt;obj&gt; = <span class="hljs-keyword">await</span> &lt;task&gt; <span class="hljs-comment"># Returns coroutine's result. Also &lt;task&gt;.cancel().</span>
19151915
</code></pre>
@@ -1932,7 +1932,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
19321932
moves = asyncio.Queue()
19331933
state = {<span class="hljs-string">'*'</span>: P(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>)} | {id_: P(W//<span class="hljs-number">2</span>, H//<span class="hljs-number">2</span>) <span class="hljs-keyword">for</span> id_ <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>)}
19341934
ai = [random_controller(id_, moves) <span class="hljs-keyword">for</span> id_ <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>)]
1935-
mvc = [human_controller(screen, moves), model(moves, state), view(state, screen)]
1935+
mvc = [controller(screen, moves), model(moves, state), view(state, screen)]
19361936
tasks = [asyncio.create_task(coro) <span class="hljs-keyword">for</span> coro <span class="hljs-keyword">in</span> ai + mvc]
19371937
<span class="hljs-keyword">await</span> asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
19381938

@@ -1942,7 +1942,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
19421942
moves.put_nowait((id_, d))
19431943
<span class="hljs-keyword">await</span> asyncio.sleep(random.triangular(<span class="hljs-number">0.01</span>, <span class="hljs-number">0.65</span>))
19441944

1945-
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">human_controller</span><span class="hljs-params">(screen, moves)</span>:</span>
1945+
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">controller</span><span class="hljs-params">(screen, moves)</span>:</span>
19461946
<span class="hljs-keyword">while</span> <span class="hljs-keyword">True</span>:
19471947
key_mappings = {<span class="hljs-number">258</span>: D.s, <span class="hljs-number">259</span>: D.n, <span class="hljs-number">260</span>: D.w, <span class="hljs-number">261</span>: D.e}
19481948
<span class="hljs-keyword">if</span> d := key_mappings.get(screen.getch()):
@@ -2934,7 +2934,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
29342934

29352935

29362936
<footer>
2937-
<aside>July 31, 2025</aside>
2937+
<aside>September 4, 2025</aside>
29382938
<a href="https://gto76.github.io" rel="author">Jure Šorn</a>
29392939
</footer>
29402940

parse.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ const COROUTINES =
133133
' moves = asyncio.Queue()\n' +
134134
' state = {<span class="hljs-string">\'*\'</span>: P(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>)} | {id_: P(W//<span class="hljs-number">2</span>, H//<span class="hljs-number">2</span>) <span class="hljs-keyword">for</span> id_ <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>)}\n' +
135135
' ai = [random_controller(id_, moves) <span class="hljs-keyword">for</span> id_ <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>)]\n' +
136-
' mvc = [human_controller(screen, moves), model(moves, state), view(state, screen)]\n' +
136+
' mvc = [controller(screen, moves), model(moves, state), view(state, screen)]\n' +
137137
' tasks = [asyncio.create_task(coro) <span class="hljs-keyword">for</span> coro <span class="hljs-keyword">in</span> ai + mvc]\n' +
138138
' <span class="hljs-keyword">await</span> asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)\n' +
139139
'\n' +
@@ -143,7 +143,7 @@ const COROUTINES =
143143
' moves.put_nowait((id_, d))\n' +
144144
' <span class="hljs-keyword">await</span> asyncio.sleep(random.triangular(<span class="hljs-number">0.01</span>, <span class="hljs-number">0.65</span>))\n' +
145145
'\n' +
146-
'<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">human_controller</span><span class="hljs-params">(screen, moves)</span>:</span>\n' +
146+
'<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">controller</span><span class="hljs-params">(screen, moves)</span>:</span>\n' +
147147
' <span class="hljs-keyword">while</span> <span class="hljs-keyword">True</span>:\n' +
148148
' key_mappings = {<span class="hljs-number">258</span>: D.s, <span class="hljs-number">259</span>: D.n, <span class="hljs-number">260</span>: D.w, <span class="hljs-number">261</span>: D.e}\n' +
149149
' <span class="hljs-keyword">if</span> d := key_mappings.get(screen.getch()):\n' +

0 commit comments

Comments
 (0)