65.9K
CodeProject is changing. Read more.
Home

Shared and Exclusive lock control

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.05/5 (7 votes)

Aug 26, 2004

2 min read

viewsIcon

44902

downloadIcon

630

C++ class for shared and exclusive lock control.

Introduction

This article shows a C++ class that provides access to named locks on a Shared and Exclusive basis within a process. The function is similar to the IBM OS/390 ENQ/DEQ macros.

  1. RET=HAVE is implied.
  2. The lock name is LOCKNAME/LOCKNAME_LENGTH pair rather than a QNAME/RNAME/RNAMEL combination.

A thread can request exclusive or shared ownership of a lock. Ownership is granted based on the following table:

Request

Held by other threads

Action

EXCLUSIVE

NONE

Granted

EXCLUSIVE

ANY

Wait

SHARED

NONE/SHARED

Granted

SHARED

EXCLUSIVE (any)

Wait

Threads placed in a wait state are released when the lock becomes available. Any EXCLUSIVE request blocks all requests following it until the EXCLUSIVE request is released.

Background

Written in ANSI C++, except for the three internal classes described below.

Needed to be able to refine the Windows CRITICAL_SECTION function into shareable and exclusive locks for thread control.

Can be ported to other environments with minimal changes.

Replace:

  • Internal class EXCLUSIVE_EX.
  • Internal class Semaphore.
  • Internal class ThreadIdentity

Using the code

Lock names may contain binary codes, for instance, an address. All compares, copies, etc. use the mem*** C++ functions. The maximum length for a lock name is 64 bytes (parameterized within locker.h).

How to use Locker:

In the parent thread, create an instance of the Locker class.

Locker  *Lockset;
Lockset=new Locker()

Pass Lockset to child threads that need access to the locks.

In any thread with access to Lockset:

    int rc;

    rc=Lockset->GetSharedLock(const char *lname, int lnamel);
      Returns LOCK_OK        (lock established)
              LOCK_SHARED    (Shared lock already held)
              LOCK_EXCL      (Exclusive lock already held)
              LOCK_ERROR     (LNAMEL > MAXLOCKNAME)

    rc=Lockset->GetExclLock(const char *lname, int lnamel);
      Returns LOCK_OK     (lock established)
              LOCK_SHARED (Shared lock already held)
                          The lock state was NOT changed
                          to Exclusive, and remains in
                          effect as Shared.
              LOCK_EXCL   (Exclusive lock already held)
              LOCK_ERROR  (LNAMEL > MAXLOCKNAME)

    rc=Lockset->RelLock(const char *lname, int lnamel);
      Returns LOCK_OK          (lock released)
              LOCK_NOT_HELD    (lock wasn't held)
              LOCK_ERROR       (LNAMEL > MAXLOCKNAME)

    rc=Lockset->TestLock(const char *lname, int lnamel);
      Returns LOCK_SHARED   (Shared lock held)
              LOCK_EXCL     (Exclusive lock held)
              LOCK_NOT_HELD (lock wasn't held)
              LOCK_ERROR    (LNAMEL > MAXLOCKNAME)

When all threads are no longer using the Lockset:

delete Lockset;

If any threads are still using the Lockset, the destructor terminates the process with an assert(0), preventing program checks in the active threads when they attempt to access the deleted class.

History

  • First release.
  • Version 1.1
    1. Fixed a bug that caused a loop during RelLock
    2. Performance enhancement and code simplification - changed RelLock to not remove the Lock structure when no users of a lock remain. Lock structures are now removed a destructor time only.
    3. Updated Locker.h Locker.cpp to move all Windows-specific code into Locker internal classes, making ports to other systems easier.
    4. Updated Tlocker.cpp to use the data base address as the lock.
    5. Added tlocker_readme.txt file to describe the test program and how to run it.
    6. Created a separate VC workspace that contains only the Locker project (Locker.dws, Locker.dsp, and Tlocker.dsp).