【发布时间】:2014-05-27 07:04:31
【问题描述】:
SDL_AddTimer 的 wiki 文档声称
"请注意,可以通过将要执行的函数的地址和 userevent.data2 的参数提供给 userevent.data1 来避免 SDL 计时器的多线程问题,然后在事件循环。”
如何使用它来避免多线程问题? 有人能解释一下我无法理解的陈述吗?
【问题讨论】:
标签: multithreading sdl sdl-2
SDL_AddTimer 的 wiki 文档声称
"请注意,可以通过将要执行的函数的地址和 userevent.data2 的参数提供给 userevent.data1 来避免 SDL 计时器的多线程问题,然后在事件循环。”
如何使用它来避免多线程问题? 有人能解释一下我无法理解的陈述吗?
【问题讨论】:
标签: multithreading sdl sdl-2
第一个示例假设工作函数,即您要执行的函数 ( my_function() ),驻留在 my_callbackfunc() 函数中。
SDL_AddTimer() 指定:使用此函数设置一个回调函数,以便在指定的毫秒数过去后在单独的线程上运行。
这将引入 my_function() 的并发问题。
解决方案(第二个示例),假设事件轮询线程与添加计时器的线程相同,并调用该线程中的函数。
【讨论】:
我也阅读了该 SDL 文档,它对它的“解决方法”提出了一个非常不好的建议。具体来说,它建议将函数地址转换为 void 指针。这不是便携式的!不要这样做,请阅读
https://isocpp.org/wiki/faq/pointers-to-members#cant-cvt-fnptr-to-voidptr
如果你觉得你必须这样做(或类似的事情),那么我建议将函数指针包装在结构/类中。
struct Wrapper
{
void (*f)(void*);
Wrapper(void (*F)(void*)) { f = F; }
};
要推送自定义事件时创建包装器
SDL_Event event;
event.user.data1 = (void*) new Wrapper(your_function);
event.user.data2 = your_function_arg;
SDL_PushEvent(&user);
然后在你的主循环中,调用,删除包装器
SDL_WaitEvent(&event);
if (event.type == SDL_USEREVENT)
{
Wrapper *p = ((Wrapper*) event.user.data1)
p->f(event.user.data2);
delete p;
}
【讨论】: