#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 クラスオブジェクトへの基本的な操作のシーケンスを実装するために使用します。クラス stream_locker はマルチスレッド (MT) 安全な libC の新しい機能です。1 つの iostream オブジェクトに対して、一度に 1 つのスレッドしか操作を実行できない相互排他の領域を定義するために使用できます。
stream_locker オブジェクトはスレッド単位で適用されます。プロセス内の 1 つのスレッドが iostream オブジェクトをロックすると、ほかのスレッドは、その iostream オブジェクトを使用しようとしている間ブロックされます。stream_locker オブジェクトのスコープを使用すると、相互排他領域の境界を定義できます。stream_locker はローカルでのみ作成してください。グローバルまたは静的スコープで stream_locker を作成しないことをお勧めします。
stream_locker オブジェクトをローカルで作成すると、そのコンストラクタは相互排他領域の先頭を定義し、デストラクタは領域の終端を定義します。または lock() および unlock() メンバー関数を指定して、相互排他領域の境界を明示的に定義できます。
libC の MT-安全バージョンのすべての iostream クラスは、クラス stream_MT から派生します。このコンストラクタは、引数として指定されたストリームをロックします。
lock-choice フラグは、相互排他領域をどのように定義するかを示します。lock_defer の値は、領域が lock() および unlock() メンバー関数によって定義されることを示します。lock_now の値は stream_locker のコンストラクタとデストラクタによって定義されることを示します。lock_choice のデフォルト値は lock_now です。
クラス stream_rmutex は iostream クラスによって使用される再帰的相互排他です。これをアプリケーションで使用することはできません。
void lock();
void unlock();
例:
この最初の例では、stream_locker オブジェクトは、ファイル内の特定のオフセットへのシークとファイルからの読み取りが最小単位であり、元のスレッドがファイルを読み取る前に別のスレッドがファイルのオフセットを変更する可能性がないようにします。
{ fstream fs; stream_locker s_lock(fs); // lock the stream fs . . . . .// open file 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) { // read a line at a time instr.getline (ibuf, bufsize, '\n'); if (instr.eof()) break; // lock cout stream so the i/o operation is atomic lockout.lock(); // tag line and send to cout cout << thread_tag << ibuf << "\n"; lockout.unlock(); } }
Stream_locker クラスオブジェクトは角括弧であるため、相互排他領域の終端が暗黙的または明示的に定義されていない場合、ユーザーエラーであり、結果は不定です。