|
/*-------------------------------------------------------------------
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.
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.