it is OK to let the user actively trigger the callback handling by
calling the sleep-function - most of them are familar with Windows and
therefore know that strange concept of actively managing WinAPI
message queue.
That's the approach I take with winapi - callbacks only happen on the main thread, and the mutex is unlocked whenever the main thread is sleep, either explicitly in winapi.sleep or through other 'blocking' operations. When winapi is used with a GUI application, then I switch to dispatching callbacks on the GUI thread, using the message queue.