feat(thread-pool): Expose thread_pool component via the x-platform libraries (c++/python) - #680
Conversation
|
✅Static analysis result - no issues found! ✅ |
thread_pool component via the x-platform libraries (c++/python)
There was a problem hiding this comment.
⚠️ Not ready to approve
The current Python binding/stub updates introduce deadlock risk (missing GIL release on blocking calls) and invalid/incorrect .pyi/test-script content that should be fixed before approval.
Pull request overview
This PR exposes the existing thread_pool component through the cross-platform “pc” C++ library and the Python bindings, enabling espp::ThreadPool usage on desktop (C++/Python) and adding corresponding example-style tests.
Changes:
- Add
thread_poolinclude + source wiring to the x-platform CMake build and umbrella header. - Generate/introduce
ThreadPoolPython bindings (pybind) and corresponding type stubs. - Add PC and Python ThreadPool test programs; normalize some documentation punctuation (em-dash → hyphen) across several headers.
File summaries
| File | Description |
|---|---|
| python/thread_pool.py | Adds a Python test script exercising the ThreadPool binding API. |
| pc/tests/thread_pool.cpp | Adds a PC-side C++ test executable for ThreadPool behavior. |
| lib/python_bindings/pybind_espp.cpp | Exposes espp::ThreadPool (and Stats/Config) via pybind11. |
| lib/python_bindings/espp/init.pyi | Updates autogenerated Python typing stubs, including new ThreadPool stubs. |
| lib/include/espp.hpp | Exposes thread_pool.hpp via the umbrella include. |
| lib/espp.cmake | Adds thread_pool include dir + source file to the pc library build inputs. |
| lib/autogenerate_bindings.py | Adds thread_pool.hpp to the binding autogeneration inputs (after dependencies). |
| components/thread_pool/include/thread_pool.hpp | Minor doc/comment formatting tweaks in ThreadPool header. |
| components/touch/include/touch.hpp | Doc/comment punctuation normalization. |
| components/st7123touch/include/st7123touch.hpp | Doc/comment punctuation normalization. |
| components/rtsp/include/rtsp_session.hpp | Doc/comment punctuation normalization. |
| components/rtsp/include/rtsp_client.hpp | Doc/comment punctuation normalization. |
| components/rtsp/include/h264_packetizer.hpp | Doc/comment punctuation normalization. |
| components/rtsp/include/h264_depacketizer.hpp | Doc/comment punctuation normalization. |
| components/rtps/include/rtps.hpp | Doc/comment punctuation normalization. |
| components/m5stack-tab5/include/m5stack-tab5.hpp | Doc/comment punctuation normalization. |
| components/esp32-p4-function-ev-board/include/esp32-p4-function-ev-board.hpp | Doc/comment punctuation normalization. |
Review details
- Files reviewed: 17/17 changed files
- Comments generated: 6
- Review effort level: Low
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
There was a problem hiding this comment.
⚠️ Not ready to approve
The new ThreadPool Python surface has correctness/type-safety issues (stub types + constructor signature) and a real GIL/deadlock risk for blocking submit() that should be addressed before approval.
Review details
Comments suppressed due to low confidence (4)
python/thread_pool.py:284
- Same issue in the try_submit producer:
c7_donemay be set after the first job since it compares againsttotal_accepted7[0](initially 0). This can let the test proceed without waiting for the expected TOTAL jobs to complete.
with c7_lock:
c7[0] += 1
if c7[0] >= total_accepted7[0]:
c7_done.set()
lib/python_bindings/pybind_espp.cpp:2466
ThreadPool.submit()can block (bounded queue +block_on_submit_when_full=true), but the binding does not release the GIL forsubmit. This can deadlock if worker threads need the GIL to run Python callbacks while the submitting thread is blocked in C++ holding the GIL.
.def("submit", &espp::ThreadPool::submit, py::arg("job"),
"/ @brief Submit a job, optionally blocking when the queue is full.\n/\n/ Blocks if "
"Config::block_on_submit_when_full is True and the queue has\n/ reached its capacity "
"limit. Otherwise behaves identically to try_submit().\n/ @param job Callable to "
"enqueue; moved into the queue on acceptance.\n/ @return True if the job was accepted, "
"False if it was rejected.")
lib/python_bindings/espp/init.pyi:3785
- The stubs introduce
job: Jobin the ThreadPool API, butJobis not defined/imported anywhere in the .pyi. This breaks type checking for any consumer using the new ThreadPool binding.
#################### <generated_from:thread_pool.hpp> ####################
lib/python_bindings/espp/init.pyi:3923
- The ThreadPool binding is constructed with a
Configin Python (ThreadPool(Config(...))), but the stub only declares a no-arg__init__. This makes the new API appear unusable to type checkers/IDEs.
def __init__(self) -> None:
"""Auto-generated default constructor"""
pass
- Files reviewed: 17/17 changed files
- Comments generated: 3
- Review effort level: Low
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
There was a problem hiding this comment.
⚠️ Not ready to approve
The new lib/python_bindings/espp/__init__.pyi ThreadPool stub currently contains invalid Python syntax and mismatched/undefined types, which will break stub consumers.
Review details
Comments suppressed due to low confidence (5)
lib/python_bindings/pybind_espp.cpp:2397
- ThreadPool::Stats.rejected docstring is truncated (ends at "or queue"), which makes the Python binding documentation misleading.
.def_readwrite("rejected", &espp::ThreadPool::Stats::rejected,
"/< Total jobs rejected (invalid job, stopped/stopping, or queue");
lib/python_bindings/espp/init.pyi:3841
- The ThreadPool.Config stub uses C++-style comments ("///<") and designated-initializer syntax (".name = ...") inside a Python call, which makes this .pyi file invalid Python syntax.
worker_task_config: Task.BaseConfig = Task.BaseConfig(
///< Base configuration applied to every worker task.
.name = "thread_pool_worker",
.stack_size_bytes = 4096,
.priority = 5,
lib/python_bindings/espp/init.pyi:3884
- ThreadPool.submit() uses an undefined type name
Jobin the stub. This breaks type checking; the binding accepts a Python callable, so the stub should use a defined type (at leastobject).
def submit(self, job: Job) -> bool:
lib/python_bindings/espp/init.pyi:3894
- ThreadPool.try_submit() uses an undefined type name
Jobin the stub. This breaks type checking; the binding accepts a Python callable, so the stub should use a defined type (at leastobject).
def try_submit(self, job: Job) -> bool:
lib/python_bindings/espp/init.pyi:3923
- The stub declares a zero-arg ThreadPool() constructor, but the binding registers only
py::init<const ThreadPool::Config &>(), so Python callers must pass a Config instance. The stub should match the bound signature.
def __init__(self) -> None:
"""Auto-generated default constructor"""
pass
- Files reviewed: 17/17 changed files
- Comments generated: 1
- Review effort level: Low
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
⚠️ Not ready to approve
The generated Python stubs introduce invalid .pyi syntax (and undefined types) and the Python ThreadPool test has a potential deadlock path due to unchecked wait timeouts.
Review details
Comments suppressed due to low confidence (5)
lib/python_bindings/espp/init.pyi:3841
- The generated type stub introduces invalid Python syntax in the default value for
worker_task_config(C++-style///<comment and designated-initializer.name = ...), which makes__init__.pyiunparsable.
worker_task_config: Task.BaseConfig = Task.BaseConfig(
///< Base configuration applied to every worker task.
.name = "thread_pool_worker",
.stack_size_bytes = 4096,
.priority = 5,
lib/python_bindings/espp/init.pyi:3852
- The
ThreadPool.Config.__init__signature uses an invalid default expression (Task.BaseConfig(///< ... .name = ...)), which is not valid Python syntax for stubs and will break parsing/type-checking.
block_on_submit_when_full: bool = False,
worker_task_config: Task.BaseConfig = Task.BaseConfig(///< Base configuration applied to every worker task.
.name = "thread_pool_worker",
lib/python_bindings/pybind_espp.cpp:2397
- The docstring for
ThreadPool::Stats.rejectedis truncated (ends at "or queue"), which makes the Python API docs misleading compared to the C++ header comment.
.def_readwrite("rejected", &espp::ThreadPool::Stats::rejected,
"/< Total jobs rejected (invalid job, stopped/stopping, or queue");
lib/python_bindings/espp/init.pyi:3884
Jobis not defined anywhere in the stub file, sodef submit(self, job: Job)will cause name-resolution/type-checking errors. Usingobjecthere avoids an undefined type while still accurately reflecting that any callable-like Python object is accepted.
def submit(self, job: Job) -> bool:
lib/python_bindings/espp/init.pyi:3894
Jobis not defined anywhere in the stub file, sodef try_submit(self, job: Job)will cause name-resolution/type-checking errors. Usingobjecthere avoids an undefined type while still accurately reflecting that any callable-like Python object is accepted.
def try_submit(self, job: Job) -> bool:
- Files reviewed: 17/17 changed files
- Comments generated: 1
- Review effort level: Low
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 18 changed files in this pull request and generated 7 comments.
Comments suppressed due to low confidence (1)
python/thread_pool_test.py:1
- The determinism of the ‘queue is full’ assertions depends on
first_started.wait(...)andall_fill_done.wait(...)actually completing. Currently the code ignores the Event.wait() return value, so on a slow/loaded system the test may proceed without the queue being full (or stop before all fill jobs complete), producing flaky/invalid results. Treat a timeout as a hard failure (setpassed = False, print a FAIL, and ensure the pool is released/stop is still called) before proceeding to rejection checks.
"""ThreadPool Python test.
There was a problem hiding this comment.
⚠️ Not ready to approve
The generated Python stubs (__init__.pyi) currently disagree with the runtime bindings (invalid enum member defaults, undefined Job type, and incorrect ThreadPool.__init__ signature), which will break type-checking and IDE usage.
Review details
Comments suppressed due to low confidence (5)
lib/python_bindings/pybind_espp.cpp:2397
- ThreadPool.Stats.rejected docstring is truncated (ends at "or queue"), which makes the generated Python docs misleading. It should include the full explanation from thread_pool.hpp about queue-full rejection and dropped jobs on stop().
.def_readwrite("rejected", &espp::ThreadPool::Stats::rejected,
"/< Total jobs rejected (invalid job, stopped/stopping, or queue");
lib/python_bindings/espp/init.pyi:3884
- ThreadPool.submit() references a "Job" type that is not defined anywhere in this stub file, which will cause type-checker errors when importing the stubs.
def submit(self, job: Job) -> bool:
lib/python_bindings/espp/init.pyi:3894
- ThreadPool.try_submit() references a "Job" type that is not defined anywhere in this stub file, which will cause type-checker errors when importing the stubs.
def try_submit(self, job: Job) -> bool:
lib/python_bindings/espp/init.pyi:3923
- ThreadPool is not default-constructible in the bindings (pybind exposes only init(config: ThreadPool.Config)), but the stub currently declares a no-arg init(). This makes the stub disagree with the runtime API.
def __init__(self) -> None:
"""Auto-generated default constructor"""
pass
lib/python_bindings/espp/init.pyi:753
- The Logger.Config constructor default uses Logger.Verbosity.WARN, but the Verbosity enum exposed by pybind uses lowercase member names (debug/info/warn/error/none). As written, this default is an invalid attribute reference for type checkers; similar uppercase Verbosity defaults elsewhere in the stub likely have the same issue.
tag: str = str(),
include_time: bool = bool(True),
rate_limit: std.chrono.duration[float] = std.chrono.duration<float>(0),
level: Logger.Verbosity = Logger.Verbosity.WARN
) -> None:
- Files reviewed: 18/18 changed files
- Comments generated: 0 new
- Review effort level: Low
Note
Your feedback helps us improve the quality of this feature.
Please use 👍 or 👎 to tell us whether this assessment is correct.
Description
expose the thread_pool
Motivation and Context
expose the thread_pool via the x-platform libraries, so it can be used on pc with cpp or python
Also update some components' comment to fix some UTF-8 Issues only happened in Windows.
How has this been tested?
added test under pc/ and python/
Screenshots (if appropriate, e.g. schematic, board, console logs, lab pictures):
Python:

PC:

Types of changes
Checklist:
Software
.github/workflows/build.ymlfile to add my new test to the automated cloud build github action.Hardware