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 con-
structor defines the beginning of the mutual exclusion
region and the destructor defines the end of the region.
Alternatively lock() and unlock() member functions are pro-
vided 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 indi-
cates 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 ios-
tream classes. It is not available for use by applica-
tions.
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 defini-
tion 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.