ver*_*sap 6 c++ multithreading boost signals clutter
我正在努力从一个额外的线程调用一个杂乱的函数.我使用boost :: thread进行线程化和clutter库1.0.
具体来说,该线程包含一个循环函数,该函数每隔一段时间发出一个带有x和y坐标参数的boost :: signals2 :: signal.该信号连接到一个函数,该函数将这些变量置于混乱状态,即x,y in
clutter_stage_get_actor_at_pos(CLUTTER_STAGE(演员),CLUTTER_PICK_ALL,x,y);
这就是我遇到段错误的地方.
显然杂乱有一些线程处理程序.我试着打电话
g_thread_init(NULL);
clutter_threads_init();
在启动clutter_main()之前.我也尝试将杂乱函数包含在内
clutter_threads_enter();
clutter_stage_get_actor_at_pos(CLUTTER_STAGE(演员),CLUTTER_PICK_ALL,x,y);
clutter_threads_leave();
但这也不行.
每个提示都表示赞赏,谢谢你提前!
附录
我只是伪造了我想要做的最小样本.我按照建议"保护"了clutter_main()例程.杂乱的一些功能似乎从单独的线程起作用(例如,设置舞台颜色或设置演员位置).我的代码还有问题吗?
#include <clutter/clutter.h>
#include <boost/thread.hpp>
ClutterActor *stage;
ClutterActor* rect = NULL;
void receive_loop()
{
while(1)
{
sleep(1);
clutter_threads_enter();
ClutterActor* clicked = clutter_stage_get_actor_at_pos(CLUTTER_STAGE(stage), CLUTTER_PICK_ALL,300, 500);
clutter_threads_leave();
}
}
int main(int argc, char *argv[])
{
clutter_init(&argc, &argv);
g_thread_init(NULL);
clutter_threads_init();
stage = clutter_stage_get_default();
clutter_actor_set_size(stage, 800, 600);
rect = clutter_rectangle_new();
clutter_actor_set_size(rect, 256, 128);
clutter_actor_set_position(rect, 300, 500);
clutter_group_add (CLUTTER_GROUP (stage), rect);
clutter_actor_show(stage);
boost::thread thread = boost::thread(&receive_loop);
clutter_threads_enter();
clutter_main();
clutter_threads_leave();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
好吧,我想我找到了答案..
它在"线程模型"部分中说:
在多线程环境中使用Clutter API的唯一安全且可移植的方法是永远不会从未调用clutter_init()和clutter_main()的线程访问API.
将线程与Clutter一起使用的常见模式是使用工作线程执行阻塞操作,然后在线程结束时安装空闲或时间源以及结果.
Clutter提供了g_idle_add()和g_timeout_add()的线程感知变体,它们在调用提供的回调之前获取Clutter锁:clutter_threads_add_idle()和clutter_threads_add_timeout().
所以我对最小样本代码的修正是将receive_loop()改为
void receive_loop()
{
while(1)
{
sleep(1);
int pos[2];
pos[0] = 400;
pos[1] = 200;
clutter_threads_add_idle_full (G_PRIORITY_HIGH_IDLE,
get_actor,
&pos,
NULL);
}
}
Run Code Online (Sandbox Code Playgroud)
并添加get_actor函数(如在menitioned doc页面上的示例代码中)
static gboolean
get_actor (gpointer data)
{
int* pos = (int*) data;
ClutterActor* clicked = clutter_stage_get_actor_at_pos(CLUTTER_STAGE(stage), CLUTTER_PICK_ALL, pos[0], pos[1]);
return FALSE;
}
Run Code Online (Sandbox Code Playgroud)
clutter_threads_add_idle_full负责线程锁等.
我玩了你的代码,看起来你做的一切都很好,尽管我不是混乱方面的专家。我还在 gdb 下运行了你的程序,出现了一些有趣的事情:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb799db70 (LWP 3023)]
0x002d97c6 in glDisable () from /usr/lib/nvidia-current/libGL.so.1
(gdb) thread apply all bt
Thread 2 (Thread 0xb799db70 (LWP 3023)):
#0 0x002d97c6 in glDisable () from /usr/lib/nvidia-current/libGL.so.1
#1 0x001b3ec3 in cogl_disable_fog () from /usr/lib/libclutter-glx-1.0.so.0
#2 0x0018b00a in ?? () from /usr/lib/libclutter-glx-1.0.so.0
#3 0x0019dc82 in clutter_stage_get_actor_at_pos () from /usr/lib/libclutter-glx-1.0.so.0
#4 0x080498de in receive_loop () at seg.cpp:19
Run Code Online (Sandbox Code Playgroud)
显然,事故发生在glDisable () from /usr/lib/nvidia-current/libGL.so.1。请注意,我在 GeForce 8600 GT 上使用 NVIDIA 的 OpenGL 驱动程序。
您能否确认您的应用程序在使用其他显卡(非 NVIDIA)的计算机上也会崩溃?我怀疑崩溃是由于 NVIDIA OpenGL 实现上的错误造成的。
对我来说,似乎 *clutter_threads_enter/leave()* 并没有保护 *clutter_stage_get_actor_at_pos()* ,因为我测试了 *receive_loop()* 被称为回调:
g_signal_connect(stage, "button-press-event", G_CALLBACK(receive_loop), NULL);
Run Code Online (Sandbox Code Playgroud)
所以我们知道您的代码似乎没问题。
我鼓励您将问题发送到Clutter 讨论和帮助邮件列表:clutter-app-devel-list
使用 Clutter、其集成库或基于 Clutter 的工具包的应用程序开发人员的邮件列表。