stream_locker(3CC4)

名前
stream_locker - iostream クラスオブジェクトのアプリケーション・レベルのロックに使用するクラス

形式

#include <rlocks.h>

class stream_locker {
public:
	enum lock_choice { lock_defer=0, lock_now=1 	};
	stream_locker(stream_MT&, lock_choice lock_flag=lock_now);
	stream_locker(stream_MT*, lock_choice lock_flag=lock_now);
	stream_locker(stream_rmutex&, lock_choice lock_flag=lock_now);
	stream_locker(stream_rmutex*, lock_choice lock_flag=lock_now);
	~stream_locker();
	void lock();
	void unlock();
};

機能説明

クラス stream_locker のインスタンスは、 iostream クラスのオブジェクトに対する基本操作のシーケンスを 実装するときに使用します。 このクラスは、マルチスレッド環境で使用しても安全な (MT-safe) libC の 新しい機能で、1 つの iostream オブジェクトに対して常に 1 つのスレッドからしか 操作ができない相互排他的な区域を定義できます。

stream_locker オブジェクトはスレッド単位で適用されます。 プロセス内の 1 つのスレッドが iostream オブジェクトをロックすると、 同じプロセス内の他のスレッドは、 その iostream オブジェクトの使用を試みている間ブロックされます。 stream_locker オブジェクトの有効範囲を使用すれば、 相互排他区域の境界を定義できます。 stream_locker は局所的にしか作成できません。 有効範囲が大域的または静的である stream_locker を作成することはお勧めできません。

stream_locker オブジェクトを局所的な有効範囲で作成すると、 そのコンストラクタは相互排他区域の先頭を定義し、 デストラクタは相互排他区域の終端を定義します。 または、メンバー関数の lock() と unlock() を使用すれば、 相互排他区域の境界を明示的に定義できます。

  コンストラクタ

stream_locker(stream_MT&, lock_choice lock_flag=lock_now);

stream_locker(stream_MT*, lock_choice lock_flag=lock_now);
    libC の MT-safe バージョンのすべての iostream クラスは、 stream_MT クラスから派生します。このコンストラクタは、 引数で指定されたストリームのロックを行います。

    lock-choice フラグは、相互排他区域をどのように定義するか を示します。このフラグが lock_defer の場合、相互排他区域は メンバー関数の lock() と unlock() によって定義されます。 lock_now の場合は stream_locker のコンストラクタと デストラクタによって定義されます。 lock_choice のデフォルト値は lock_now です。

stream_locker(stream_rmutex&, lock_choice lock_flag=lock_now);

stream_locker(stream_rmutex*, lock_choice lock_flag=lock_now);
    クラス stream_rmutex は、 iostream によって使用される 再帰相互排他ロック (recursive mutex) です。このクラスを アプリケーションで使用することはできません。

  メンバー関数
        void lock();
        void unlock();

使用例

最初の例で stream_locker オブジェクトは、ファイル内の特定の オフセットへのシークとファイルからの読み込みが最小単位で行われること、 さらにオリジナルのスレッドがファイルを読み取る前に別のスレッドがファイルの オフセットを変更する可能性がないことを保証します。

{
	fstream fs;
	stream_locker s_lock(&fs); // ストリーム fs をロック
	. . . . . // ファイルをオープン
	fs.seekg(offset, ios::beg);
	fs.read(buf, len);
}

オブジェクト s_lock のコンストラクタは、 fstream オブジェクトの fs と、有効範囲 (スコープ) の終わりで実行されたデストラクタをロックした後、 fs のロックを解除します。

2 番目の例は、 stream_locker オブジェクトのメンバー関数の lock() と unlock() を用いて、相互排他区域を明示的に定義する方法を示します。

const int bufsize = 256;
void print_tagged_lines(char *filename, int thread_tag) {
        char    ibuf[bufsize+1];
        stream_locker   lockout(cout, stream_locker::lock_defer);
        ifstream instr(filename);
  	while(1) {
	    // 一度に 1 行を読み取る
    	    instr.getline(ibuf, bufsize, '\n');
    	    if(instr.eof())
      		break;
            // cout ストリームをロック。入出力はアトミック (分割不可能)。
            lockout.lock();
            // 行にタグを付けて cout に送る
            cout << thread_tag << ibuf << "\n";
            lockout.unlock();
  	}
}

エラー

stream_locker クラスのオブジェクトは、かっこのように機能します。そのため、 相互排他区域の終端が暗黙的または明示的に定義されていないことは 誤りであり、その場合、結果は保証されません。