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);

そして、それが私がセグメンテーションフォールトを取得する場所です。

どうやらクラッターにはいくつかのスレッド処理ルーチンがあります。電話してみた

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() ルーチンを既に「保護」しています。clutter の一部の機能 (ステージの色の設定や俳優の位置の設定など) は、別のスレッドから動作しているようです。私のコードにまだ何か問題がありますか?

#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 Docs 一般

「スレッドモデル」のセクションで次のように述べています。

マルチスレッド環境で Clutter API を使用する唯一の安全で移植可能な方法は、clutter_init() と clutter_main() を呼び出さないスレッドから API にアクセスしないことです。

Clutter でスレッドを使用する一般的なパターンは、ワーカー スレッドを使用してブロッキング操作を実行し、スレッドが終了したときにアイドル状態のソースをインストールするか、その結果を使用してソースを時間計測することです。

Clutter は、提供されたコールバックを呼び出す前に Clutter ロックを取得する g_idle_add() および g_timeout_add() のスレッド対応バリアントを提供します: 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

私はクラッターの専門家ではありませんが、あなたのコードで遊んだところ、すべてうまくいっているようです。また、あなたのプログラムを 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 実装のバグが原因でクラッシュしたとは思えません。

*receive_loop()* がコールバックとして呼び出されることをテストしたので、*clutter_threads_enter/leave()* は *clutter_stage_get_actor_at_pos()* を保護していないようです。

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 バインディングで非常によく似た状況に苦労しました。クラッター スレッドのサポートを思うように動作させることはできませんでした。

最後にトリックを行ったのは、アイドル プロシージャ (Python では gobject.idle_add) を使用して、実行する必要のある作業をメイン クラッタ スレッドにプッシュすることでした。そうすれば、混乱した呼び出しを行うスレッドが 1 つしかなく、すべて問題ありません。

于 2010-10-03T15:39:27.620 に答える
0

を使用clutter_threads_add_idleして更新するか、 OpenGL コンテキストを切り替えてスレッド内で使用できるようClutterActorに修正する必要があります。clutter_threads_enter/leave

クラッシュ

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 に答える