Windows2003-3790/windows/advcore/gdiplus/engine/runtime/lockable.hpp
2020-09-30 16:53:55 +02:00

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