On Wed Mar 6 08:50:07 2024 +0000, Yuxuan Shui wrote:
the callbacks aren't guaranteed to run. note that the callbacks decrement the refcount _twice_, once in `queue_release_pending_item`, once directly; whereas `queue_cancel_item` only does it once. so if the callbacks aren't run, the `work_item` is leaked.
The language used here ([CloseThreadpoolWait](https://learn.microsoft.com/en-us/windows/win32/api/threadpoolapiset/nf-thre...)) is a bit ambiguous:
The wait object is freed immediately if there are no outstanding callbacks; otherwise, the timer object is freed asynchronously after the outstanding callbacks complete.
It's unclear what "outstanding" means, so I used this test:
```cpp #include <windows.h> #include <stdio.h> #include <assert.h>
void CALLBACK MyWaitCallback( PTP_CALLBACK_INSTANCE Instance, PVOID Parameter, PTP_WAIT Wait, TP_WAIT_RESULT WaitResult ) { (void)Instance; (void)Parameter; (void)Wait; (void)WaitResult;
fprintf(stderr, "MyWaitCallback: wait is over.\n"); }
int main(void) { PTP_WAIT Wait = NULL; PTP_WAIT_CALLBACK waitcallback = MyWaitCallback; HANDLE hEvent = NULL;
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); assert(hEvent);
Wait = CreateThreadpoolWait(waitcallback, NULL, NULL); assert(Wait);
SetThreadpoolWait(Wait, hEvent, NULL); CloseThreadpoolWait(Wait); Sleep(500);
SetEvent(hEvent); Sleep(5000); return 0; } ```
As you can see, the callback isn't guaranteed to run.