Skip to content

Commit 589b4ab

Browse files
committed
fix: deal with the threads being initialized in the process_frame callback with a threading.Lock
1 parent 259d87f commit 589b4ab

File tree

6 files changed

+228
-206
lines changed

6 files changed

+228
-206
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## Upcoming
4+
5+
- fix: deal with the threads being initialized in the `process_frame` callback with a `threading.Lock`
6+
37
## Version 0.12.3
48

59
- chore: update dependencies, update code with the latest ruff and pyright rules

demo.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,24 +60,25 @@ def build(self) -> FboGridLayout:
6060
"""Build the demo application."""
6161
fbg = FboGridLayout(rows=2, cols=2)
6262

63+
shape_by_label = {}
6364
for index, color in enumerate(
6465
[(1, 0, 0, 1), (0, 1, 0, 1), (0, 0, 1, 1), (1, 1, 0, 0)],
6566
):
6667
label = Label(text=f'Hello {index}')
6768

6869
with label.canvas.before:
6970
Color(*color)
70-
label.shape = Ellipse()
71+
shape_by_label[label] = Ellipse()
7172

7273
label.bind(
7374
size=lambda label, *_: (
7475
setattr(
75-
label.shape,
76+
shape_by_label[label],
7677
'size',
7778
(label.size[0] / 2, label.size[1] / 2),
7879
),
7980
setattr(
80-
label.shape,
81+
shape_by_label[label],
8182
'pos',
8283
(
8384
label.pos[0] + label.size[0] / 4,
@@ -86,7 +87,7 @@ def build(self) -> FboGridLayout:
8687
),
8788
),
8889
pos=lambda label, *_: setattr(
89-
label.shape,
90+
shape_by_label[label],
9091
'pos',
9192
(
9293
label.pos[0] + label.size[0] / 4,

headless_kivy/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
if TYPE_CHECKING:
3030
from numpy._typing import NDArray # pyright: ignore[reportPrivateImportUsage]
3131

32-
kivy.require('2.1.0')
32+
kivy.require('2.1.0') # pyright: ignore[reportAttributeAccessIssue]
3333

3434

3535
class SetupHeadlessConfig(TypedDict):

headless_kivy/widget.py

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66

77
from __future__ import annotations
88

9+
import contextlib
910
import threading
1011
import time
11-
from queue import Queue
12+
from queue import Empty, Queue
1213
from threading import Thread
1314
from typing import TYPE_CHECKING, ClassVar
1415

@@ -67,6 +68,7 @@ def __init__(self: HeadlessWidget, **kwargs: object) -> None:
6768

6869
__import__('kivy.core.window')
6970

71+
self.thread_lock = threading.Lock()
7072
self.last_thread: threading.Thread | None = None
7173
self.last_render = 0
7274
self.render_queue = Queue(2 if config.double_buffering() else 1)
@@ -171,19 +173,20 @@ def process_frame(self: HeadlessWidget, *_: object) -> None:
171173
if not np.any(mask):
172174
return
173175

174-
self.last_thread = Thread(
175-
target=self.render,
176-
kwargs={
177-
'mask': mask,
178-
'data': data,
179-
'x': x,
180-
'y': y,
181-
'last_thread': self.last_thread,
182-
},
183-
daemon=False,
184-
)
185-
self.render_queue.put(self.last_thread)
186-
self.last_thread.start()
176+
with self.thread_lock:
177+
new_thread = self.last_thread = Thread(
178+
target=self.render,
179+
kwargs={
180+
'mask': mask,
181+
'data': data,
182+
'x': x,
183+
'y': y,
184+
'last_thread': self.last_thread,
185+
},
186+
daemon=False,
187+
)
188+
self.render_queue.put(new_thread)
189+
new_thread.start()
187190
self.last_render = time.time()
188191

189192
def render(
@@ -271,7 +274,8 @@ def render(
271274
for region in regions
272275
],
273276
)
274-
self.render_queue.get_nowait()
277+
with contextlib.suppress(Empty):
278+
self.render_queue.get_nowait()
275279

276280
@classmethod
277281
def get_instance(

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ profile = "black"
8989
[tool.pyright]
9090
exclude = ['typings', '.venv']
9191
filterwarnings = 'error'
92+
disableTaggedHints = true
9293

9394
[tool.coverage.report]
9495
exclude_also = ["if TYPE_CHECKING:"]

0 commit comments

Comments
 (0)