我正在努力从一个额外的线程调用一个杂乱的函数。 我使用boost :: thread进行线程化和clutter库1.0。
具体来说,该线程包含一个循环函数,该函数每隔一段时间发出一个带有x和y坐标参数的boost :: signals2 :: signal。 该信号连接到一个函数,该函数将这些变量置于混乱状态,即
中的x,yclutter_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;
}
答案 0 :(得分:6)
好吧,我想我找到了 答案..
在“线程模型”部分中说:
在多线程环境中使用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);
}
}
并添加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;
}
clutter_threads_add_idle_full负责线程锁定等。
答案 1 :(得分:0)
我玩了你的代码,看起来你做的一切都还好,虽然我不是Clutter的专家。我还在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
显然崩溃发生在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);
所以我们知道您的代码似乎没问题。
我们建议您将问题发送到Clutter discussion and help邮件列表: clutter-app-devel-list
使用Clutter的应用程序开发人员的邮件列表,其集成库或基于Clutter的工具包。
答案 2 :(得分:0)
我在Python绑定中遇到了非常类似的混乱情况。我无法以我想要的方式使Clutter线程支持工作。
最后诀窍是使用空闲proc(python中的gobject.idle_add)将我需要完成的工作推送到主要的混乱线程中。这样我只有1个线程进行杂乱调用,一切都很好。
答案 3 :(得分:0)
您可以使用clutter_threads_add_idle
更新ClutterActor
,也可以修复clutter_threads_enter/leave
以切换OpenGL上下文,以便在线程中使用它。
崩溃
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
是因为调用线程没有获取OpenGL上下文所以它崩溃了。