Click here to Skip to main content
15,896,201 members
Articles / Programming Languages / C++

Shared and Exclusive lock control

Rate me:
Please Sign up or sign in to vote.
3.05/5 (7 votes)
31 Aug 20042 min read 44.3K   629   11  
C++ class for shared and exclusive lock control.
/*-------------------------------------------------------------------
Definition of class LOCKER

Function:  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.

Operating System:  Windows 98 or higher
                    Can be ported to other operating systems
                    by replacing:
                      Internal Class EXCLUSIVE_EX
                      Internal Class Semaphore
                      Internal Class ProcIdentity
Usage:    Locks 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.

          Calling sequences:

          In the parent thread:
            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).

Release Notes:
08/24/2004  Original Release
08/31/2004  Version 1.1
            1. Fixed a bug that caused a loop during RelLock
            2. Performance enhancement - 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 tests and
                how to run them.
            6. Created a separate VC workspace that contains only the
                Locker projects (Locker.dsp and Tlocker.dsp).
---------------------------------------------------------------------*/

#ifndef   LOCKER_H
#define   LOCKER_H
#include "barebones_windows.h"
#include <windows.h>

#define   LOCK_OK       0         // Function completed normally
#define   LOCK_NOT_HELD 1         // TestLock: Lock not held
#define   LOCK_SHARED   2         // Lock held SHARED
#define   LOCK_EXCL     3         // Lock held EXCLUSIVE
#define   LOCK_ERROR    -1        // LNAMEL > MAXLOCKNAME --
                                  // Function failed.

#define   MAXLOCKNAME   64


class Locker
{
private:

//-----------------------------------------
// Private Class for serializing thread execution.
//-----------------------------------------
class EXCLUSIVE_EX            // Replace with appropriate code for any ports.
                              // Serializes only threads that are in Locker code.
                              // Other threads can still run.
{
private:

// HANDLE   Event;               // Windows EVENT
CRITICAL_SECTION  crit;

public:

/*

EXCLUSIVE_EX()   {Event=CreateEvent(NULL,FALSE,FALSE,NULL);}; // Initially-nonsignaled event
                                                              // that releases one waiter
                                                              // per pulse.
~EXCLUSIVE_EX()  {CloseHandle(Event);};
void   Get()     {WaitForSingleObject(Event,INFINITE);};
void   Release() {PulseEvent(Event);};
*/
EXCLUSIVE_EX()   {InitializeCriticalSection(&crit);};
~EXCLUSIVE_EX()  {DeleteCriticalSection(&crit);};
void   Get()     {EnterCriticalSection(&crit);};
void   Release() {LeaveCriticalSection(&crit);};

};


//-----------------------------------------
// Private Class for serializing locks.
//-----------------------------------------
class Semaphore
                              // Replace with appropriate code for any ports.
{
private:

HANDLE   Event;                     // Windows EVENT

public:

Semaphore()      {Event=CreateEvent(NULL,TRUE,TRUE,NULL);};  // Initially-signaled event.
~Semaphore()     {CloseHandle(Event);};

void   Block()   {ResetEvent(Event);};
void   UnBlock() {PulseEvent(Event);};
void   Wait()    {WaitForSingleObject(Event,INFINITE);};
};


class ProcIdentity
{
public:

DWORD  ProcId;
DWORD  ThreadId;

ProcIdentity()
     {
     ProcId=GetCurrentProcessId();  // Thread's identity
     ThreadId=GetCurrentThreadId(); // Search for thread's lock entry
     };
~ProcIdentity()  {};

BOOL Compare(ProcIdentity *pid)
     {
     if (pid->ProcId==ProcId && pid->ThreadId==ThreadId) return TRUE;
     return FALSE;
     };
};



//-------------------------------------------
// Private data type definitions
//-------------------------------------------
typedef struct LOCKUSER_
{
struct LOCKUSER_  *prev;
struct LOCKUSER_  *next;
ProcIdentity      *pid;
int               locktype;           // LOCK_SHARED | LOCK_EXCL
} *PLOCKUSER;


typedef struct LOCKLIST_
{
Semaphore         *Semaphore;         // Blocked only when an EXLUSIVE lock
                                      //  is on the list.
struct LOCKLIST_  *next;
struct LOCKLIST_  *prev;
int               lnamel;             // Lock name length
char              lname[MAXLOCKNAME]; // Lock name
PLOCKUSER         users;
} *PLOCKLIST;

//-------------------------------------------
// Private data areas
//-------------------------------------------
PLOCKLIST        locks;
EXCLUSIVE_EX     *Ex;

//-------------------------------------------
// Private functions
//-------------------------------------------
PLOCKLIST  FindL(const void *lname, int lnamel);
PLOCKLIST  MakeL(const void *lname, int lnamel);
PLOCKUSER  FindLock(const void *lname, int lnamel, ProcIdentity *pid);
void       InsertLock(const void *lname, int lnamel, int locktype, ProcIdentity *pid);
void       WaitForLock(PLOCKLIST, ProcIdentity *pid, int locktype);

//-------------------------------------------
// Public functions
//-------------------------------------------
public:

Locker();
~Locker();

int   GetSharedLock(const void *lname, int lnamel),
      GetExclLock(const void *lname, int lnamel),
      RelLock(const void *lname, int lnamel),
      TestLock(const void *lname, int lnamel);
};



#endif  // LOCKER_H

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
United States United States
Application and systems programmer since 1972.
Mostly mainframe programming - Assembler, PL/X.
Products: IBM: DFSMSHSM, Candle Corp: Omegamon (IMS and MVS), PKWARE: SecureZIP


Dabble in Windows and Linux at home - C++ and Intel Assembler.

Comments and Discussions