Skip to content

Change timers to enable proper rundown#147

Merged
EmJayGee merged 1 commit intomainfrom
micgrier/make_tp_timers_unique_ptrs
Dec 21, 2025
Merged

Change timers to enable proper rundown#147
EmJayGee merged 1 commit intomainfrom
micgrier/make_tp_timers_unique_ptrs

Conversation

@EmJayGee
Copy link
Copy Markdown
Collaborator

This ended up being a moderately significant reconsideration of how timers run down.

The windows thread pool has some fun oddities in how it synchronizes with cancellation / finalization of potentially concurrent dispatch of the events for shutdown. These are understandable but were not really handled in the original design in a way that was usable.

The API is now more straightforward, although the current implementation does encapsulate the Windows oddity that at shutdown of a timer, a wait for the possibly in flight event to complete must happen. That wait has no timeouts and is not interruptible. See CloseThreadPoolTimer in the Microsoft Win32 API documentation for more details.

There is another alternative to this which is to have the timer object be a front for another reference counted object, as Raymond Chen describes in this post. I didn't choose this approach for three reasons:

  1. It seemed to add more complexity where the shutdown behavior could merely be documented and exposed so that the client could mitigate it by themselves moving it to another location if necessary
  2. Turning the already somewhat complex timer object into yet another sub-object that was reference counted seemed again like overkill. How many things do we need to create to manage one thing? (I know, as many as you have to, and no more, but see point Initial commit of changes from the GiM copy of m #1)
  3. The "safety" here is that the reference counted object would be able to stop dispatching callbacks to the owner object when it was destroyed, and itself be destroyed only when the callbacks were completed. But then how is this reference back to the owner object managed? Is it a std::atomic<raw_pointer_to_owner*> that gets set to null on shutdown? There's still a race here when the timer callback is called regarding whether the owner is prepared to deal with a callback!

In the end, it seemed like adding the level of indirection was just putting off the disaster a little bit, and there are still issues about ensuring that the code (as in the DLL in the case of Windows) stays mapped during the possible callback duration.

Thus, I elected to not pursue the more complex solution since it seems to open a cavern of more issues.

@EmJayGee EmJayGee force-pushed the micgrier/make_tp_timers_unique_ptrs branch 5 times, most recently from 58aab2d to 05b7c45 Compare December 21, 2025 04:09
@EmJayGee EmJayGee force-pushed the micgrier/make_tp_timers_unique_ptrs branch from 05b7c45 to 7e9a2cd Compare December 21, 2025 04:25
@EmJayGee EmJayGee merged commit df62ed8 into main Dec 21, 2025
5 checks passed
@EmJayGee EmJayGee deleted the micgrier/make_tp_timers_unique_ptrs branch December 21, 2025 04:40
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.

1 participant