この章では、ToolTalk セッションを結合する方法を説明します。同様に、ToolTalk サービスから渡される値の記憶を管理する方法、および ToolTalk サービスが返すエラーを処理する方法を説明します。
アプリケーションが ToolTalk サービスを使用するためには、ToolTalk API ライブラリの ToolTalk 関数を呼び出します。ToolTalk サービスを使用するためにアプリケーションを変更するには、最初に ToolTalk API ヘッダーファイルをプログラムに組み込まなければなりません。ToolTalk サービスを初期化し、セッションを結合した後、ファイルを結合し、追加のユーザーセッションを結合できます。処理を終了する準備ができたら、メッセージパターンの登録を解除し、ToolTalk セッションを終了します。
ToolTalk サービスを使用するためにアプリケーションを変更するには、最初に ToolTalk API ヘッダーファイルの tt_c.h をプログラムに組み込まなければなりません。このファイルは、/usr/dt/include/Tt ディレクトリにあります。
次のコード例は、このファイルをプログラムに組み込む方法を示しています。
#include <stdio.h> #include <sys/param.h> #include <sys/types.h> #include <Tt/tt_c.h> |
ToolTalk セッションを結合するためには、ToolTalk サービスにユーザープロセスを登録しなければなりません。アプリケーションを起動した ToolTalk セッション (「初期セッション」) に登録するか、他のセッションを検索して登録できます。
ToolTalk サービスに登録しなければならない ToolTalk 関数を表 7-1 に示します。
表 7-1 ToolTalk サービスへの登録
返される型 |
ToolTalk 関数 |
機能 |
---|---|---|
char * |
tt_open(void) |
プロセス識別子 |
int |
tt_fd(void) |
ファイル記述子 |
char * |
tt_X_session(const char *xdisplay) |
指定した X ディスプレイサーバーのセッション識別子を返す |
Tt_status |
tt_default_session_set(const char *sessid) |
tt_open の接続先セッションを設定する |
アプリケーションは、プロセスを初期化して初期 ToolTalk セッションに登録するために、プロセス識別子 (procid) を取得する必要があります。その後、新規に初期化した ToolTalk プロセスに対応するファイル記述子 (fd) を取得できます。
次のコード例では、まずサンプルプログラムを初期化し、ToolTalk サービスに登録します。その後、対応するファイル記述子を取得します。
int ttfd; char *my_procid; /* * Initialize ToolTalk, using the initial default session */ my_procid = tt_open(); /* * obtain the file descriptor that will become active whenever * ToolTalk has a message for this process. */ ttfd = tt_fd(); |
tt_open はプロセスの procid を返し、それをデフォルトの procid として設定します。tt_fd は、現在の procid のファイル記述子を返します。このファイル記述子は、アプリケーションにメッセージが到着すると使用可能になります。
アプリケーションは他の tt_ 呼び出しをする前に、tt_open を呼び出さなければなりません。そうしないと、エラーが発生する場合があります。ただし、いくつかの例外があります。tt_default_session_set と tt_X_session は、tt_open の前に呼び出して、接続するセッションを制御できます。ToolTalk をマルチスレッド環境で使用する場合は、tt_feature_required と tt_feature_enabled を呼び出すことができます。ToolTalk ファイル名マッピング API コールである tt_file_netfile、tt_netfile_file、tt_host_file_netfile、および tt_host_netfile_file を、tt_open を呼び出すことなく呼び出すことができます。
ToolTalk サービスに対する最初の呼び出しが tt_open である場合、デフォルトのセッションとして初期セッションが設定されます。デフォルトのセッション識別子 (sessid) は、ToolTalk メッセージの配信にとって重要です。アプリケーションがセッションのメッセージ属性を明示的に設定しない場合、ToolTalk サービスは、デフォルトの sessid を自動的に設定します。メッセージを TT_SESSION
に配信範囲と指定すると、メッセージは、この型のメッセージを処理対象として登録したデフォルトのセッション内のすべてのアプリケーションに配信されます。
プログラムは、初期セッション以外のセッションに登録する場合には、そのセッション名を検索し、新しいセッションをデフォルトとして設定し、ToolTalk サービスに登録しなければなりません。
次のコード例は、somehost:0 と命名された X セッションを結合する方法を示しています。このセッションは、初期セッションではありません。
char *my_session; char *my_procid; my_session = tt_X_session("somehost:0"); tt_default_session_set(my_session); my_procid = tt_open(); ttfd = tt_fd(); |
必要な呼び出しは、指定されている順番で行わなければなりません。
この呼び出しは、X ディスプレイサーバーに関連付けられているセッション名を検索します。tt_X_session() は、引数 char *xdisplay_name をとります。
xdisplay_name は、X ディスプレイサーバー名です (この例では、somehost:0 です)。
この呼び出しは、新しいセッションをデフォルトのセッションとして設定します。
この呼び出しは、プロセスの procid を返し、それをデフォルトの procid として設定します。
この呼び出しは、現在の procid のファイル記述子を返します。
メッセージを複数のセッション間で送受信したい場合もあります。複数のセッションに登録する場合、プログラムは接続したいセッションの識別子を検索し、新しいセッションを設定し、ToolTalk サービスに登録しなければなりません。
次のコード例は、procid を sessid1 に、procid2 を sessid2 に接続する方法を示しています。
tt_default_session_set(sessid1); my_procid1 = tt_open(); tt_default_session_set(sessid2); my_procid2 = tt_open(); tt_fd2 = tt_fd(); |
こうしておくと、tt_default_procid_set() を使用して、セッション間を切り替えることができます。
アプリケーションが他のアプリケーションからのメッセージを受信するためには、着信メッセージの有無を監視するプロセスを設定しなければなりません。メッセージがアプリケーションに到着すると、ファイル記述子が使用可能になります。ファイル記述子が使用可能になったことをアプリケーションに通知するコードは、アプリケーションの構成によって異なります。
たとえば、xv_main_loop または notify_start 呼び出しによって XView 通知子を使用するプログラムは、ファイル記述子が使用可能になったときにコールバック関数を呼び出すことができます。次のコード例は、メッセージオブジェクトのハンドルをパラメタとして notify_set_input_func を呼び出しています。
/* * Arrange for XView to call receive_tt_message when the * ToolTalk file descriptor becomes active. */ notify_set_input_func(base_frame, (Notify_func)receive_tt_message, ttfd); |
表 7-2 は、各種のウィンドウツールキットと着信メッセージの有無を監視する呼び出しを示したものです。
表 7-2 着信メッセージの有無を監視するモード
ウィンドウツールキット |
使用されるコード |
---|---|
XView |
notify_set_input_func() |
X Window System Xt (イントリンシクス) |
XtAddInput() または XtAddAppInput() |
他のツールキット (select(2) または poll(2) のシステムコールに基づいて構成された Xlib など) |
tt_fd() が返すファイル記述子 注 - ファイル記述子が使用可能になってから select 呼び出しを終了した場合は、tt_message_receive() を使用して、着信メッセージのハンドルを取得します。 |
受信側は、要求された操作を完了すると、通常そのメッセージを削除します。しかし、ToolTalk サービスでは受信側にも要求側にも同じメッセージ ID を使用するため、同じプロセス内で送受信を行うと、要求側にあるメッセージも削除されてしまいます。
この対処方法の 1 つは、メッセージに参照カウントを付加することです。そのためには、tt_message_user[_set]() 関数を使用します。
もう 1 つの対処方法は、送信側が現在の procid でない場合だけ、受信側のメッセージを破棄することです。次に例を示します。
Tt_callback_action my_pattern_callback(Tt_message m, Tt_pattern p) { /* normal message processing goes here */ if (0!=strcmp(tt_message_sender(m),tt_default_procid()) { tt_message_destroy(m); } return TT_CALLBACK_PROCESSED; } |
ToolTalk サービスをネットワーク環境で使用できます。たとえば、別のマシン上のツールを実行したり、別のマシン上で動作するセッションを結合したりできます。そのためには ttsession を起動する際に、-c または -p オプションを指定してください。
-c オプションを指定すると指定したプログラムが起動され、そのプログラムの TT_SESSION
環境変数に正しいセッション ID が設定されます。たとえば、次のコマンドを入力します。
ttsession -c dtterm |
cmdtool の TT_SESSION
環境変数が定義されるため、その値を $TT_SESSION
環境変数に設定して実行する ToolTalk クライアントはすべて、この ttsession が所有するセッションに結合されます。
-p オプションを指定すると、セッション ID が標準出力に出力されます。その後 ttsession は、バックグラウンドにセッションを生成し、そのセッションを起動します。
セッションを結合する際、アプリケーションは tt_open 関数を呼び出す前に、tt_default_session_set でセッション ID を設定するか、TT_SESSION
環境変数にセッション ID を設定しなければなりません。tt_open は TT_SESSION
環境変数を確認し、(値が設定されていれば) そのセッションを結合します。
ToolTalk サービスおよび他の ToolTalk セッション参加者との対話を停止したい場合は、アプリケーションを終了する前に、プロセスを「登録解除」しなければなりません。
/* * Before leaving, allow ToolTalk to clean up. */ tt_close(); exit(0); } |
tt_close は Tt_status を返し、現在のデフォルトの procid を閉じます。
ここでは、マルチスレッド環境における ToolTalk の使用方法について説明します。
マルチスレッドクライアントで ToolTalk ライブラリを使用するには、次のような初期化コールを必要とします。
tt_feature_required(TT_FEATURE_MULTITHREADED); |
このコールは、他のどの ToolTalk コールよりも前に呼び出しておく必要があります。他の ToolTalk API コールの後に tt_feature_required (TT_FEATURE_MULTITHREADED
) を呼び出そうとすると、TT_ERR_TOOLATE
エラーとなります。
ToolTalk を使用するライブラリやその他の再利用可能なモジュールは、ToolTalk ライブラリに照会して、呼び出しアプリケーションが ToolTalk のマルチスレッド機能を有効にしているかどうかを確認できます。tt_feature_enabled() API コールが、この目的のために追加されました。アプリケーションが初期化されているか知ることができるので、トップレベルのアプリケーションは tt_feature_enabled() をほとんど使う必要はありません。
ToolTalk クライアントが tt_open() または tt_session_join() を呼び出すと、新規 procid またはセッションがそのスレッドのデフォルトとなります。マルチスレッド以外の ToolTalk クライアントのときは、全プロセスが対象でしたが、ここではそうでありません。tt_open() または tt_session_join() への呼び出しが行われる前のスレッドの procid およびセッションのデフォルト値は、最初はスレッドの作成者のものと同様です。tt_open() または tt_session_join() によるデフォルト値の変更の他に、tt_thread_procid_set() と tt_thread_session_set() を使うと、以前に作成した他のデフォルト値を変更できます。procid とセッションのデフォルト値は、tt_thread_procid() と tt_thread_session() を使って検索できます。スレッドに特有の procid とセッション値は、スレッドに特有の記憶領域を使って管理します。スレッドに値が作成されていない場合は、ToolTalk プロセス全体におけるデフォルト値は代替値です。
tt_default_procid() と tt_thread_procid() (同様に、tt_default_session() と tt_thread_session()) によって返される値が、特定の時間においてスレッドによって違う場合があります。これは、tt_default_procid_set() と tt_default_session_set() が、スレッドのデフォルト値に影響しないためです。影響を受けるのは、ToolTalk 全体のプロセスのデフォルト値だけです。
ToolTalk が有効なアプリケーションでスレッドを使用することは、procid とセッションを切り換えるプログラムの自然な実装技術の 1 つです。これらのプログラムを使用して、ある時点でどの ToolTalk procid が ToolTalk セッションと関連を持っているかを簡単に判断できます。これは、ToolTalk の以前のバージョンで実行するのは困難でした。これを行うために、tt_procid_session() が提供されています。tt_procid_session() は、スレッドに依存しているわけではありませんが、ToolTalk でスレッドを使用するアプリケーションには有効です。
tt_mark() と tt_release() は、スレッド 1 つごとに割り当てている記憶領域に影響を与えますが、プロセス単位で割り当てている領域には影響ありません。したがって、tt_mark() を使って別のスレッドでマークを付けられた記憶領域を 1 つのスレッドが tt_release() を使って解放することはできません。
1 つのスレッドでメッセージを送信し、もう 1 つのスレッドでメッセージを処理する方法は、よく使われる技術です。ただし、別のスレッドがメッセージの内容を検査または処理している最中に tt_message_destroy() を使ってメッセージを破棄する場合には注意が必要です。受信スレッドが、別のスレッドが解放した記憶領域にアクセスしようとすると、プログラムクラッシュを引き起こします。これは、マルチスレッドにおけるアプリケーションの ToolTalk 以外の記憶領域の管理に類似していますが、ToolTalk API を使うと、より簡単になります。