Comments in my other thread (idle not at 0% - #7 by Levo) is having me think it’d be a good idea to use main instead of callbacks. Here’s my main problem
I would like to WaitEvent and never draw unless I need to. I’d want WaitEvent to return if my background thread sends data (I push a user event for this.) However with callbacks it seems like user events can execute outside of the main thread and concurrently with AppIterate and AppEvent which I never want to happen. I only support desktop OSes (mac, linux and likely windows) so I don’t think I need callbacks?
What’s my best option? It seems that if I should use a main function? Events and iterate will always happen on the main thread/loop and never concurrently? And if the background thread sends a message to the main thread (so it could update UI) using a user event is the best idea if I want to block with WaitEvent? I’m assuming using main and having a loop won’t be deprecated? That’s only for wasm and mobile OSes?
AFAIK these callbacks are designed specifically for mobile devices, so if you have plans to support only desktop platforms, you can implement the main game loop however you like.
Typically, the main game loop is implemented in the main game thread, without the use of any other threads, both for updating the logic and (especially) rendering the game frames. If you want to maintain a certain framerate, simply implement a main game loop based on the SDL_PollEvent and use SDL_Delay or SDL_DelayPrecise to wait for the next frame, if there is a spare time between frames (to keep low CPU time usage). If you want to update the game state only when something happened (e.g. an event is queued), implement the loop based on the SDL_WaitEvent function, without delays between frames.
For the game to work, it must have a main loop implemented. If you don’t want to use SDL callbacks, you’ll have to implement one yourself. No need to feel weird about it, it’s a normal think to do.
FYI it’s not a game. I’m writing https://bold-edit.com/ the background thread is to deal with LSPs since they take forever to do things. There’s no telling when an LSP event will take 1ms or 15 seconds and what order events will happen.
I redraw because it’ll send me autocomplete information or which lines have syntax errors and other things I need to display to the user. Otherwise I’d only need to draw on keypress, mouse movement (for gui) and sometimes on a timeout (mouse moved off a menu long enough for it to be hidden)
Please next time specify exactly what you are developing, to avoid guessing.
I stand by what I wrote earlier. Create a main loop, wait for events using SDL_WaitEvent function and repaint the window only when necessary. You can safely add your events to the queue using SDL_PushEvent if a side thread needs to communicate something to the main thread (and force a window to repaint, for example).
I would like to WaitEvent and never draw unless I need to
I thought the start of the paragraph would make it obvious enough that it isn’t a game
I stand by what I wrote earlier
Yeah I like it.
I started a stopwatch, it took 10mins to write this. It seems correct and I have 0% cpu usage on idle. Whomever stumbled into this thread feel free to take this
int main(int argc, char*argv[])
{
void*appState=0;
SDL_AppResult res = SDL_AppInit(&appState, argc, argv);
SDL_Event e;
while (res == SDL_APP_CONTINUE) {
if (SDL_WaitEvent(&e)) {
res = SDL_AppEvent(appState, &e);
while (res == SDL_APP_CONTINUE && SDL_PollEvent(&e)) {
res = SDL_AppEvent(appState, &e);
}
}
if (res == SDL_APP_CONTINUE) {
res = SDL_AppIterate(appState);
}
}
SDL_AppQuit(appState, res);
return res == SDL_APP_SUCCESS ? 0 : 1;
}
I’ll need to set the res var regardless for main’s exit code. You’re right about the SDL_AppEvent, an optimize build still has two separate calls. However, I dislike do-while so much that I banned it from my codebase. It never made sense the while couldn’t see into the do’s body. I rather have the below instead
if (SDL_WaitEvent(&e)) {
while ((res = SDL_AppEvent(appState, &e)) == SDL_APP_CONTINUE && SDL_PollEvent(&e)) { }
}