C++ ライブラリ・リファレンス

「MT-安全」の iostream ライブラリの制限

iostream ライブラリのマルチスレッドに対する安全性に制限があるのは、iostream ライブラリで使用しているプログラミング手法の多くが、共有 iostream オブジェクトを使用するマルチスレッド環境では正しく実行できないためです。

エラー状態のチェック

「MT-安全」にするには、次の例のように、エラーを起こすような入出力操作を伴う危険領域では、入出力のエラーを調べる必要があります。


例 4-1 エラー状態のチェック

#include <iostream.h>
#include <rlocks.h>
enum iostate { IOok, IOeof, IOfail };

iostate read_number(istream& istr, int& num)
{
       stream_locker sl(istr, stream_locker::lock_now);

       istr >> num;

       if (istr.eof()) return IOeof;
       if (istr.fail()) return IOfail;
       return IOok;
}

この例では、stream_locker オブジェクトである sl のコンストラクタが istream オブジェクトの istr をロックしています。sl のデストラクタは、read_number の終了時に呼ばれ、istr のロックを解除します。

最後のフォーマットなし入力操作で抽出された文字の取得

「MT-安全」にするには、最も近いフォーマットなし入出力とそれに続く gcount 呼び出しの間に、iostream オブジェクトを排他的に使用するスレッド内で gcount 関数の呼び出しを行う必要があります。次の例を参照してください。


例 4-2 gcount の呼び出し

#include <iostream.h>	
#include <rlocks.h>
void fetch_line(istream& istr, char* line, int& linecount)
{
       stream_locker sl(istr, stream_locker::lock_defer);

       sl.lock(); // ストリーム istr をロック
       istr >> line;
       linecount = istr.gcount();
       sl.unlock(); // istr のロック解除
       ...
}

この例では、stream_locker クラスの lock メンバー関数および unlock メンバー関数がプログラム中で相互排他領域を定義しています。

ユーザー定義の入出力操作

「MT-安全」にするには、ユーザー定義型に対して定義された入出力操作で特定の操作順序を持つものは、ロックして危険領域を定義する必要があります。次の例を参照してください。


例 4-3 ユーザー定義の入出力操作

#include <rlocks.h>
#include <iostream.h>
class mystream: public istream {

       // その他の定義...
       int getRecord(char* name, int& id, float& gpa);
}

int mystream::getRecord(char* name, int& id, float& gpa)
{
       stream_locker sl(this, stream_locker::lock_now);

       *this >> name;
       *this >> id;
       *this >> gpa;
       return this->fail() == 0;
}