#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 是多线程 (multi-thread, MT) 安全的 libC 的一项新功能。它可以用来定义一个互斥区域,在该区域中,一次只有一个线程可以对 iostream 对象执行操作。
stream_locker 对象以线程为单位进行应用。当进程中的一个线程锁定了某个 iostream 对象时,其他对象在尝试访问该 iostream 对象时会被阻止。可以使用 stream_locker 对象的作用域来定义互斥区域的边界。只应当在本地创建 stream_locker。建议不要创建具有全局或静态作用域的 stream_locker。
当在本地创建 stream_locker 对象时,其构造函数定义互斥区域的开头,析构函数定义该区域的末尾。另外,还提供了 lock() 和 unlock() 成员函数来显式定义互斥区域的边界。
libC 的多线程安全版本中的所有 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。
第二个示例说明了如何使用 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 类对象括在括号内,因此,如果未隐式或显式定义互斥区域的末尾,则这属于用户错误并且结果无法确定。