Sun Studio 12 Update 1: C++ ユーザーズガイド

11.4.1.3 マルチスレッドで使用しても安全な iostream の制約

iostream ライブラリのマルチスレッドでの安全性には制約があります。これは、マルチスレッド環境で iostream オブジェクトが共有された場合に、iostream を使用するプログラミング手法の多くが安全ではなくなるためです。

エラー状態のチェック

マルチスレッドでの安全性を実現するには、エラーの原因になる入出力操作を含んでいる危険領域で、エラーチェックを行う必要があります。エラーが発生したかどうかを確認するには次のようにします。


例 11–1 エラー状態のチェック


#include <iostream.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 がロックされます。このロックは、read_number が終了したときに呼び出される sl のデストラクタによって解除されます istr

最後の書式なし入力操作で抽出された文字列の取得

マルチスレッドでの安全性を実現するには、最後の入力操作と gcount の呼び出しを行う期間に、istream オブジェクトを排他的に使用するスレッドの内部から、gcount 関数を呼び出す必要があります。gcount は次のように呼び出します。


例 11–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(); // lock the stream istr
    istr >> line;
    linecount = istr.gcount();
    sl.unlock(); // unlock istr
    ...
}

この例では、stream_locker クラスの lock メンバー関数を呼び出してから unlock メンバー関数を呼び出すまでが、プログラムの相互排他領域になります。

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

マルチスレッドでの安全性を実現するには、別々の操作を特定の順番で行う必要があるユーザー定義型用の入出力操作を、危険領域としてロックする必要があります。この入出力操作の例を次に示します。


例 11–3 ユーザー定義の入出力操作


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

    // other definitions...
    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;
}