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

234 lines
4.1 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-05-14 23:44:07 +02:00
inline void SYNC_LOG_DEBUG(...) {}
2011-04-30 13:38:00 +02:00
enum SyncType {
SYNC_NONE,
SYNC_EXCLUSIVE,
SYNC_SHARED,
SYNC_INVALID
};
class Sync;
class ThreadSync;
2011-05-07 21:33:46 +02:00
class SyncObject
{
public:
SyncObject()
2011-04-30 04:28:31 +02:00
: waiters(0),
monitorCount(0),
exclusiveThread(NULL),
waitingThreads(NULL)
{
}
2011-04-30 13:38:00 +02:00
~SyncObject()
2011-04-30 04:28:31 +02:00
{
}
2011-04-30 13:38:00 +02:00
void lock(Sync* sync, SyncType type);
bool lockConditional(SyncType type);
2011-04-30 13:38:00 +02:00
void unlock(Sync* sync, SyncType type);
2011-04-28 18:59:29 +02:00
void unlock();
2011-04-30 13:38:00 +02:00
void downgrade(SyncType type);
2011-04-30 13:38:00 +02:00
SyncType getState() const
{
if (lockState.value() == 0)
2011-04-30 13:38:00 +02:00
return SYNC_NONE;
if (lockState.value() < 0)
2011-04-30 13:38:00 +02:00
return SYNC_EXCLUSIVE;
2011-04-30 13:38:00 +02:00
return SYNC_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;
protected:
2011-04-30 13:38:00 +02:00
void wait(SyncType type, ThreadSync* thread, Sync* sync);
2011-04-30 04:28:31 +02:00
ThreadSync* grantThread(ThreadSync* thread);
2011-04-28 18:59:29 +02:00
void grantLocks();
2011-04-30 13:38:00 +02:00
void validate(SyncType 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 13:38:00 +02:00
Sync(SyncObject* obj, const char* fromWhere)
: state(SYNC_NONE),
request(SYNC_NONE),
2011-04-30 04:28:31 +02:00
syncObject(obj),
prior(NULL),
where(fromWhere)
{
2011-04-28 18:59:29 +02:00
fb_assert(obj);
}
~Sync()
{
2011-04-30 13:38:00 +02:00
fb_assert(state != SYNC_INVALID);
2011-04-30 13:38:00 +02:00
if (syncObject && state != SYNC_NONE)
{
syncObject->unlock(this, state);
2011-04-30 13:38:00 +02:00
state = SYNC_INVALID;
}
}
2011-04-30 13:38:00 +02:00
void lock(SyncType type)
{
request = type;
syncObject->lock(this, type);
state = type;
}
2011-04-30 13:38:00 +02:00
void lock(SyncType type, const char* fromWhere)
{
where = fromWhere;
lock(type);
}
void unlock()
{
2011-04-30 13:38:00 +02:00
fb_assert(state != SYNC_NONE);
syncObject->unlock(this, state);
2011-04-30 13:38:00 +02:00
state = SYNC_NONE;
}
2011-04-30 13:38:00 +02:00
void downgrade(SyncType type)
{
2011-04-30 13:38:00 +02:00
fb_assert(state == SYNC_EXCLUSIVE);
2011-04-28 18:59:29 +02:00
syncObject->downgrade(type);
2011-04-30 13:38:00 +02:00
state = SYNC_SHARED;
}
2011-04-30 13:38:00 +02:00
void setObject(SyncObject* obj)
{
2011-04-30 13:38:00 +02:00
if (syncObject && state != SYNC_NONE)
syncObject->unlock(this, state);
2011-04-30 13:38:00 +02:00
state = SYNC_NONE;
syncObject = obj;
}
2011-05-09 12:15:19 +02:00
SyncType getState() const
{
return state;
}
protected:
2011-04-30 13:38:00 +02:00
SyncType state;
SyncType request;
SyncObject* syncObject;
2011-04-30 04:28:31 +02:00
Sync* prior; // not used
const char* where;
};
class SyncLockGuard : public Sync
{
public:
2011-04-30 13:38:00 +02:00
SyncLockGuard(SyncObject* obj, SyncType type, const char* fromWhere)
2011-04-30 04:28:31 +02:00
: Sync(obj, fromWhere)
{
lock(type);
}
~SyncLockGuard()
{
2011-04-30 13:38:00 +02:00
//fb_assert(state != SYNC_NONE);
if (state != SYNC_NONE)
unlock();
}
};
2011-05-10 03:12:14 +02:00
class SyncUnlockGuard
{
public:
2011-05-10 03:12:14 +02:00
SyncUnlockGuard(Sync& aSync) :
sync(aSync)
{
2011-05-09 12:15:19 +02:00
oldState = sync.getState();
2011-04-30 13:38:00 +02:00
fb_assert(oldState != SYNC_NONE);
if (oldState != SYNC_NONE)
2011-05-09 12:15:19 +02:00
sync.unlock();
}
~SyncUnlockGuard()
{
2011-04-30 13:38:00 +02:00
if (oldState != SYNC_NONE)
2011-05-09 12:15:19 +02:00
sync.lock(oldState);
}
private:
2011-04-30 13:38:00 +02:00
SyncType oldState;
2011-05-10 03:12:14 +02:00
Sync& sync;
};
} // namespace Firebird
#endif // CLASSES_SYNCOBJECT_H