2011-04-28 16:35:58 +02:00
|
|
|
/*
|
|
|
|
*
|
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
|
2011-04-28 16:35:58 +02:00
|
|
|
* 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
|
2011-04-28 16:35:58 +02:00
|
|
|
* 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
|
2011-04-28 16:35:58 +02:00
|
|
|
* 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
|
2011-04-28 16:35:58 +02:00
|
|
|
|
|
|
|
enum LockType {
|
2011-04-30 04:28:31 +02:00
|
|
|
LOCK_TYPE_NONE,
|
|
|
|
LOCK_TYPE_EXCLUSIVE,
|
|
|
|
LOCK_TYPE_SHARED,
|
|
|
|
LOCK_TYPE_INVALID
|
2011-04-28 16:35:58 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
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;
|
2011-04-28 16:35:58 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class SyncObject : public SynchronizationObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SyncObject()
|
2011-04-30 04:28:31 +02:00
|
|
|
: waiters(0),
|
|
|
|
monitorCount(0),
|
|
|
|
exclusiveThread(NULL),
|
|
|
|
waitingThreads(NULL)
|
2011-04-28 16:35:58 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~SyncObject()
|
2011-04-30 04:28:31 +02:00
|
|
|
{
|
|
|
|
}
|
2011-04-28 16:35:58 +02:00
|
|
|
|
2011-04-30 04:28:31 +02:00
|
|
|
virtual void lock(Sync* sync, LockType type);
|
2011-04-28 16:35:58 +02:00
|
|
|
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 16:35:58 +02:00
|
|
|
|
2011-04-28 18:59:29 +02:00
|
|
|
virtual void downgrade(LockType type);
|
2011-04-28 16:35:58 +02:00
|
|
|
|
2011-04-28 18:59:29 +02:00
|
|
|
LockType getState() const
|
2011-04-28 16:35:58 +02:00
|
|
|
{
|
|
|
|
if (lockState.value() == 0)
|
2011-04-30 04:28:31 +02:00
|
|
|
return LOCK_TYPE_NONE;
|
2011-04-28 16:35:58 +02:00
|
|
|
|
|
|
|
if (lockState.value() < 0)
|
2011-04-30 04:28:31 +02:00
|
|
|
return LOCK_TYPE_EXCLUSIVE;
|
2011-04-28 16:35:58 +02:00
|
|
|
|
2011-04-30 04:28:31 +02:00
|
|
|
return LOCK_TYPE_SHARED;
|
2011-04-28 16:35:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2011-04-28 16:35:58 +02:00
|
|
|
|
|
|
|
void sysServiceFailed(const char* service, int code);
|
2011-04-28 18:59:29 +02:00
|
|
|
void assertionFailed();
|
2011-04-28 16:35:58 +02:00
|
|
|
|
|
|
|
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();
|
2011-04-28 16:35:58 +02:00
|
|
|
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-28 16:35:58 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-04-30 04:28:31 +02:00
|
|
|
class Sync
|
2011-04-28 16:35:58 +02:00
|
|
|
{
|
2011-04-30 04:28:31 +02:00
|
|
|
friend class ThreadSync;
|
|
|
|
|
2011-04-28 16:35:58 +02:00
|
|
|
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 16:35:58 +02:00
|
|
|
{
|
2011-04-28 18:59:29 +02:00
|
|
|
fb_assert(obj);
|
2011-04-28 16:35:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
~Sync()
|
|
|
|
{
|
2011-04-30 04:28:31 +02:00
|
|
|
fb_assert(state != LOCK_TYPE_INVALID);
|
2011-04-28 16:35:58 +02:00
|
|
|
|
2011-04-30 04:28:31 +02:00
|
|
|
if (syncObject && state != LOCK_TYPE_NONE)
|
2011-04-28 16:35:58 +02:00
|
|
|
{
|
|
|
|
syncObject->unlock(this, state);
|
2011-04-30 04:28:31 +02:00
|
|
|
state = LOCK_TYPE_INVALID;
|
2011-04-28 16:35:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
2011-04-28 16:35:58 +02:00
|
|
|
{
|
|
|
|
where = fromWhere;
|
|
|
|
lock(type);
|
|
|
|
}
|
|
|
|
|
|
|
|
void unlock()
|
|
|
|
{
|
2011-04-30 04:28:31 +02:00
|
|
|
fb_assert(state != LOCK_TYPE_NONE);
|
2011-04-28 16:35:58 +02:00
|
|
|
syncObject->unlock(this, state);
|
2011-04-30 04:28:31 +02:00
|
|
|
state = LOCK_TYPE_NONE;
|
2011-04-28 16:35:58 +02:00
|
|
|
}
|
|
|
|
|
2011-04-28 18:59:29 +02:00
|
|
|
void downgrade(LockType type)
|
2011-04-28 16:35:58 +02:00
|
|
|
{
|
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-28 16:35:58 +02:00
|
|
|
}
|
|
|
|
|
2011-04-30 04:28:31 +02:00
|
|
|
void setObject(SynchronizationObject* obj)
|
2011-04-28 16:35:58 +02:00
|
|
|
{
|
2011-04-30 04:28:31 +02:00
|
|
|
if (syncObject && state != LOCK_TYPE_NONE)
|
2011-04-28 16:35:58 +02:00
|
|
|
syncObject->unlock(this, state);
|
|
|
|
|
2011-04-30 04:28:31 +02:00
|
|
|
state = LOCK_TYPE_NONE;
|
2011-04-28 16:35:58 +02:00
|
|
|
syncObject = obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
2011-04-30 04:28:31 +02:00
|
|
|
LockType state;
|
|
|
|
LockType request;
|
|
|
|
SynchronizationObject* syncObject;
|
|
|
|
Sync* prior; // not used
|
|
|
|
const char* where;
|
2011-04-28 16:35:58 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class SyncLockGuard : public Sync
|
|
|
|
{
|
|
|
|
public:
|
2011-04-30 04:28:31 +02:00
|
|
|
SyncLockGuard(SynchronizationObject* obj, LockType type, const char* fromWhere)
|
|
|
|
: Sync(obj, fromWhere)
|
2011-04-28 16:35:58 +02:00
|
|
|
{
|
|
|
|
lock(type);
|
|
|
|
}
|
|
|
|
|
|
|
|
~SyncLockGuard()
|
|
|
|
{
|
2011-04-30 04:28:31 +02:00
|
|
|
//fb_assert(state != LOCK_TYPE_NONE);
|
|
|
|
if (state != LOCK_TYPE_NONE)
|
2011-04-28 16:35:58 +02:00
|
|
|
unlock();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class SyncUnlockGuard : public Sync
|
|
|
|
{
|
|
|
|
public:
|
2011-04-30 04:28:31 +02:00
|
|
|
SyncUnlockGuard(SynchronizationObject* obj, const char* fromWhere)
|
|
|
|
: Sync(obj, fromWhere)
|
2011-04-28 16:35:58 +02:00
|
|
|
{
|
|
|
|
oldState = state;
|
|
|
|
|
2011-04-30 04:28:31 +02:00
|
|
|
fb_assert(oldState != LOCK_TYPE_NONE);
|
|
|
|
if (oldState != LOCK_TYPE_NONE)
|
2011-04-28 16:35:58 +02:00
|
|
|
unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
~SyncUnlockGuard()
|
|
|
|
{
|
2011-04-30 04:28:31 +02:00
|
|
|
if (oldState != LOCK_TYPE_NONE)
|
2011-04-28 16:35:58 +02:00
|
|
|
lock(oldState);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
LockType oldState;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace Firebird
|
|
|
|
|
|
|
|
#endif // CLASSES_SYNCOBJECT_H
|