Reputation: 14418
The wiki document for SDL_AddTimer claims that
"Note that it is possible to avoid the multithreading problems with SDL timers by giving to userevent.data1 the address of a function you want to be executed and to userevent.data2 its params, and then deal with it in the event loop."
How it is used to avoid multithreading problem?. Can someone explain what is it i am unable to understand the statement ?
Upvotes: 1
Views: 1029
Reputation: 5290
The first example assumes the working function, i.e. the function you want to execute ( my_function() ), resides in the my_callbackfunc() function.
SDL_AddTimer() specifies: Use this function to set up a callback function to be run on a separate thread after the specified number of milliseconds has elapsed.
This will introduce concurrency problems with my_function().
The solution (second example), assumes the event polling thread is the same thread that added the timer, and calls the function in that thread.
Upvotes: 1
Reputation: 153
I've read that SDL documentation as well, and it makes a really bad suggestion for its "workaround". Specifically, it recommends casting a function address to a void pointer. This is not portable! Do not do it and please read
https://isocpp.org/wiki/faq/pointers-to-members#cant-cvt-fnptr-to-voidptr
If you feel that you must do this (or something like it) then I'd suggest wrapping the function pointer inside a struct/class.
struct Wrapper
{
void (*f)(void*);
Wrapper(void (*F)(void*)) { f = F; }
};
Create the wrapper when you want to push the custom event
SDL_Event event;
event.user.data1 = (void*) new Wrapper(your_function);
event.user.data2 = your_function_arg;
SDL_PushEvent(&user);
Then in your main loop, do the call, delete the wrapper
SDL_WaitEvent(&event);
if (event.type == SDL_USEREVENT)
{
Wrapper *p = ((Wrapper*) event.user.data1)
p->f(event.user.data2);
delete p;
}
Upvotes: 1