mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 19:40:18 +00:00
Create threading.md
This commit is contained in:
parent
cdbe55b539
commit
076627fb76
140
docs/features/threading.md
Normal file
140
docs/features/threading.md
Normal file
@ -0,0 +1,140 @@
|
||||
---
|
||||
icon: dot
|
||||
title: Threading
|
||||
---
|
||||
|
||||
pocketpy organizes its state by `VM` structure.
|
||||
Users can have at maximum 16 `VM` instances (index from 0 to 15).
|
||||
Each `VM` instance can only be accessed by exactly one thread at a time.
|
||||
If you are trying to run two python scripts in parallel refering the same `VM` instance,
|
||||
you will crash it definitely.
|
||||
|
||||
However, there are two ways to achieve multi-threading in pocketpy.
|
||||
|
||||
One way is to use a native threading library such as `pthread`.
|
||||
You can wrap the multi-threading logic into a C function and bind it to pocketpy.
|
||||
Be careful and not to access the same `VM` instance from multiple threads at the same time.
|
||||
You need to lock critical resources or perform a deep copy of all needed data.
|
||||
|
||||
## ComputeThread
|
||||
|
||||
The other way is to use `pkpy.ComputeThread`.
|
||||
It is like an isolate in Dart language.
|
||||
`ComputeThread` is a true multi-threading model to allow you run python scripts in parallel without lock,
|
||||
backed by a separate `VM` instance.
|
||||
|
||||
`ComputeThread` is highly designed for computational intensive tasks in games.
|
||||
For example, you can run game logic in main thread (VM 0) and run world generation in another thread (e.g. VM 1).
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph Main Thread
|
||||
A[Game Start]
|
||||
B[Submit WorldGen Job]
|
||||
C[Frame 1]
|
||||
D[Frame 2]
|
||||
E[Frame 3]
|
||||
F[...]
|
||||
G[Get WorldGen Result]
|
||||
H[Render World]
|
||||
end
|
||||
subgraph WorldGen Thread
|
||||
O[Generate Biomes]
|
||||
P[Generate Terrain]
|
||||
Q[Generate Creatures]
|
||||
R[Dump Result]
|
||||
end
|
||||
A --> B
|
||||
B --> C
|
||||
C --> D
|
||||
D --> E
|
||||
E --> F
|
||||
F --> G
|
||||
G --> H
|
||||
|
||||
O --> P
|
||||
P --> Q
|
||||
Q --> R
|
||||
|
||||
B --> O
|
||||
R --> G
|
||||
```
|
||||
|
||||
#### `main.py`
|
||||
```python
|
||||
import time
|
||||
from pkpy import ComputeThread
|
||||
|
||||
thread = ComputeThread(1)
|
||||
print("Game Start")
|
||||
|
||||
# import worldgen.py
|
||||
thread.exec_blocked('from worldgen import gen_world')
|
||||
|
||||
print("Submit WorldGen Job")
|
||||
thread.call('gen_world', 3, (100, 100), 10)
|
||||
|
||||
# wait for worldgen to finish
|
||||
for i in range(1, 100000):
|
||||
print('Frame:', i)
|
||||
time.sleep(1)
|
||||
if thread.is_done:
|
||||
break
|
||||
|
||||
error = thread.last_error()
|
||||
if error is not None:
|
||||
print("Error:", error)
|
||||
else:
|
||||
retval = thread.last_retval()
|
||||
biomes = retval['biomes']
|
||||
terrain = retval['terrain']
|
||||
creatures = retval['creatures']
|
||||
print("World Generation Complete", len(biomes), len(terrain), len(creatures))
|
||||
```
|
||||
|
||||
#### `worldgen.py`
|
||||
```python
|
||||
import time
|
||||
import random
|
||||
|
||||
def gen_world(biome_count: int, terrain_size: tuple[int, int], creature_count: int) -> dict:
|
||||
# simulate a long computation
|
||||
time.sleep(3)
|
||||
|
||||
# generate world data
|
||||
all_biomes = ["forest", "desert", "ocean", "mountain", "swamp"]
|
||||
all_creatures = ["wolf", "bear", "fish", "bird", "lizard"]
|
||||
|
||||
width, height = terrain_size
|
||||
|
||||
terrain_data = [
|
||||
random.randint(1, 10)
|
||||
for _ in range(width * height)
|
||||
]
|
||||
|
||||
creatures = [
|
||||
{
|
||||
"name": random.choice(all_creatures),
|
||||
"x": random.randint(0, width - 1),
|
||||
"y": random.randint(0, height - 1),
|
||||
}
|
||||
for i in range(creature_count)
|
||||
]
|
||||
|
||||
return {
|
||||
"biomes": all_biomes[:biome_count],
|
||||
"terrain": terrain_data,
|
||||
"creatures": creatures,
|
||||
}
|
||||
```
|
||||
|
||||
Run `main.py` and you will see the result like this:
|
||||
```
|
||||
Game Start
|
||||
Submit WorldGen Job
|
||||
Frame: 1
|
||||
Frame: 2
|
||||
Frame: 3
|
||||
Frame: 4
|
||||
World Generation Complete 3 10000 10
|
||||
```
|
Loading…
x
Reference in New Issue
Block a user