# Is SDL Timer Callback Interrupt or MultiThread?

**URL:** <https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847>\
**Category:** SDL Development\
**Created:** [September 4, 2023, 7:01am UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847 "2023-09-04T07:01:42Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![ringo](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/r/779978/32.png) [@ringo](https://discourse.libsdl.org/u/ringo)\
**Post date:** [September 4, 2023, 7:01am UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/1 "2023-09-04T07:01:42Z")

</div>

Hi im new of this forum.  
Currently, Im using SDLTimer for game programming.  
To avoid errors, I found I need to do the Mutual exclusion.  
So I want to know how do I do mutual exclusion for SDLTimer callbacks.  
At first, these callbacks are running on a separate thread,  
Does main thread also work while callbacks are working?

I’m begginer of programming. sry if my explanation is’nt enough.  
I found a similar thread on this forum, but I couldn’t make out it

---

<div class="post-metadata">

**Author:** ![Peter87](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/p/f07891/32.png) [@Peter87](https://discourse.libsdl.org/u/Peter87)\
**Post date:** [September 4, 2023, 8:35am UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/2 "2023-09-04T08:35:51Z")

</div>

> [@ringo](#):
>
> Is SDL Timer Callback Interrupt or MultiThread?

The docs for [SDL\_AddTimer](https://wiki.libsdl.org/SDL2/SDL_AddTimer) says

> The callback is run on a separate thread.

which means it’s “multithreaded”. I.e. the main function and the callback runs on different threads and might execute code at the same time.

> [@ringo](#):
>
> how do I do mutual exclusion for SDLTimer callbacks.

The same way as with all multithreaded code. There are a few different techniques but I belive the most common ones are to use [mutexes](https://wiki.libsdl.org/SDL2/SDL_CreateMutex) (locks) to protect shared data or to use [atomic variables](https://wiki.libsdl.org/SDL2/SDL_atomic_t).

> [@ringo](#):
>
> I’m begginer of programming.

I don’t want to discourage you from learning multithreading, but personally, I don’t consider multithreading to be a beginner topic. It’s one of the most easy things to get wrong and debugging it can be a nightmare. It essentially requires that you know what you’re doing because testing might not always reveal a problem. My advice is to avoid multithreading unless you have a very good reason for using it, and in that case make sure you restrict it to as small part of the code as possible (minimize the amount of shared state and the amount of code that deals with it).

---

<div class="post-metadata">

**Author:** ![ringo](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/r/779978/32.png) [@ringo](https://discourse.libsdl.org/u/ringo)\
**Post date:** [September 5, 2023, 8:23am UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/3 "2023-09-05T08:23:25Z")

</div>

Thank you for your answer.  
Currently, I use 2 callback funcs and a main func.  
one is for game processing, another one is for the rendering. main func for the initializing and SDLevent.  
I want to make game processing and rendering separeted.

yes… I k its gonna be a hard way, but I wanna use multithreading. Of course I won’t use shared data so much as long as I can.

---

<div class="post-metadata">

**Author:** ![Peter87](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/p/f07891/32.png) [@Peter87](https://discourse.libsdl.org/u/Peter87)\
**Post date:** [September 5, 2023, 8:47am UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/4 "2023-09-05T08:47:42Z")

</div>

> [@ringo](#):
>
> one is for game processing, another one is for the rendering. main func for the initializing and SDLevent.

Just a heads up in case you’re not aware…

> **Can I call SDL video functions from multiple threads?**  
> No, most graphics back ends are not thread-safe, so you should only call SDL video functions from the main thread of your application.  
> [SDL2/FAQDevelopment - SDL Wiki](https://wiki.libsdl.org/SDL2/FAQDevelopment#can_i_call_sdl_video_functions_from_multiple_threads)

Not sure if this is going to change in SDL3.

---

<div class="post-metadata">

**Author:** ![ringo](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/r/779978/32.png) [@ringo](https://discourse.libsdl.org/u/ringo)\
**Post date:** [September 6, 2023, 2:10pm UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/6 "2023-09-06T14:10:26Z")

</div>

Excuse me.

> No, most graphics back ends are not thread-safe, so you should only call SDL video functions from the main thread of your application.

Is this a problem even if I use rendering funcs only on the rendering thread but not a main thread??  
I mean I don’t call SDL rendering funcs on the other threads except 1.

Otherwise I will combain it to the main thread immediately.

---

<div class="post-metadata">

**Author:** ![Peter87](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/p/f07891/32.png) [@Peter87](https://discourse.libsdl.org/u/Peter87)\
**Post date:** [September 6, 2023, 3:04pm UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/7 "2023-09-06T15:04:37Z")

</div>

From a [recent discussion](https://github.com/libsdl-org/SDL/issues/7140#issuecomment-1688320887) about adding better thread-safety documentation:

> [@LunarLambda](#):
>
> I’d like clarification on is the meaning of “main thread”  
> is that the thread that called SDL\_Init or the thread that is running main()?

> [@icculus](#):
>
> Almost always it means “the thread that literally runs main()” …the first thread of the program.
> 
> This is a hard requirement in several platforms (Emscripten has a ton of requirements that crucial things happen in only that thread regardless of where SDL\_Init is called, other platforms expect that thread to be where the GUI is initialized, etc)

---

<div class="post-metadata">

**Author:** ![icculus](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/icculus/32/81_2.png) [@icculus](https://discourse.libsdl.org/u/icculus)\
**Post date:** [September 6, 2023, 8:47pm UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/8 "2023-09-06T20:47:54Z")

</div>

Just throwing this idea out there:

If you just generally need some amount of time to go by, and precision isn’t super-important, you can take a basic program that looks like this:

```c
while (program_is_still_running) {
    check_for_new_events();
    do_stuff();
    draw_frame();
}

```

…and make it look like this instead…

```c
 Uint32 next_time_to_do_something = 0;

while (program_is_still_running) {

    // THIS IS THE NEW THING.
    const Uint64 now = SDL_GetTicks64(); // milliseconds program has been running.
    if (now >= next_time_to_do_something) {
        do_something_when_timer_is_up();
        next_time_to_do_something = SDL_GetTicks64() + how_long_to_wait_for_timers;
    }
    // THAT'S THE NEW THING.

    check_for_new_events();
    do_stuff();
    draw_frame();
}

```

Another option is to push a user-defined event onto the event queue from your AddTimer handler, and deal with that event from the main thread with all your other events, but this risks a little bit of lag (but almost always, it’s tolerable, and always, you _should_ write code that can tolerate it).

Rather than pushing an event, I would prefer the approach in the pseudo code above, though.

---

<div class="post-metadata">

**Author:** ![rtrussell](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/rtrussell/32/4768_2.png) [@rtrussell](https://discourse.libsdl.org/u/rtrussell)\
**Post date:** [September 7, 2023, 1:55pm UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/9 "2023-09-07T13:55:20Z")

</div>

> [@ringo](#):
>
> I k its gonna be a hard way, but I wanna use multithreading.

Go for it! My app is multi-threaded and it works fine on all platforms, even Emscripten (although multithreading does limit the browsers that will work, currently iOS browsers don’t support it).

Of course you have to be careful, and you can only make renderer-related calls from one thread, but I didn’t encounter any specific problems. SDL2 contains all the synchronising primitives you are likely to need (semaphores, mutexes etc.).

---

<div class="post-metadata">

**Author:** ![icculus](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/icculus/32/81_2.png) [@icculus](https://discourse.libsdl.org/u/icculus)\
**Post date:** [September 8, 2023, 4:04pm UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/10 "2023-09-08T16:04:03Z")

</div>

> [@rtrussell](#):
>
> currently iOS browsers don’t support it

I don’t know what version of iOS started supporting them, so it might be too new to reasonably count on, but they definitely work on my iPhone running iOS 16.6.

Here’s a thing using Emscripten with pthreads. The rendering happens in the main thread, and a background thread is generating the pixels for the green bar. (This is not a serious app, it was just to see if we could get dlopen and pthreads to work on the web with our game engine).

[https://icculus.org/~icculus/emscripten/cext\_pixel\_array-html5-1.0/](https://icculus.org/~icculus/emscripten/cext_pixel_array-html5-1.0/)

---

<div class="post-metadata">

**Author:** ![rtrussell](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/rtrussell/32/4768_2.png) [@rtrussell](https://discourse.libsdl.org/u/rtrussell)\
**Post date:** [September 8, 2023, 4:56pm UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/11 "2023-09-08T16:56:34Z")

</div>

> [@icculus](#):
>
> I don’t know what version of iOS started supporting them, so it might be too new to reasonably count on, but they definitely work on my iPhone running iOS 16.6.

In that case can you try [this link](https://wasm.bbcbasic.co.uk/bbcsdl.html) on your phone, please. It works in all desktop browsers plus Chrome and Firefox on Android, but I’ve not successfully opened it in any iOS browser (‘Exception thrown, see JavaScript console’).

---

<div class="post-metadata">

**Author:** ![icculus](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/icculus/32/81_2.png) [@icculus](https://discourse.libsdl.org/u/icculus)\
**Post date:** [September 8, 2023, 5:05pm UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/12 "2023-09-08T17:05:01Z")

</div>

> [@rtrussell](#):
>
> but I’ve not successfully opened it in any iOS browser (‘Exception thrown, see JavaScript console’).

Rebuild with `-s MAXIMUM_MEMORY=1gb` when linking and see if it fixes it.

---

<div class="post-metadata">

**Author:** ![rtrussell](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/rtrussell/32/4768_2.png) [@rtrussell](https://discourse.libsdl.org/u/rtrussell)\
**Post date:** [September 8, 2023, 5:30pm UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/13 "2023-09-08T17:30:00Z")

</div>

> [@icculus](#):
>
> Rebuild with `-s MAXIMUM_MEMORY=1gb` when linking

Unbelievable - it works! But why? It’s not necessary on any other platform, including Android. Are there any downsides?

---

<div class="post-metadata">

**Author:** ![icculus](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/icculus/32/81_2.png) [@icculus](https://discourse.libsdl.org/u/icculus)\
**Post date:** [September 8, 2023, 10:56pm UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/14 "2023-09-08T22:56:08Z")

</div>

The only downside is you can’t allocate more than a gigabyte of memory. 🙂

The exception was because it’s trying to allocate the SharedArrayBuffer and Safari/ios refuses to make one with a default maximum of 4 gigabytes (even if you don’t plan to actually allocate anything near that amount).

I ran into this same problem in DragonRuby Game Toolkit, so I knew exactly what to do when I saw it in the debugger for your app.

---

<div class="post-metadata">

**Author:** ![ringo](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/r/779978/32.png) [@ringo](https://discourse.libsdl.org/u/ringo)\
**Post date:** [September 10, 2023, 1:57pm UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/15 "2023-09-10T13:57:32Z")

</div>

> [@rtrussell](#):
>
> only make renderer-related calls from one thread

So I don’t need to use rendering functions on the main thread, right?

Past time, I actually put drawing functions at main thread  
but idk why, compared with callback threads, this method make it a bit lagging.  
I gave objects speed and let them move. but that was not look like smooth.  
this loop will takes 17msec but sometime it takes 30~60msec.  
My code is like this.

```auto
int max_fps=60;
while(event.type!=SDL_QUIT){
	prev_frame_tick=SDL_GetTicks64();
	drawing();

	while(SDL_GetTicks64()-prev_frame_tick<1000/max_fps){
		SDL_WaitEventTimeout(&event,1000/max_fps-(SDL_GetTicks64()-prev_frame_tick));
		if(event.type==SDL_QUIT){
			break;
		}
		KeyEventProcess();
	}			
}

```

And When I drag the window, main thread process stoped.  
These won’t be happened when I use callback.

```auto
Uint32 callback(Uint32 interval,void *pointer){
	drawing();
	return 1000/max_fps;
}

```

(eventfunctions on the main thread)  
These are why I wanna use timer callback for rendering.

---

<div class="post-metadata">

**Author:** ![ringo](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/r/779978/32.png) [@ringo](https://discourse.libsdl.org/u/ringo)\
**Post date:** [September 10, 2023, 2:00pm UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/16 "2023-09-10T14:00:59Z")

</div>

> [@icculus](#):
>
> Just throwing this idea out there:

Oh, I didn’t have any idea to do this method.  
Thank you!  
I will try it if I gave up learning for multi threads.

---

<div class="post-metadata">

**Author:** ![ringo](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/r/779978/32.png) [@ringo](https://discourse.libsdl.org/u/ringo)\
**Post date:** [September 10, 2023, 2:49pm UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/17 "2023-09-10T14:49:46Z")

</div>

> [@ringo](#):
>
> My code is like this.

I edited this code just now  
because I thought I shouldn’t use SDL\_Delay();

---

<div class="post-metadata">

**Author:** ![rtrussell](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/rtrussell/32/4768_2.png) [@rtrussell](https://discourse.libsdl.org/u/rtrussell)\
**Post date:** [September 10, 2023, 3:50pm UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/18 "2023-09-10T15:50:10Z")

</div>

> [@ringo](#):
>
> So I don’t need to use rendering functions on the main thread, right?

I think it’s been said that some platforms require rendering to be done in the ‘main’ thread (Emscripten for example). So whether it’s acceptable to render in a different thread (and only that thread) will depend on what platforms you want to support.

My advice is not to take the risk, and render only in the main thread. I do that in my app, and there’s no lag (but it is true that rendering stops when dragging the window).

---

<div class="post-metadata">

**Author:** ![ringo](https://discourse.libsdl.org/letter_avatar_proxy/v4/letter/r/779978/32.png) [@ringo](https://discourse.libsdl.org/u/ringo)\
**Post date:** [September 11, 2023, 5:54am UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/19 "2023-09-11T05:54:51Z")

</div>

Alright, I need to make out why my program is lagging.  
Thank you for your answer everyone.

---

<div class="post-metadata">

**Author:** ![rtrussell](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/rtrussell/32/4768_2.png) [@rtrussell](https://discourse.libsdl.org/u/rtrussell)\
**Post date:** [September 11, 2023, 10:38am UTC](https://discourse.libsdl.org/t/is-sdl-timer-callback-interrupt-or-multithread/45847/20 "2023-09-11T10:38:47Z")

</div>

> [@ringo](#):
>
> I need to make out why my program is lagging.

Things to check:

- Ensure you have specified SDL\_RENDERER\_PRESENTVSYNC in your `SDL_CreateRenderer()` call.
- Use `while (SDL_PollEvent(...))` rather than `if (SDL_PollEvent(...))` to ensure you drain all pending events every frame.

Ideally the only ‘waiting’ should be in `SDL_RenderPresent()`, **not** `SDL_Delay()` or `SDL_WaitEventTimeout()` etc.
