152 lines
3.3 KiB
C++
152 lines
3.3 KiB
C++
|
/**************************************************************************\
|
||
|
*
|
||
|
* Copyright (c) 1999 Microsoft Corporation
|
||
|
*
|
||
|
* Module Name:
|
||
|
*
|
||
|
* Locking
|
||
|
*
|
||
|
* Abstract:
|
||
|
*
|
||
|
* Lockable: A base class for lockable objects, which contains a lock.
|
||
|
* Lock: Represents a held lock on an object (acquires and releases an
|
||
|
* object's lock in its constructor and destructor).
|
||
|
*
|
||
|
* Revision History:
|
||
|
*
|
||
|
* 02/22/1999 davidx
|
||
|
* Created it.
|
||
|
* 09/08/1999 agodfrey
|
||
|
* Moved to Runtime\Lockable.hpp
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
#ifndef _LOCKABLE_HPP
|
||
|
#define _LOCKABLE_HPP
|
||
|
|
||
|
namespace GpRuntime
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// TODO: Remove the 'Gp' prefix from GpLockable and GpLock
|
||
|
//
|
||
|
|
||
|
//--------------------------------------------------------------------------
|
||
|
// Base class for lockable API objects
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
class GpLockable
|
||
|
{
|
||
|
friend class GpLock;
|
||
|
|
||
|
public:
|
||
|
|
||
|
GpLockable()
|
||
|
{
|
||
|
LockCount = -1;
|
||
|
}
|
||
|
|
||
|
~GpLockable()
|
||
|
{
|
||
|
// Comment out to prevent Office crash. 3/14/00 -- ikkof
|
||
|
// ASSERTMSG(LockCount == -1, ("~GpLock: non-zero lock count"));
|
||
|
}
|
||
|
|
||
|
LONG* GetLockCount()
|
||
|
{
|
||
|
return &LockCount;
|
||
|
}
|
||
|
|
||
|
BOOL IsLocked() const
|
||
|
{
|
||
|
return (LockCount != -1);
|
||
|
}
|
||
|
|
||
|
VOID Reset()
|
||
|
{
|
||
|
LockCount = -1;
|
||
|
}
|
||
|
|
||
|
// Copy constructor and assignment operator
|
||
|
|
||
|
GpLockable(GpLockable & lockable)
|
||
|
{
|
||
|
LockCount = -1;
|
||
|
}
|
||
|
|
||
|
GpLockable &operator=(const GpLockable & lockable)
|
||
|
{
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
LONG LockCount; // number of locks, minus one
|
||
|
};
|
||
|
|
||
|
//--------------------------------------------------------------------------
|
||
|
// Class for locking API objects
|
||
|
// NOTE: These locks are not reentrant!
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
class GpLock
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
GpLock(GpLockable* lockable)
|
||
|
{
|
||
|
// In flatapi, we sometimes need to check if an optional (NULL)
|
||
|
// parameter is busy, which means we would pass NULL into this
|
||
|
// constructor. An optional parameter should not be considered locked.
|
||
|
if (lockable != NULL)
|
||
|
{
|
||
|
LockCount = &lockable->LockCount;
|
||
|
|
||
|
// Note that it generates less code when we store the result
|
||
|
// here than it is to convert to a BOOL here and store that.
|
||
|
|
||
|
Result = InterlockedIncrement(LockCount);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Result = 0;
|
||
|
LockCount = &Result;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
~GpLock()
|
||
|
{
|
||
|
InterlockedDecrement(LockCount);
|
||
|
}
|
||
|
|
||
|
BOOL IsValid() const
|
||
|
{
|
||
|
return (Result == 0);
|
||
|
}
|
||
|
|
||
|
BOOL LockFailed() const
|
||
|
{
|
||
|
return (Result != 0);
|
||
|
}
|
||
|
|
||
|
VOID MakePermanentLock()
|
||
|
{
|
||
|
// This is useful when deleting an object. First, lock it, then
|
||
|
// leave it in a locked state. Technically the memory will be released
|
||
|
// and available for reuse, but the ObjectLock will still be left in
|
||
|
// a locked state.
|
||
|
|
||
|
LockCount = &Result;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
LONG Result;
|
||
|
LONG *LockCount;
|
||
|
};
|
||
|
|
||
|
}
|
||
|
|
||
|
#endif // !_LOCKABLE_HPP
|
||
|
|