Architectural Patterns
[PART 3]
(Synchronization idioms & Pattern)

based on
Pattern-Oriented Software Architecture, Patterns for Concurrent and
Networked Objects, Volume 2
by Douglas Schmidt, Michael Stal, Hans Rohnert and Frank Buschmann
Scoped Locking
It ensures that a lock is acquired automatically when control enters a scope and released
automatically when control leaves the scope.
Implementation 1. Define a guard class that acquires and releases a lock in its constructor and destructor
respectively.
class Thread_Mutex_Guard {
private:
Thread_Mutex *lock_; // Pointer to lock.
bool owner_; // Set to true when a lock is acquired
Thread_Mutex_Guard (const Thread_Mutex_Guard&);
// //disallow copy constructor and = operator
void operator= (const Thread_Mutex_Guard &);
public:
Thread_Mutex_Guard (Thread_Mutex &lock): lock_ (&lock), owner_ (false) {
lock_->acquire (); owner_ = true; }
~Thread_Mutex_Guard () { if (owner_) lock_->release (); }
};
Scoped Locking
2. call the thread_Mutex_Guard class object inside the class / function
Class test {
int test1(int index) {
Thread_Mutex_Guard guard (lock_);
if (/* condition */) {
// Do some more work ...
return true; } // End of scope releases the lock.
Return false ; // End of scope releases the lock.
}
Private :
Thread_Mutex lock_;
};

Mutex Lock is acquired and released automatically as control enters and leaves the test1()
method respectively.
Two specific functions acquire() and release() can be created inside the
Thread_Mutex_Guard class to acquire the lock and release the lock. In acquire(), it should
be verified if lock is already acquired. In release() should be verified if lock is already
released. This way if lock is already released , then release() in destructor can verify it.
Strategized Locking
The Strategized Locking technique parameterizes synchronization
mechanisms that protect a component's critical sections from concurrent
access.
To increase performance on large-scale multi-processor platforms, it may be
required to change the synchronization strategy to more efficient e.g. from
thread mutex to readers/writer lock which is time-consuming and error
prone.
Strategized Locking, the family of locking mechanisms becomes more
reusable and easier to apply across applications.
Implementation 1. Define an abstract interface for the locking mechanisms
2. Define a guard class and pass specific concrete lock object based on
requirement.
3. Update the component interface and implementation
Strategized Locking
# Define an abstract interface for the locking mechanisms
class Lock {
public:
// define methods.
virtual void acquire () = 0;
virtual void release () = 0;
};
# Define concrete classes for each kind of lock (e.g. concrete class for mutex lock)
class Thread_Mutex_Lock : public Lock {
public:
Virtual void acquire () { lock_.acquire (); }
Virtual void release () { lock_.release (); }
private:
Thread_Mutex mutexLock_; // Concrete lock type.

friend class Guard; // Define <test> as a friend so it can access <mutexLock_>
};
Strategized Locking
# Define guard class
class Guard {
public:
Guard (Thread_Mutex &lock): lock_ (&lock), owner_ (false) { lock_->acquire
(); owner_ = true; }
~Guard () { if (owner_) lock_->release (); }
private:
// Pointer to the lock.
Thread_Mutex *lock_;
bool owner_;
};
Strategized Locking
# Implement the interface
Polymorphic lock can be passed to the component either as a parameter in its
constructor or by adding a lock template parameter to the component declaration.
class test 1{
public:
// pass the Constructor the concrete lock object
test (Lock & mutexLock_) : lock_ (mutexLock_) {}; // lock passed as a parameter in its
constructor
void Function1(const char *pathname) {
Guard guard (lock_);
//Critical section
return;
}
private:
Thread_Mutex *lock_;
};
Thread-Safe Interface
This pattern ensures If a method that uses the Scoped Locking idiom, does
not call itself recursively to avoid self-deadlock.
Double-Checked Locking Optimization This technique avoids race conditions when accessing and modifying shared
resources by concurrent application during program execution
Implementation –
• All interface methods, (e.g. C++ public methods) should only
acquire/release component lock(s).
•

Implementation methods should only perform the task when called by interface
methods.
Example –
Thread safe single ton class Implementation with Double-Checked Locking technique.
Thread-Safe Interface
Implementation –
# To protect the critical section from concurrent access , apply Scoped Locking.
class Singleton {
public:
static Singleton *instance () {
if (instance_ == 0)
Guard<Thread_Mutex> guard (singleton_lock_);
instance_ = new Singleton;
return instance_;
} // Destructor releases lock automatically
private:
static Singleton *instance_;
static Thread_Mutex singleton_lock_;
Singleton() { };
Singleton(const Singleton &) { };
Singleton& operator= (const Singleton &) { };
};
Thread-Safe Interface
# Introduce a check to avoid modifying “ instance_ “ when multiple threads access it
class Singleton
public:
static Singleton *instance () {
if (instance_ == 0) {
Guard<Thread_Mutex> guard (singleton_lock_);
if (instance_ == 0) {
instance_ = new Singleton;
} }
return instance_;
} // Destructor releases lock automatically
private:
static Singleton *instance_;
static Thread_Mutex singleton_lock_;
Singleton() { };
Singleton(const Singleton &) { };
Singleton& operator= (const Singleton &) { };
};
Thank You

Your suggestions and comments are always welcome.
Please send me your feedback at
a_s_sinha@yahoo.com

Architectural patterns part 3

  • 1.
    Architectural Patterns [PART 3] (Synchronizationidioms & Pattern) based on Pattern-Oriented Software Architecture, Patterns for Concurrent and Networked Objects, Volume 2 by Douglas Schmidt, Michael Stal, Hans Rohnert and Frank Buschmann
  • 2.
    Scoped Locking It ensuresthat a lock is acquired automatically when control enters a scope and released automatically when control leaves the scope. Implementation 1. Define a guard class that acquires and releases a lock in its constructor and destructor respectively. class Thread_Mutex_Guard { private: Thread_Mutex *lock_; // Pointer to lock. bool owner_; // Set to true when a lock is acquired Thread_Mutex_Guard (const Thread_Mutex_Guard&); // //disallow copy constructor and = operator void operator= (const Thread_Mutex_Guard &); public: Thread_Mutex_Guard (Thread_Mutex &lock): lock_ (&lock), owner_ (false) { lock_->acquire (); owner_ = true; } ~Thread_Mutex_Guard () { if (owner_) lock_->release (); } };
  • 3.
    Scoped Locking 2. callthe thread_Mutex_Guard class object inside the class / function Class test { int test1(int index) { Thread_Mutex_Guard guard (lock_); if (/* condition */) { // Do some more work ... return true; } // End of scope releases the lock. Return false ; // End of scope releases the lock. } Private : Thread_Mutex lock_; }; Mutex Lock is acquired and released automatically as control enters and leaves the test1() method respectively. Two specific functions acquire() and release() can be created inside the Thread_Mutex_Guard class to acquire the lock and release the lock. In acquire(), it should be verified if lock is already acquired. In release() should be verified if lock is already released. This way if lock is already released , then release() in destructor can verify it.
  • 4.
    Strategized Locking The StrategizedLocking technique parameterizes synchronization mechanisms that protect a component's critical sections from concurrent access. To increase performance on large-scale multi-processor platforms, it may be required to change the synchronization strategy to more efficient e.g. from thread mutex to readers/writer lock which is time-consuming and error prone. Strategized Locking, the family of locking mechanisms becomes more reusable and easier to apply across applications. Implementation 1. Define an abstract interface for the locking mechanisms 2. Define a guard class and pass specific concrete lock object based on requirement. 3. Update the component interface and implementation
  • 5.
    Strategized Locking # Definean abstract interface for the locking mechanisms class Lock { public: // define methods. virtual void acquire () = 0; virtual void release () = 0; }; # Define concrete classes for each kind of lock (e.g. concrete class for mutex lock) class Thread_Mutex_Lock : public Lock { public: Virtual void acquire () { lock_.acquire (); } Virtual void release () { lock_.release (); } private: Thread_Mutex mutexLock_; // Concrete lock type. friend class Guard; // Define <test> as a friend so it can access <mutexLock_> };
  • 6.
    Strategized Locking # Defineguard class class Guard { public: Guard (Thread_Mutex &lock): lock_ (&lock), owner_ (false) { lock_->acquire (); owner_ = true; } ~Guard () { if (owner_) lock_->release (); } private: // Pointer to the lock. Thread_Mutex *lock_; bool owner_; };
  • 7.
    Strategized Locking # Implementthe interface Polymorphic lock can be passed to the component either as a parameter in its constructor or by adding a lock template parameter to the component declaration. class test 1{ public: // pass the Constructor the concrete lock object test (Lock & mutexLock_) : lock_ (mutexLock_) {}; // lock passed as a parameter in its constructor void Function1(const char *pathname) { Guard guard (lock_); //Critical section return; } private: Thread_Mutex *lock_; };
  • 8.
    Thread-Safe Interface This patternensures If a method that uses the Scoped Locking idiom, does not call itself recursively to avoid self-deadlock. Double-Checked Locking Optimization This technique avoids race conditions when accessing and modifying shared resources by concurrent application during program execution Implementation – • All interface methods, (e.g. C++ public methods) should only acquire/release component lock(s). • Implementation methods should only perform the task when called by interface methods. Example – Thread safe single ton class Implementation with Double-Checked Locking technique.
  • 9.
    Thread-Safe Interface Implementation – #To protect the critical section from concurrent access , apply Scoped Locking. class Singleton { public: static Singleton *instance () { if (instance_ == 0) Guard<Thread_Mutex> guard (singleton_lock_); instance_ = new Singleton; return instance_; } // Destructor releases lock automatically private: static Singleton *instance_; static Thread_Mutex singleton_lock_; Singleton() { }; Singleton(const Singleton &) { }; Singleton& operator= (const Singleton &) { }; };
  • 10.
    Thread-Safe Interface # Introducea check to avoid modifying “ instance_ “ when multiple threads access it class Singleton public: static Singleton *instance () { if (instance_ == 0) { Guard<Thread_Mutex> guard (singleton_lock_); if (instance_ == 0) { instance_ = new Singleton; } } return instance_; } // Destructor releases lock automatically private: static Singleton *instance_; static Thread_Mutex singleton_lock_; Singleton() { }; Singleton(const Singleton &) { }; Singleton& operator= (const Singleton &) { }; };
  • 11.
    Thank You Your suggestionsand comments are always welcome. Please send me your feedback at a_s_sinha@yahoo.com