stream_locker(3C++)

NAME
stream_locker - class used for application level locking of iostream class objects.

SYNOPSIS

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

DESCRIPTION
Instances of class stream_locker are used to implement an atomic sequence of operations on a iostream class object. The class stream_locker is a new feature of the multi-thread (MT) safe libC. It can be used to define a region of mutual exclusion in which only one thread can perform operations on an iostream object at any one time. A stream_locker object applies on a per thread basis. When one thread in a process locks an iostream object other threads are blocked while trying to use that iostream object. The scope of a stream_locker object can be used to define the bounds of the mutual exclusion region. A stream_locker should only be created locally. It is not recommended to create a stream_locker with global or static scope. When a stream_locker object is created locally, its constructor defines the beginning of the mutual exclusion region and the destructor defines the end of the region. Alternatively lock() and unlock() member functions are provided to define explicitly the bounds of a mutual exclusion region.

  Constructors

stream_locker(stream_MT&, lock_choice lock_flag=lock_now);
stream_locker(stream_MT*, lock_choice lock_flag=lock_now);

    All iostream classes in the MT safe version of libC are derived from class stream_MT. The constructor does the locking for the stream given as an argument. The lock-choice flag indicates how the mutual exclusion region is to be defined. A value of lock_defer indicates that the region is to be defined by the lock() and unlock() member functions. A value of lock_now indicates that the region is defined by the constructor and destructor of stream_locker. The default value of the lock_choice is lock_now.

stream_locker(stream_rmutex&, lock_choice lock_flag=lock_now); stream_locker(stream_rmutex*, lock_choice lock_flag=lock_now);

    Class stream_rmutex is the recursive mutex used by iostream classes. It is not available for use by applications.

  Member functions

void lock();
void unlock();
Examples: In this first example a stream_locker object ensures that a seek to a particular offset in a file and a read from the file is atomic and there is no possibility of another thread changing the file offset before the original thread reads the file.

{	fstream fs;
	stream_locker s_lock(fs); // lock the stream fs
	. . . . .// open file
	fs.seekg(offset, ios::beg);
	fs.read(buf, len);
}
The constructor of object s_lock locks the fstream object fs and the destructor, executed at end of scope, unlocks fs. The second example illustrates the use of explicit definition of the mutual exclusion region using lock() and unlock() member function calls of a stream_locker object.

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();
	}
}

ERRORS
Stream_locker class objects are bracketing so if the end of a mutual exclusion region is not defined implicitly or explicitly it is a user error and the result cannot be determined.