iostream ライブラリのマルチスレッドに対する安全性に制限があるのは、iostream ライブラリで使用しているプログラミング手法の多くが、共有 iostream オブジェクトを使用するマルチスレッド環境では正しく実行できないためです。
「MT-安全」にするには、次の例のように、エラーを起こすような入出力操作を伴う危険領域では、入出力のエラーを調べる必要があります。
#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 関数の呼び出しを行う必要があります。次の例を参照してください。
#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-安全」にするには、ユーザー定義型に対して定義された入出力操作で特定の操作順序を持つものは、ロックして危険領域を定義する必要があります。次の例を参照してください。
#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;
}