Skip to content

Wake up a sleeping ipc::Thread on cancel() - #3

Merged
sadko4u merged 1 commit into
lsp-plugins:develfrom
CmdrShepardsPie:thread-cancel-wakeup
Oct 16, 2026
Merged

sadko4u merged 1 commit into
lsp-plugins:develfrom
CmdrShepardsPie:thread-cancel-wakeup

Conversation

@CmdrShepardsPie

@CmdrShepardsPie CmdrShepardsPie commented Oct 16, 2026 •

Copy link
Copy Markdown

Follow-up to lsp-plugins/lsp-plugins#670.

ipc::Thread::sleep() sleeps in slices of at most 100 ms to check bCancelled, so a 320 ms sleep of the catalog thread costs four wakeups. With this change, sleep() waits on a condition variable until its deadline and cancel() signals it, so each sleep costs one wakeup and cancel() takes effect at once. Measured with a thread that sleeps 320 ms in a loop like the catalog thread (Linux, 3 runs of 10 s each): 12.4 wakeups/s before, 3.2 after.

As you asked, Thread.h no longer includes Windows headers. The thread handle, the mutex and the condition variable are in a private detail::thread_impl_t, defined in Thread.cpp and allocated by the constructor, as ipc::Condition does on Windows. Thread.h no longer includes pthread.h either. Nothing in lsp-runtime-lib, lsp-plugin-fw, lsp-ws-lib, lsp-tk-lib, lsp-dsp-units, lsp-plugins-shared or the JACK and PipeWire libraries relied on it, but I can put it back if you prefer.

Testing:

  • Linux (g++ 13 and g++ 15): the full utest suite passes (68/68), and the new runtime.ipc.thread_sleep test passes, also under valgrind (0 errors). In normal runs the thread typically wakes up 0.05–0.2 ms after cancel(), and a 320 ms sleep takes one context switch.
  • Windows: every source file compiles with MinGW-w64 (g++ 13) without warnings; not run.
  • macOS: not built or run.

Happy to rework it however you prefer.

Made with AI assistance. Written by Claude Opus 5.5 under the direction of Chris Simpson (GitHub @CmdrShepardsPie), who reviewed and approved it.

ipc::Thread::sleep() split the sleep of an ipc::Thread into intervals of
at most 100 ms to poll the cancellation flag, so a thread that sleeps for
a long time woke up at least 10 times per second, and cancel() took effect
only at the end of the current interval.

Added a mutex and a condition variable to ipc::Thread. cancel() now sets
the cancellation flag and signals the condition variable under the lock,
and sleep() waits on the condition variable for the whole interval:
* POSIX: until a CLOCK_MONOTONIC deadline, or a CLOCK_REALTIME one if
  pthread_condattr_setclock() fails; the deadline is limited to the
  maximum value of time_t, so a very long sleep() lasts until cancel().
* MacOS: pthread_condattr_setclock() is not available, so sleep() waits
  with pthread_cond_timedwait_relative_np() for the time left until a
  CLOCK_MONOTONIC deadline, recomputed after each wake-up.
* Windows: the time left is computed with QueryPerformanceCounter() after
  each return of SleepConditionVariableCS(), so neither an early timeout
  nor a spurious wake-up ends sleep() early.
sleep() returns STATUS_CANCELLED as soon as the thread is cancelled.
sleep() of a thread that is not an ipc::Thread is unchanged.

The thread handle, the mutex and the condition variable are kept in the
private structure detail::thread_impl_t, defined in Thread.cpp and
allocated by the constructor, so ipc/Thread.h no longer includes Windows
or pthread headers. The thread launchers became static members of that
structure. start() returns STATUS_NO_MEM if the allocation failed.

Declared a private copy constructor of ipc::Thread, as the thread now
owns the platform-specific state.

Added the runtime.ipc.thread_sleep unit test.

Co-Authored-By: Claude <noreply@anthropic.com>
@sadko4u
sadko4u merged commit 9faa2e1 into lsp-plugins:devel Oct 16, 2026
@sadko4u

sadko4u commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

Hello! I've just merged the changes with some additions. You may test sleeps now.

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.

2 participants