Skip to content

Add thread naming and thread-start callback for all library threads#14792

Open
surban wants to merge 1 commit intorealsenseai:developmentfrom
mlilabs:thread-spawn-callback
Open

Add thread naming and thread-start callback for all library threads#14792
surban wants to merge 1 commit intorealsenseai:developmentfrom
mlilabs:thread-spawn-callback

Conversation

@surban
Copy link
Contributor

@surban surban commented Mar 5, 2026

All threads created by the library are now named with an "rs:" prefix and assigned an OS-level thread name (via pthread_setname_np / SetThreadDescription).

A global thread-start callback can be registered via rs2_set_thread_start_callback() which is invoked from within each new thread before any work begins, allowing the caller to set thread priorities or perform other per-thread setup.

Each thread is classified into one of eight categories (rs2_thread_category): usb_io, video_capture, sensor_io, frame_processing, device_monitoring, dispatch, network, utility.

Changes:

  • New rsutils::concurrency::create_thread() helper with thread naming and callback
  • dispatcher, active_object, watchdog now require thread_category and thread_name
  • All ~50 thread creation sites migrated to create_thread or named constructors
  • Public C API: rs2_thread_category enum, rs2_set_thread_start_callback()
  • C++ API: rs2::set_thread_start_callback() convenience wrapper
  • Wrapper enum parity: Python, C#, Java, MATLAB, Unreal Engine 4

All threads created by the library are now named with an "rs:" prefix and
assigned an OS-level thread name (via pthread_setname_np / SetThreadDescription).

A global thread-start callback can be registered via rs2_set_thread_start_callback()
which is invoked from within each new thread before any work begins, allowing
the caller to set thread priorities or perform other per-thread setup.

Each thread is classified into one of eight categories (rs2_thread_category):
usb_io, video_capture, sensor_io, frame_processing, device_monitoring,
dispatch, network, utility.

Changes:
- New rsutils::concurrency::create_thread() helper with thread naming and callback
- dispatcher, active_object, watchdog now require thread_category and thread_name
- All ~50 thread creation sites migrated to create_thread or named constructors
- Public C API: rs2_thread_category enum, rs2_set_thread_start_callback()
- C++ API: rs2::set_thread_start_callback() convenience wrapper
- Wrapper enum parity: Python, C#, Java, MATLAB, Unreal Engine 4
Copilot AI review requested due to automatic review settings March 5, 2026 08:55
@sysrsbuild-gh
Copy link

Can one of the admins verify this patch?

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a unified mechanism for naming all library-created threads (with an rs: prefix and OS-level thread name) and introduces a global “thread-start” callback API surfaced consistently across C/C++ and language wrappers.

Changes:

  • Introduce rsutils::concurrency::create_thread() + thread_category to standardize thread creation, naming, and thread-start callback invocation.
  • Extend public API with rs2_thread_category, rs2_set_thread_start_callback*(), and rs2_thread_category_to_string().
  • Migrate existing thread creation sites and update wrapper enum parity (Python/C#/Java/MATLAB/UE4).

Reviewed changes

Copilot reviewed 53 out of 53 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
wrappers/unrealengine4/Plugins/RealSense/Source/RealSense/Public/RealSenseTypes.h Add UE4-facing thread category enum for wrapper parity
wrappers/python/c_files.cpp Bind rs2_thread_category enum into Python module
wrappers/matlab/thread_category.m Add MATLAB thread_category enumeration mirror
wrappers/csharp/Intel.RealSense/Types/Enums/ThreadCategory.cs Add C# ThreadCategory enum mirror
wrappers/csharp/Intel.RealSense/Types/Enums/CMakeLists.txt Include new C# enum source in build
wrappers/android/librealsense/src/main/java/com/intel/realsense/librealsense/ThreadCategory.java Add Java ThreadCategory enum mirror
unit-tests/rsutils/concurrency/test-dispatcher.cpp Update dispatcher tests for new ctor signature (category + name)
tools/dds/dds-adapter/lrs-device-controller.cpp Categorize/name dispatcher threads in DDS adapter
third-party/rsutils/src/thread-utils.cpp Implement thread naming + global thread-start callback + create_thread()
third-party/rsutils/src/network-adapter-watcher.cpp Migrate watcher thread creation to create_thread()
third-party/rsutils/src/dispatcher.cpp Dispatcher uses create_thread() and stores category/name for diagnostics
third-party/rsutils/include/rsutils/concurrency/thread-utils.h New public rsutils thread utilities API (category, callback, create_thread)
third-party/rsutils/include/rsutils/concurrency/delayed.h Use create_thread() for delayed worker thread
third-party/rsutils/include/rsutils/concurrency/concurrency.h Extend dispatcher/active_object/watchdog APIs to require category + name
third-party/realdds/src/dds-topic-reader-thread.cpp Migrate DDS reader thread to create_thread() (network category)
third-party/realdds/src/dds-notification-server.cpp Provide category/name to underlying active object thread
third-party/realdds/src/dds-network-adapter-watcher.cpp Migrate watcher thread to create_thread()
third-party/realdds/src/dds-device-watcher.cpp Migrate detached device add/remove threads to create_thread() with categories
third-party/realdds/src/dds-device-server.cpp Categorize/name control dispatcher thread
third-party/realdds/src/dds-device-broadcaster.cpp Migrate broadcaster and ack threads to create_thread()
src/winusb/messenger-winusb.cpp Categorize/name per-endpoint WinUSB dispatcher threads
src/uvc/uvc-streamer.cpp Categorize/name UVC dispatcher, publishing thread, and watchdog thread
src/uvc/uvc-device.cpp Categorize/name UVC device dispatcher thread
src/uvc-sensor.h Use create_thread() for delayed power-release helper thread
src/usbhost/device-usbhost.cpp Categorize/name USBHost dispatchers (control + endpoints)
src/to-string.cpp Add rs2_thread_category string conversion + C API export
src/rs.cpp Implement rs2_set_thread_start_callback*() and assert enum parity
src/realsense.def Export new C API symbols on Windows
src/polling-device-watcher.h Categorize/name polling watcher active object thread
src/platform-camera.cpp Use create_thread() for delayed initialization thread
src/pipeline/pipeline.cpp Categorize/name pipeline dispatcher thread
src/mf/mf-backend.cpp Use create_thread() for Windows device-monitoring thread
src/media/record/record_device.cpp Categorize/name record write dispatcher thread
src/media/playback/playback_sensor.cpp Categorize/name playback per-profile dispatchers
src/media/playback/playback_device.cpp Categorize/name playback read dispatcher thread
src/linux/udev-device-watcher.cpp Categorize/name udev watcher active object thread
src/linux/backend-v4l2.cpp Name/categorize V4L2 capture thread
src/linux/backend-hid.cpp Name/categorize HID capture and PM threads; name PM dispatcher
src/libusb/context-libusb.cpp Name/categorize libusb event handler thread
src/hid/hid-device.cpp Name/categorize HID dispatcher and interrupt active object
src/global_timestamp_reader.cpp Name/categorize time sync active object thread
src/error-handling.cpp Name/categorize error polling active object thread
src/ds/ds-thermal-monitor.cpp Name/categorize thermal monitor active object thread
src/ds/d400/d400-mipi-device.cpp Name/categorize detached reconnection notification thread
src/core/options-watcher.cpp Name/categorize options watcher thread
src/core/notification.cpp Name/categorize notifications dispatcher thread
src/core/enum-helpers.h Add enum helper macros for rs2_thread_category
src/android/fw-logger/rs-fw-logger.cpp Name/categorize Android fw logger thread
src/algo.cpp Name/categorize auto-exposure processing thread
include/librealsense2/rs.hpp Add C++ convenience wrapper rs2::set_thread_start_callback()
include/librealsense2/rs.h Declare new C APIs for thread-start callback registration
include/librealsense2/hpp/rs_types.hpp Define C++ callback interface type rs2_thread_start_callback
include/librealsense2/h/rs_types.h Add rs2_thread_category enum + callback typedefs + to_string declaration
Comments suppressed due to low confidence (3)

third-party/rsutils/include/rsutils/concurrency/thread-utils.h:47

  • The comment on set_current_thread_name() says the name is prefixed with "rs:" automatically, but the implementation uses the provided string verbatim. Either update the comment to reflect that callers must pass the final name, or change set_current_thread_name() to apply the prefix itself (and ensure create_thread() doesn’t double-prefix).
    src/rs.cpp:1954
  • The C/C++ thread-start callback APIs enforce VALIDATE_NOT_NULL( callback ), which prevents callers from unregistering/clearing the callback once set. This also makes it hard for the C++ wrapper to safely treat an empty std::function as “clear”. Consider allowing nullptr to clear the registration (and documenting it), or add a dedicated rs2_clear_thread_start_callback* API.
void rs2_set_thread_start_callback( rs2_thread_start_callback_ptr callback, void * arg, rs2_error ** error ) BEGIN_API_CALL
{
    VALIDATE_NOT_NULL( callback );
    // Wrap the C function pointer + user data into a C++ callback object, then delegate to the _cpp version
    rs2_thread_start_callback_sptr cb_ptr{ new on_thread_start_callback( callback, arg ) };
    rsutils::concurrency::set_thread_start_callback(

third-party/rsutils/src/thread-utils.cpp:87

  • New behavior in create_thread() (name prefixing + callback invocation) isn’t covered by unit tests. Since rsutils concurrency already has tests (e.g., unit-tests/rsutils/concurrency/test-dispatcher.cpp), please add a focused test that asserts the callback is invoked on thread start and receives the expected prefixed name/category.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


void on_thread_start( rs2_thread_category category, const char * name ) noexcept override
{
_on_thread_start( category, name );
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thread_start_callback::_on_thread_start is invoked unconditionally inside a noexcept override. If a user passes an empty std::function (e.g., attempting to clear the callback), this will throw std::bad_function_call and terminate the process. Add an emptiness check (no-op if empty) and/or provide an explicit way to clear/unregister the callback that doesn’t require constructing a callback object with an empty function.

Suggested change
_on_thread_start( category, name );
if ( _on_thread_start )
_on_thread_start( category, name );

Copilot uses AI. Check for mistakes.
@Nir-Az
Copy link
Collaborator

Nir-Az commented Mar 5, 2026

Hey @surban thanks for the PR,
Can you explain the motivation and added value of it?
Why do the user need a callback for every thread we open?

@surban
Copy link
Contributor Author

surban commented Mar 5, 2026

Two reasons:

  • since all threads now get named (with an rs: prefix) so you can actually tell them apart in tools like htop or Visual Studio's thread debugger, important to debug performance issues

  • the optional callback lets users set thread priorities or CPU affinity for each thread, which is important on embedded systems where you might want USB threads at higher priority to avoid frame drops

@Nir-Az Nir-Az requested a review from OhadMeir March 5, 2026 15:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants