8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-02-01 08:43:02 +01:00
firebird-mirror/src/common/classes/SyncObject.h

239 lines
4.6 KiB
C
Raw Normal View History

/*
*
2011-04-30 04:28:31 +02:00
* The contents of this file are subject to the Initial
* Developer's Public License Version 1.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.ibphoenix.com/idpl.html.
*
* Software distributed under the License is distributed on
* an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
* express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The contents of this file or any work derived from this file
2011-04-30 04:28:31 +02:00
* may not be distributed under any other license whatsoever
* without the express prior written permission of the original
* author.
*
*
* The Original Code was created by James A. Starkey for IBPhoenix.
*
* Copyright (c) 1997 - 2000, 2001, 2003 James A. Starkey
* Copyright (c) 1997 - 2000, 2001, 2003 Netfrastructure, Inc.
* All Rights Reserved.
*
2011-04-28 18:59:29 +02:00
* The Code was ported into Firebird Open Source RDBMS project by
* Vladyslav Khorsun at 2010
*
* Contributor(s):
*/
#ifndef CLASSES_SYNCOBJECT_H
#define CLASSES_SYNCOBJECT_H
#include "../../common/classes/fb_atomic.h"
#include "../../common/classes/locks.h"
namespace Firebird {
2011-04-30 04:28:31 +02:00
#define SYNC_LOG_DEBUG
enum LockType {
2011-04-30 04:28:31 +02:00
LOCK_TYPE_NONE,
LOCK_TYPE_EXCLUSIVE,
LOCK_TYPE_SHARED,
LOCK_TYPE_INVALID
};
class Sync;
class ThreadSync;
class SynchronizationObject
{
public:
2011-04-30 04:28:31 +02:00
virtual void lock(Sync* sync, LockType type) = 0;
virtual void unlock(Sync* sync, LockType type) = 0;
2011-04-28 18:59:29 +02:00
virtual void downgrade(LockType type) = 0;
};
class SyncObject : public SynchronizationObject
{
public:
SyncObject()
2011-04-30 04:28:31 +02:00
: waiters(0),
monitorCount(0),
exclusiveThread(NULL),
waitingThreads(NULL)
{
}
virtual ~SyncObject()
2011-04-30 04:28:31 +02:00
{
}
2011-04-30 04:28:31 +02:00
virtual void lock(Sync* sync, LockType type);
bool lockConditional(LockType type);
2011-04-30 04:28:31 +02:00
virtual void unlock(Sync* sync, LockType type);
2011-04-28 18:59:29 +02:00
void unlock();
2011-04-28 18:59:29 +02:00
virtual void downgrade(LockType type);
2011-04-28 18:59:29 +02:00
LockType getState() const
{
if (lockState.value() == 0)
2011-04-30 04:28:31 +02:00
return LOCK_TYPE_NONE;
if (lockState.value() < 0)
2011-04-30 04:28:31 +02:00
return LOCK_TYPE_EXCLUSIVE;
2011-04-30 04:28:31 +02:00
return LOCK_TYPE_SHARED;
}
bool isLocked() const
{
return lockState.value() != 0;
}
bool hasContention() const
{
return (waiters.value() > 0);
}
2011-04-28 18:59:29 +02:00
bool ourExclusiveLock() const;
void sysServiceFailed(const char* service, int code);
2011-04-28 18:59:29 +02:00
void assertionFailed();
protected:
2011-04-30 04:28:31 +02:00
void wait(LockType type, ThreadSync* thread, Sync* sync);
ThreadSync* grantThread(ThreadSync* thread);
2011-04-28 18:59:29 +02:00
void grantLocks();
void validate(LockType lockType);
2011-04-30 04:28:31 +02:00
AtomicCounter lockState;
AtomicCounter waiters;
//int waiters;
int monitorCount;
Mutex mutex;
ThreadSync* volatile exclusiveThread;
ThreadSync* volatile waitingThreads;
};
2011-04-30 04:28:31 +02:00
class Sync
{
2011-04-30 04:28:31 +02:00
friend class ThreadSync;
public:
2011-04-30 04:28:31 +02:00
Sync(SynchronizationObject* obj, const char* fromWhere)
: state(LOCK_TYPE_NONE),
request(LOCK_TYPE_NONE),
syncObject(obj),
prior(NULL),
where(fromWhere)
{
2011-04-28 18:59:29 +02:00
fb_assert(obj);
}
~Sync()
{
2011-04-30 04:28:31 +02:00
fb_assert(state != LOCK_TYPE_INVALID);
2011-04-30 04:28:31 +02:00
if (syncObject && state != LOCK_TYPE_NONE)
{
syncObject->unlock(this, state);
2011-04-30 04:28:31 +02:00
state = LOCK_TYPE_INVALID;
}
}
void lock(LockType type)
{
request = type;
syncObject->lock(this, type);
state = type;
}
2011-04-30 04:28:31 +02:00
void lock(LockType type, const char* fromWhere)
{
where = fromWhere;
lock(type);
}
void unlock()
{
2011-04-30 04:28:31 +02:00
fb_assert(state != LOCK_TYPE_NONE);
syncObject->unlock(this, state);
2011-04-30 04:28:31 +02:00
state = LOCK_TYPE_NONE;
}
2011-04-28 18:59:29 +02:00
void downgrade(LockType type)
{
2011-04-30 04:28:31 +02:00
fb_assert(state == LOCK_TYPE_EXCLUSIVE);
2011-04-28 18:59:29 +02:00
syncObject->downgrade(type);
2011-04-30 04:28:31 +02:00
state = LOCK_TYPE_SHARED;
}
2011-04-30 04:28:31 +02:00
void setObject(SynchronizationObject* obj)
{
2011-04-30 04:28:31 +02:00
if (syncObject && state != LOCK_TYPE_NONE)
syncObject->unlock(this, state);
2011-04-30 04:28:31 +02:00
state = LOCK_TYPE_NONE;
syncObject = obj;
}
protected:
2011-04-30 04:28:31 +02:00
LockType state;
LockType request;
SynchronizationObject* syncObject;
Sync* prior; // not used
const char* where;
};
class SyncLockGuard : public Sync
{
public:
2011-04-30 04:28:31 +02:00
SyncLockGuard(SynchronizationObject* obj, LockType type, const char* fromWhere)
: Sync(obj, fromWhere)
{
lock(type);
}
~SyncLockGuard()
{
2011-04-30 04:28:31 +02:00
//fb_assert(state != LOCK_TYPE_NONE);
if (state != LOCK_TYPE_NONE)
unlock();
}
};
class SyncUnlockGuard : public Sync
{
public:
2011-04-30 04:28:31 +02:00
SyncUnlockGuard(SynchronizationObject* obj, const char* fromWhere)
: Sync(obj, fromWhere)
{
oldState = state;
2011-04-30 04:28:31 +02:00
fb_assert(oldState != LOCK_TYPE_NONE);
if (oldState != LOCK_TYPE_NONE)
unlock();
}
~SyncUnlockGuard()
{
2011-04-30 04:28:31 +02:00
if (oldState != LOCK_TYPE_NONE)
lock(oldState);
}
private:
LockType oldState;
};
} // namespace Firebird
#endif // CLASSES_SYNCOBJECT_H