6

我正在努力从一个额外的线程调用一个杂乱的函数。我使用 boost::thread 进行线程处理,并使用杂乱库 1.0。

具体来说,该线程包含一个循环函数,该函数每隔一段时间发出带有 x 和 y 坐标参数的 boost::signals2::signal 。该信号连接到一个函数,该函数将这些变量交给杂波,即 x,y in

clutter_stage_get_actor_at_pos(CLUTTER_STAGE(演员),CLUTTER_PICK_ALL,x,y);

这就是我遇到段错误的地方。

显然,clutter 有一些线程处理例程。我试着打电话

g_thread_init(NULL);

混乱线程初始化();

在开始 clutter_main() 之前。我还尝试将杂乱功能包含在

混乱线程输入();

clutter_stage_get_actor_at_pos(CLUTTER_STAGE(演员),CLUTTER_PICK_ALL,x,y);

混乱线程离开();

但这也不起作用..

感谢您的每一个提示,在此先感谢您!

附录

我只是伪造了我正在尝试做的最小样本。我已经按照建议“保护”了 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;
}
4

4 回答 4

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 函数(如提到的文档页面上的示例代码)

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 负责线程锁等。

于 2010-10-18T11:16:57.503 回答
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 上下文所以它崩溃了。

于 2012-01-05T10:20:49.920 回答
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 讨论和帮助邮件列表:clutter-app-devel-list

使用 Clutter、其集成库或基于 Clutter 的工具包的应用程序开发人员的邮件列表。

于 2010-09-30T15:13:21.280 回答
0

我在 Python 绑定中遇到了非常相似的情况,因为混乱。我永远无法使 Clutter 线程支持按我想要的方式工作。

最终的诀窍是使用空闲进程(python 中的 gobject.idle_add)将我需要完成的工作推送到主杂乱线程中。这样我只有 1 个线程进行混乱的调用,一切都很好。

于 2010-10-03T15:39:27.620 回答