Best way to flush event queue in SDL2?

I would like to ease the load of the program when I know that I don’t want any old events in the queue, but I have some concerns.

  1. I am unsure if it would be faster to run SDL_FlushEvents(), or just (like the 2003/2004 thread solutions) make an infinite Poll/Pump event loop

  2. There is a concerning fixme! in SDL_FlushEvents(), and frankly I am unsure if this is actually fixed or still a problem.

So can you tell me what would be the optimal way to get rid of all events from a queue if I don’t want to keep processing and wasting computer resources on stuff I know I don’t need?

Thank you!

Are you sure you want to ignore all events, even SDL_QUIT?

As for the FIXME comment I don’t think this was ever a problem for SDL_TEXTINPUT events in SDL2 because there doesn’t seem to be anything to clean up. The text field in SDL_TextInputEvent is just a fixed-size array. This changed in SDL3 but I don’t think it should be a problem after this commit. The drop events might be a problem in SDL2 but I think you would have the same problem with SDL_PollEvent if you don’t manually call SDL_Free on the “file” field of each drop event.

Just for 1 frame, if I change state and want fresh inputs, and no residual ones

My guess is that SDL_FlushEvents might be a little faster but if you want to know you should measure.

To avoid memory leaks in SDL2 you might want to call SDL_PollEvent so that you can clean up after the drop events (you probably want to do the same in your normal event handling loop too).

SDL_Event event;
while (SDL_PollEvent(&event))
{
	if (event.type == SDL_DROPFILE || 
	    event.type == SDL_DROPTEXT)
	{
		SDL_free(event.drop.file);
	}
}

Or if you don’t use the drop events you might want to simply disable them instead. Then it would probably be fine to call SDL_FlushEvents (unless there are some other events that needs cleaning up that I don’t know about).

SDL_EventState(SDL_DROPFILE, SDL_DISABLE);
SDL_EventState(SDL_DROPTEXT, SDL_DISABLE);

For SDL3 my understanding is that all events will be cleaned up automatically (maybe not right away) so you probably don’t need to do anything special.

In either case, you might want to call SDL_PumpEvents first to make sure all events are discarded.

1 Like

Imagine that you want to store data about the joystick axis. During fast move of the gamepad stick, there can be dozens of SDL_JOYAXISMOTION events in the queue. If you process only the first event of this type and flush the rest, you will have data inconsistent with the actual axis position.

What you have described here and in previous posts is not the recommended way of working with events. The traditional event loop is not usually the biggest CPU draw for a game, so optimizing it usually provides limited benefits for most developers. (On a 1GHz computer you have over 16 million cycles available in 1/60th of a second. Processing even a thousand events in the queue is still just a drop in the bucket.)

However, I think it is an interesting exercise/experiment. Do you have code that you are willing to share, or some minimal working example of what you have in mind?

SDL_FlushEvents(min, max) is generally used in order to remove a certain type-range of events from the queue. The event type values are somewhat loosely arranged by a category hierarchy. (See SDL/include/SDL_events.h). For instance mouse based events are 0x400 through 0x403. You could remove all mouse related events in the current queue by calling SDL_FlushEvents(SDL_MOUSEMOTION, SDL_MOUSEWHEEL);

SDL_FlushEvent(SDL_MOUSEMOTION) will actually call SDL_FlushEvents(SDL_MOUSEMOTION, SDL_MOUSEMOTION), so while the wiki suggests using SDL_FlushEvent() for single event types, it is one less function call to use SDL_FlushEvents() by default.

It would indeed save a couple dozen CPU cycles per event by removing the ignored events from the queue instead of calling SDL_PollEvent(&event) just to ignore said event. On the other hand, if your program doesn’t use the mouse much, then you are adding a function call to each frame which may increase the CPU load on an otherwise idle program.

It would be easier to help further if we can see your code to work on.

Edit: Here’s how I imagine it might look.

#include <SDL2/SDL.h>

int main()
{
	SDL_Init(SDL_INIT_EVERYTHING);
	SDL_Window * win = SDL_CreateWindow("title", 10, 10, 1000, 800, SDL_WINDOW_SHOWN);
	SDL_Renderer * screen = SDL_CreateRenderer(win, -1, 0);

	SDL_Rect box = {0,0,32, 32};
	bool run = true;
	while(run)
	{
		while(SDL_WaitEvent(NULL) < 0)
		{
			// There are some cases where the Kernel can timeout SDL_WaitEvent, 
			// but those will cause it to return as a negative number, 
			// so we just tell the program to return to a waiting state.
		}
		SDL_FlushEvents(SDL_MOUSEMOTION, SDL_MOUSEMOTION);
		SDL_Event ev;
		while(SDL_PollEvent(&ev))
		{
			switch(ev.type)
			{
				case SDL_MOUSEBUTTONDOWN:
					box.x = ev.button.x;
					box.y = ev.button.y;
					break;
				case SDL_QUIT:
					run = false;
					break;
			}
		}

		SDL_SetRenderDrawColor(screen, 50, 10, 10, 255);
		SDL_RenderClear(screen);

		SDL_SetRenderDrawColor(screen, 10, 200, 10, 255);
		SDL_RenderFillRect(screen, &box);
		SDL_RenderPresent(screen);
	}
	SDL_Quit();
}

There are some events that the source code describes as “spammy” see this exerpt from the SDL_LogEvent function:

    /* sensor/mouse/finger motion are spammy, ignore these if they aren't demanded. */
    if ( (SDL_EventLoggingVerbosity < 2) &&
            ( (event->type == SDL_MOUSEMOTION) ||
              (event->type == SDL_FINGERMOTION) ||
              (event->type == SDL_CONTROLLERTOUCHPADMOTION) ||
              (event->type == SDL_CONTROLLERSENSORUPDATE) ||
              (event->type == SDL_SENSORUPDATE) ) ) {
        return;
    }

Note to SDL3 Devs: It would be nice if SDL_FlushEvents() returned either a confirmation bool that an event was removed or a count of the number of events removed. Maybe something that SDL3 could implement?

You could also disable the spammy events before the game loop using the function that Peter87 used to disable dropfile events.

Edit:
I can confirm that disabling the unused spammy event would save more cycles than using SDL_Flush would.

I’m still in the process of weighing my options, but I stole your code to show what I had in mind:

#include <SDL2/SDL.h>

int main()
{
	SDL_Init(SDL_INIT_EVERYTHING);
	SDL_Window * win = SDL_CreateWindow("title", 10, 10, 1000, 800, SDL_WINDOW_SHOWN);
	SDL_Renderer * screen = SDL_CreateRenderer(win, -1, 0);

	SDL_Rect box = {0,0,32, 32};
	bool run = true;
	while(run)
	{
		while(SDL_WaitEvent(NULL) < 0)
		{
			// There are some cases where the Kernel can timeout SDL_WaitEvent, 
			// but those will cause it to return as a negative number, 
			// so we just tell the program to return to a waiting state.
		}
		SDL_Event ev;
		while(SDL_PollEvent(&ev))
		{
	        if (current_state == 0) {
			    switch(ev.type)
			    {
				    case SDL_MOUSEBUTTONDOWN:
					    current_state = 1;
					    SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT);
					    break;
				    case SDL_QUIT:
					    run = false;
					    break;
			    }
	        }
	        else if (current_state == 1) {
			    switch(ev.type)
			    {
				    case SDL_MOUSEBUTTONDOWN:
					    current_state = 0;
					    SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT);
					    break;
				    case SDL_QUIT:
					    run = false;
					    break;
			    }
	        }
		}

		SDL_SetRenderDrawColor(screen, 50, 10, 10, 255);
		SDL_RenderClear(screen);

		SDL_SetRenderDrawColor(screen, 10, 200, 10, 255);
		SDL_RenderFillRect(screen, &box);
		SDL_RenderPresent(screen);
	}
	SDL_Quit();
}

The point is basically that after I get the input to change state, I don’t really care anymore what the mouse position is or if the mouse button is currently down or up. Frankly, I want a fresh clean slate where I know that the mouse button is up, so I don’t get any unexpected inputs from the last frame.

Mainly, though, I want to make my program as efficient as possible, and processing unneeded events (even worse when you told me that a mouse can make 1000 events) seemed like the obvious quick fix.

My program will be mouse-centric, so I can’t just disable the spammy events. Or can I? Can I just manually get the mouse state each frame? Would that be better or worse for performance? I think the mouse will move 50% of the time. So it’s either the cost of the OS call, or the cost of spammy events. Wish I could just get the state of events once per frame instead of the history of every cursor position over the previous 16 microseconds

PS: can you send some more info on the Kernel Wait event problem?

You can disable all events that you don’t need. Just use the SDL_EventState function.

Yes, use the SDL_GetMouseState function. To do the same for keyboard, use the SDL_GetKeyboardState function and for the joystick, use the SDL_JoystickGetButton and similar. Next time just check the documentation first.

The difference will not be measurable, so it does not matter. Processing events doesn’t take much time, even if there are hundreds of them in the queue. Use whatever method works for you rather than worrying about saving a few CPU cycles per second.

If by “change state” you mean something like going between the main menu and the actual game then it might possibly make sense but there are usually many events that are more or less independent of the state of the game. E.g. SDL_QUIT and all the different SDL_WINDOWEVENT. If you handle these events then you probably want to handle them regardless of the state of the program and I don’t think you would want to ignore them just because they happen to come after other events in the even queue.

If you instead mean little things like updating the position or velocity of the player when an arrow key is pressed then I don’t think you would want to throw away a lot of events just because of that. In a game where you can walk, jump and throw bananas you should normally be able to do all three things at the same time. If you press the jump key and the throw key at the exact same time then you should do both, not just one of them.

To me this sounds like premature optimization. If you don’t have a performance problem then there isn’t really anything to fix. If you get 1000 events per second and your game runs at 60 fps that’s only about 16-17 events per frame on average. If you do nothing or just set some flag for most of these events then it’s unlikely to be a problem.

Yes, you can. If you disable SDL_MOUSEMOTION you can still get the position of the mouse each frame by using SDL_GetMouseState.

You can do that for some things, e.g. SDL_GetKeyboardState will give you an array where you can check the state of each key.

I think this is suitable for actions that you want to perform a little at a time for as long as the key is held down, like when holding down an arrow key to move the player.

But if you actually want to do something for each event and don’t risk missing anything then I still think events are better. For example, if you press ESC to abort some action or you press space to fire a bullet then you always want to do that. You don’t want the event to get ignored just because you hit the key very quickly so that it got pressed and released within the same frame.

What type of a program are you thinking of?
Is it a turn-based game, a drawing program,a scientific calculator?

It’s a problem that is pretty well solved by the wait loop, and what little research I did was several years ago now.

I know I said “Kernel” in the comment, but that was more for brevity. If I remember correctly; on Linux I actually blame “watchdog”, a background program that kind of pings all running programs to check if the program is frozen or not, and in order to not have an error thrown, SDL is forced to break out of the wait function. It does seem like some versions of Linux are less likely to break the wait loop, and sometimes it’s not a problem at all. I don’t know if it is a likely problem on other operating systems. I think it’s only a problem on the main thread.
Here’s a quote I found online about watchdog:

During the regular operation of a Linux system, the watchdog periodically expects a response, like a heartbeat, from the system software. If the system is functioning correctly, it sends back the heartbeat within the scheduled time frame.

If you run your system monitor and check out the above program’s CPU usage it should show near 0% CPU usage or possibly even a sleeping state if the mouse isn’t being wiggled.
It should be noted that the screen is only redrawn when an event is in the queue, so the wait loop is a best fit for event-driven and turn-based programs rather than real-time games. I haven’t tested it with emscripten.

You could set up a timer that pushes a User Event every x seconds if you need to have some kind of time-triggered turn system.

Ok, sounds like it would be good to disable all events I don’t intend on using.

I’m confused by this because if you disable MOUSEMOTION, the only other event that gives you the xy coordinates is a MOUSEBUTTON(UP/DOWN) event, so I’m not sure what updates the “internal input device state” for the mouse.

I have followed SDL_GetMouseState() to SDL_GetMouse(), which just does return &SDL_mouse;, which is a mouse struct. But how and where it is updated, I am unsure.

I have followed SDL_PumpEvents() to SDL_PumpEventsInternal(), which un-presses all buttons, and then seems to ignore events that are SDL_DISABLEd.

So it seems like it shouldn’t work because you would only get a mouse event on click, and SDL_GetMouseState() x and y would update only then. So I’m confused by why this would work.

As others have recommended, it’s very useful when you’re thinking of something experimental to create a minimal system to test it on. That way you can work out the kinks in the experiment before applying it to the larger system.

The SDL_mouse object seems to get updated in SDL_PrivateSendMouseMotion regardless of whether SDL_MOUSEMOTION is enabled or not.

AFAIK, all that disabling certain events does is keep the application from seeing them. SDL still gets them from the OS and still needs to handle them.

Last time I looked at the code, all that SDL_GetMouseState() and SDL_GetKeyboardState() do is run through the available events to figure out what the current mouse/keyboard state is. So they aren’t saving you any processing time.

The thing you don’t seem to be understanding is that you’re supposed to process all events every frame. This means there won’t be any “unexpected” inputs from the last frame.

Typically, your program should just be setting flags etc in the while(SDL_PollEvents()) loop for most things. Then the actual work happens afterward.

Like someone else said, this is premature optimization. Running through the event queue, even with lots of mouse events, will be far less than a millisecond most of the time.

Sometimes the things that are important to us just don’t make sense in the real world.

Still having trouble finding out how it works.

SDL_GetMouse() just returns the static structure (which is an interesting way to do it)

SDL_PrivateSendMouseMotion seems to get used in SDL_SendMouseMotion(), which gets used in SDL_EVDEV_Poll(void) on linux, and updateMouse() on bsd. dead end

SDL_GetMouseState() just copy pastes whatever is in the static structure you get the pointer to with SDL_GetMouse(), so it’s not like it activates anything that isn’t already there.

I’m trying to find the part of the code that shows the exact moment when these get filled in (probably somewhere between getting them from the OS, but before pushing the events to the queue and evaluating which ones we want to listen to)

Going from the front, it goes: SDL_PollEvent() SDL_WaitEventTimeout()SDL_PumpEventsInternal() → (which calls the video subsystem-specific → PumpEvents() function) so I’m lost again. Can’t really connect SDL_PollEvent() to SDL_GetMouse() struct being updated.

I’m trying to decide if I want to get mouse events via “State” functions, or via the event queue. Regardless how many times you tell me that the path is important, I really can’t see how it would matter where the mouse was in the time between the current and last frame. I just need 2 sets of coordinates. Any thousands of positional events are really just spam. Even more if I actually react to them and update some bitflag that tells me the event has happened, or even worse, try to update the screen in reaction to the motion.

So on X11 what happens is that:

Imagine you’re creating a graphics editor that lets you draw lines with the mouse. You could just draw a line from the position where the mouse was last frame and where it’s currently at, but by taking the intermediate coordinates into account you would be able to draw something that is more accurate.

motion-events

1 Like

Amazing

I think I have all the info to make an informed decision now. Thank you guys <3