optional event-driven callback-main
SDL really offer quite a complete package for general app development, however one dealbreaker is the busy-wait polling of SDL_WaitEvents() making it unsuited for background apps.
With the addition of callback-based main, I think there is an opportunity here to add the ability for making truly event-driven blocking main loops.
Some ideas for how to expose this functionality as an interface:
-
Idea 1: add a new
SDL_APP_WAITEVENTentry to the SDL_AppResult enum that directs control flow to a blocking event wait.- the developer can return this from SDL_AppEvent() to skip calling SDL_AppIterate() for that iteration.
- the developer can return this from SDL_AppIterate() to choose to block until next event instead of going straight to event pumping
-
Idea 2: add a hint or function call that globally switches between poll-based and wait-based event loop, then SDL_AppIterate() is called only on a timer message.
-
Idea 3: dynamically detect whether or not SDL_AppIterate() is defined, use wait-based event loop when absent and poll-based event loop when present.
If this is added and idea 1 (new return value) is used, then another addition can be SDL_APP_SKIPEVENTS that can be used to force a call to SDL_AppIterate even if the event queue is not emptied. The events left in the queue can be emptied after SDL_AppIterate returns, unless the user returns SDL_APP_SKIPEVENTS again.
Just hit a need for this in porting Silk.NET to use SDL3 and SDL_EnterAppMainCallbacks. We introduced our event-driven feature upon request from users developing graphical applications as opposed to games, where you don't necessarily need to be rendering every frame and instead only render in response to changes or as requested by the user (for our SDL backend we just pushed a throwaway event onto the queue to deal with this scenario). I intended to use this same implementation, until I realised that there's no way to halt SDL_AppIterate and even if there was, my solution would just result in a SDL_AppEvent and not necessarily a SDL_AppIterate given that these two callbacks are not necessarily intrinsically tied.
To review the available options (based on my understanding of SDL from its documentation, I don't know how it's actually implemented and only know the assumptions the documentation tells me to make):
Because SDL_AppEvent and SDL_AppIterate are not necessarily intrinsically tied (this is only true in the typical use case where SDL_EnterAppMainCallbacks is processing WM events before calling iterate, and won't be the case where the user pushes their own event onto the pump which would be a common need in event-driven scenarios to "wake up" the event thread), idea 1 is likely inappropriate. SDL_AppEvent can technically be concurrent, and in that scenario it is not obvious which result should influence the behaviour of SDL_AppIterate. I think SDL internally stores the result as an atomic integer, but even still this may result in undesired behaviour with this idea. This behaviour is a lot easier to reason for where the only result from the function is "terminate my application" (Success/Failure, in which case it doesn't really matter which thread wins because we only need one to want to quit) or "don't terminate my application" (Continue, business as usual).
Idea 2 is interesting, but is likely a separate conversation as it doesn't really make the application event-driven, rather it just makes SDL_AppIterate more predictable and user-controllable, which will be fine in some use cases but not others. Idea 3 was infeasible as soon as you said the word "dynamically" :P Simple and obvious is the best way.
To be honest, I would just add a hint that halts SDL_AppIterate until any SDL_AppEvent (be that from the user or the window manager) is received. This should be feasible to implement on most platforms, as this is how SDL_WaitEvent works today, but I can't speak for the more exotic platforms. If the user wants a predictable SDL_AppIterate, they can spawn off a timer thread that posts an event to the queue or (less objectionably) a separate feature request issue can be opened to discuss adding those options to make SDL_AppIterate more predictable/customisable.
EDIT: I've just realised my response entirely ignores SDL_WaitEventTimeout. In which case, yes maybe a customisable hint for that should be added as part of this work item.
I'm going to look at this as maybe an extension of the current SDL_HINT_MAIN_CALLBACK_RATE hint and see if we can make something work with that. Stay tuned.
Definitely check out #11770 and see if it solves your problem. Thanks!