working on SWTSwing

現在、SWTSwingというプロジェクトに片足だけつっこんでいる。そして、ここ2週間ほど、SWTSwingのスレッドに関する問題について考えていた。
そして、その問題が今日解決できた。うれしー。しかし、以下をこれから英語になおしてChristopherさめ(SWTSwingのリーダー)に説明しなきゃだ。英語は、やっぱしんどい。

  • SWTスレッドから、AWTスレッドに仕事を投げたいことがある(処理をAWTスレッド上で行いたい。具体的にはmain()でDisplay#readAndDispatch()を呼ぶ前や、readAndDispatch()がtrueを返したときにwhileループ内で書きたいケース)
  • 通常のSwingアプリだと、SwingUtilities#invokeAndWait()を呼び出す。このメソッドはAWTイベントキューの最後にInvocationEventとして同期処理を積む。
  • しかし、SWTSwingの場合は、AWTイベントが流れてきたらそこでAWTスレッドを止めるようになっている(SWTのイベント処理と同期をとるため)ため、AWTスレッドが止まっており、invokeAndWait()で、イベントキューの末尾にイベントを追加しても実行されず、お互い待ち続けてデッドロック的状況になってしまう。
  • この問題を解決するため、SWTSwing用にDisplay#syncSwing(Runnable)という、専用のメソッドを追加する。このメソッドはAWTスレッドを止めている箇所を一時的に起こして優先的に同期処理をAWTスレッド上で行う。そのため、このメソッドが呼び出されるときは、常にAWTスレッドが既に待ち状態に入っている必要がある。
  • いつでもAWTスレッドが既に待ち状態になっているようにするために、Displayのコンストラクタで、SwingUtilities#invokeLater()でInvocationEventをpostしている。これにより、readAndDispatch()が呼ばれるより以前にも必ずAWTスレッドが待ち状態になっていることが保証される。