Oracle Solaris Studio 12.2:C++ 用户指南

10.4.1.3 MT 安全的 iostream 限制

有关 iostream 库的 MT 安全性的限制定义意味着,用于 iostream 的许多编程常用方式在使用共享 iostream 对象的多线程环境中是不安全的。

检查错误状态

要实现 MT 安全,必须在具有可能导致出现错误的 I/O 操作的关键区中进行错误检查。以下示例说明了如何检查错误:


示例 10–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

获取通过上次未格式化输入操作提取的字符

要实现 MT 安全,必须在执行上次输入操作和 gcount 调用这一期间独占使用 istream 对象的线程内调用 gcount 函数。以下示例说明了对 gcount 的调用:


示例 10–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 类的成员函数 lockunlock 定义了程序中的互斥区域。

用户定义的 I/O 操作

要实现 MT 安全,必须锁定为用户定义类型定义且涉及对各个操作进行特定排序的 I/O 操作,才能定义关键区。以下示例说明了用户定义的 I/O 操作:


示例 10–3 用户定义的 I/O 操作


#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;
}