GUIへの応用

t-araki2007-02-18

PARDSの並行処理サポート機能を使って、テストとしてごく簡単なGTK+プログラムを書いてみた。ポイントは、SPAWNしたプロセスの出力をUIにどう反映するかの部分。SPAWNしたプロセスが例えばSyncListに出力を出していくとして、受け取り側でread()を実行すると、プロセスがブロックしてしまう。そうすると、GUIプログラムとしての他の処理(例えばボタンを押すと何かの反応をするとか)も処理されなくなってしまう。

これを解決するため、ちょっとしたヘルパーライブラリを作成した。

  • GTK+のファイルディスクリプタ待ち機能を使う
  • SyncListの内容を見て、値が決まるとパイプに書き込むプロセスを作成する
  • パイプに書き込まれると、GUI側でSyncListの値を読み込み(書き込まれているのでブロックしない)、書き込まれた内容に対応する処理を行う

という寸法。

中でやっていることはややこしいけど、ユーザは接続用の初期化関数を呼び出すだけ。初期化関数の中で、対応するSyncListの最初のセルへのポインタを渡す。

このSyncListはSyncListと定義する。Callbackクラスは上記のヘルパーライブラリで定義されているが、中身はほとんど空で、run()というvirtualなメンバ関数だけが宣言されている。

ユーザはCallbackクラスから継承して、自分のコールバック用クラスを作成する。run()を再定義すると、再定義されたrunがGUI側で呼び出される。run()の中で必要なデータはそのクラスのメンバ変数として定義する。

Callbackクラスはnewを使って確保すると、共有メモリ上に置かれるので、GUI側でもデータにアクセスできる。

プログラムの様子は添付した画像の通り。複数のプロセスからの入力を表示しつつ(ここにはMergerを使っている)、ボタンからの入力を受けつけている。

余談だが、作成中デバッグではまってしまった。printfデバッグしていたのだが、(マルチプロセスなので)どこでセグメンテーションフォールトが起こっているのか分らなくて…
今から考えると、gdbでプロセスをフォークする部分をひっかけて、新しく生成したプロセスに別のgdbからアタッチすれば良かったか? 次は試してみよう。