# マニュアルページ stream_locker.3

## 名前

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