Threads Module User's Guide : PART II Concurrency Packages : Chapter 4 The Synchronization Package : The Synchronization Classes : The RWFIFOMutexLock Class
The RWFIFOMutexLock Class
The RWFIFOMutexLock is a special form of mutex that preserves thread acquisition ordering when granting ownership of the mutex. Except for the guarantee of FIFO acquisition semantics, this class has the same methods and features as the RWMutexLock class and can be used in an identical fashion.
The RWNullMutexLock Class
The RWNullMutexLock class is a special type of mutex that does nothing. It has the same interface as an RWMutexLock, but all of the functions are null. This feature is important when code is used in non-multithread situations because it saves execution time.
The RWTRecursiveLock Class
The RWTRecursiveLock template class converts other mutex classes, such as RWMutexLock or RWFIFOMutexLock, into a mutex that supports recursive acquisition semantics.
A thread acquires ownership of a recursive mutex the first time acquire() is called. Any subsequent calls to acquire() without an intervening call to release() cause an internal acquire-count value to be incremented. The internal count is used to ensure that a recursive mutex is released as many times as it was acquired before ownership is relinquished.
The RWTRecursiveLock template class is most useful for building monitors that allow one member function to call another member function in the same instance without producing deadlock.
Identifying Threads
Recursive locks must acquire a value that uniquely identifies a thread of execution. This value helps determine whether the recursive lock blocks or simply increments its count.
A thread “id” might also be required:
When you need to directly call the underlying API.
When doing your own thread identification within both your program logic and any debug or status output that you produce.
Thread identification is implemented by the following functions:
RWThreadId rwThreadId()
RWThreadId RWRunnableHandle::threadId() (in the Threading package)
The Synchronization package encapsulates the underlying thread id using the RWThreadId class. Instances of this class can be used just as if they are instances of the underlying thread id type. That’s because the RWThreadId class defines constructors and conversion operators that allow it to be used in this manner.
You can use the rwThreadId() function to retrieve the id of the current or calling thread. Any thread can call this function, not just threads created by the library.
Using RWTRecursiveLock
In Example 36, the date function must lock the entire Date instance to prevent partial changes while the day, month, and year accessor functions acquire and release the mutex to protect their individual members. The recursive mutex allows the date function to use the day, month, and year accessors without producing deadlock.
Example 36 – Preventing deadlock with a recursive mutex
class Date {
private:
RWTRecursiveLock<RWMutexLock> mutex_;
unsigned int day_;
unsigned int month_;
int year_;
...
public:
unsigned int day() const {
RWTRecursiveLock<RWMutexLock>::LockGuard lock(
const_cast<Date*>(this)->mutex_);
return day_;
}
void day(unsigned int newDay) {
RWTRecursiveLock<RWMutexLock>::LockGuard lock(
const_cast<Date*>(this)->mutex_);
day_ = validateDay(newDay);
}
unsigned int month() const {
RWTRecursiveLock<RWMutexLock>::LockGuard lock(
const_cast<Date*>(this)->mutex_);
return month_;
}
void month(unsigned int newMonth) {
RWTRecursiveLock<RWMutexLock>::LockGuard lock(
const_cast<Date*>(this)->mutex_);
month_ = validateMonth(newMonth);
}
int year() const {
RWTRecursiveLock<RWMutexLock>::LockGuard lock(
const_cast<Date*>(this)->mutex_);
return year_;
}
 
void year(int newYear) {
RWTRecursiveLock<RWMutexLock>::LockGuard lock(
const_cast<Date*>(this)->mutex_);
year_ = validateYear(newYear);
}
RWCString date() const {
RWTRecursiveLock<RWMutexLock>::LockGuard lock(
const_cast<Date*>(this)->mutex_);
char buf[11];
sprintf(buf,”%02d-%02d-%04d”,month(),day(),year());
return RWCString(buf);
}
...
};