mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-04 22:35:08 +00:00
fix(display): thread-safety for deferred updates, BDF faces and follower image; one refresh default (#652)
- DisplayManager.defer_update()/process_deferred_updates(): one lock around every queue mutation (appends from the update thread were lost to the render thread's filter/slice reassignments); callables run outside it. - FontManager and element_style no longer cache BDF freetype.Face objects process-wide (load_bdf_face caches them per thread); element_style's LRU is locked against get/move_to_end vs eviction races. - limit_refresh_rate_hz default is one constant, DEFAULT_REFRESH_LIMIT_HZ = 100 (the template's), for the library options, refresh_hz, the matrix guard, Vegas and scroll_config. Previously a missing key capped the panel at 90 while pacing assumed 100. - Sync follower: the TCP thread queues the leader's scroll image; the render thread swaps image/array/width in between frames. - update_display() error log rate-limited (traceback first, then once a minute with a count); swallowed DisplayController exceptions log at DEBUG. - Root display_controller.py runs run.py via runpy. - stream_manager: correct the RLock release comments; merge duplicate if. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -122,4 +122,24 @@ def test_display_manager_defaults_match_display_manager():
|
||||
for field, value in ms.DISPLAY_MANAGER_DEFAULTS.items():
|
||||
if field in ('rows', 'cols', 'chain_length', 'parallel'):
|
||||
continue # read through display_geometry's DEFAULT_* constants
|
||||
if field == 'limit_refresh_rate_hz':
|
||||
assert "get('limit_refresh_rate_hz', DEFAULT_REFRESH_LIMIT_HZ)" in source
|
||||
continue
|
||||
assert f"get('{field}', {value!r})" in source, field
|
||||
|
||||
|
||||
def test_missing_refresh_limit_applies_the_rate_pacing_assumes():
|
||||
"""With limit_refresh_rate_hz absent the library was capped at 90 Hz while
|
||||
refresh_hz (what scroll pacing solves against) reported 100. One default,
|
||||
and it is the template's."""
|
||||
import os
|
||||
from types import SimpleNamespace
|
||||
os.environ.setdefault("EMULATOR", "true") # import off-Pi, as other modules do
|
||||
from src.display_manager import DisplayManager
|
||||
|
||||
options = DisplayManager.apply_matrix_options(SimpleNamespace(), {})
|
||||
reported = DisplayManager.refresh_hz.fget(SimpleNamespace(config={}))
|
||||
assert options.limit_refresh_rate_hz == reported
|
||||
template = json.loads((REPO_ROOT / 'config' / 'config.template.json').read_text(encoding='utf-8'))
|
||||
assert options.limit_refresh_rate_hz == template['display']['hardware']['limit_refresh_rate_hz']
|
||||
assert ms.DISPLAY_MANAGER_DEFAULTS['limit_refresh_rate_hz'] == options.limit_refresh_rate_hz
|
||||
|
||||
Reference in New Issue
Block a user