class Lock { // (pure abstract) interface public : virtual ~Lock() = 0; // [to have it in vtbl] virtual void lock() = 0; virtual void unlock() = 0; }; class Id { // (pure abstract) interface public : virtual ~Id() = 0; // [to have it in vtbl] virtual bool isSelf() = 0; virtual void setSelf() = 0; }; class RecursiveLock : public Lock { public : RecursiveLock(Lock* twoLocks, Id& anId); virtual void lock(); // implements Lock::lock virtual void unlock(); // implements Lock::unlock private : Lock& waitLock; // lock to block upon int lockCount; // lock's reference count Id& ownerId; // lock's owner Lock& metaLock; // this data's guard }; RecursiveLock::RecursiveLock(Lock* twoLocks, Id& anId) : waitLock(twoLocks[0]), lockCount(0), // lock is initially unused, i.e. reference count zero ownerId(anId), // [not explicitly initialized here] metaLock(twoLocks[1]) { } void RecursiveLock::lock() { // loop to try acquiring lock; // may take several times since two locks are involved for (;;) { // data guard metaLock.lock(); // will only block shortly bool nonBlocking = (lockCount == 0 || ownerId.isSelf()); if (nonBlocking) { // lock is available or ours if (lockCount == 0) { // unused at the moment // get it waitLock.lock(); // won't block here ownerId.setSelf(); } lockCount++; // reference count } metaLock.unlock(); if (nonBlocking) { break; } // wait on actual lock waitLock.lock(); // may block longer // [needed, to acquire locks in a defined sequence, // to avoid deadlocks] waitLock.unlock(); } } void RecursiveLock::unlock() { // data guard metaLock.lock(); // will only block shortly // preconditions [not checked in this sample code]: // lockCount> 0 && ownerId.isSelf() lockCount--; // reference count if (lockCount == 0) { waitLock.unlock(); } metaLock.unlock(); }