|
From: <hv...@us...> - 2011-04-28 14:36:10
|
Revision: 52832
http://firebird.svn.sourceforge.net/firebird/?rev=52832&view=rev
Author: hvlad
Date: 2011-04-28 14:35:58 +0000 (Thu, 28 Apr 2011)
Log Message:
-----------
Preparing for the shared page cache : new sync objects ported from Vulcan
Modified Paths:
--------------
firebird/trunk/builds/win32/msvc10/common.vcxproj
firebird/trunk/builds/win32/msvc10/common.vcxproj.filters
firebird/trunk/builds/win32/msvc8/common.vcproj
firebird/trunk/builds/win32/msvc9/common.vcproj
firebird/trunk/src/common/ThreadStart.cpp
firebird/trunk/src/common/classes/alloc.h
firebird/trunk/src/common/classes/fb_atomic.h
Added Paths:
-----------
firebird/trunk/src/common/classes/SyncObject.cpp
firebird/trunk/src/common/classes/SyncObject.h
firebird/trunk/src/common/classes/Synchronize.cpp
firebird/trunk/src/common/classes/Synchronize.h
Modified: firebird/trunk/builds/win32/msvc10/common.vcxproj
===================================================================
--- firebird/trunk/builds/win32/msvc10/common.vcxproj 2011-04-28 03:16:44 UTC (rev 52831)
+++ firebird/trunk/builds/win32/msvc10/common.vcxproj 2011-04-28 14:35:58 UTC (rev 52832)
@@ -35,6 +35,8 @@
<ClCompile Include="..\..\..\src\common\classes\SafeArg.cpp" />
<ClCompile Include="..\..\..\src\common\classes\semaphore.cpp" />
<ClCompile Include="..\..\..\src\common\classes\Switches.cpp" />
+ <ClCompile Include="..\..\..\src\common\classes\Synchronize.cpp" />
+ <ClCompile Include="..\..\..\src\common\classes\SyncObject.cpp" />
<ClCompile Include="..\..\..\src\common\classes\TempFile.cpp" />
<ClCompile Include="..\..\..\src\common\classes\timestamp.cpp" />
<ClCompile Include="..\..\..\src\common\classes\UserBlob.cpp" />
@@ -102,7 +104,6 @@
<ClInclude Include="..\..\..\src\common\classes\Hash.h" />
<ClInclude Include="..\..\..\src\common\classes\ImplementHelper.h" />
<ClInclude Include="..\..\..\src\common\classes\init.h" />
- <ClInclude Include="..\..\..\src\common\classes\Interface.h" />
<ClInclude Include="..\..\..\src\common\classes\Interlock.h" />
<ClInclude Include="..\..\..\src\common\classes\locks.h" />
<ClInclude Include="..\..\..\src\common\classes\MetaName.h" />
@@ -119,6 +120,8 @@
<ClInclude Include="..\..\..\src\common\classes\sparse_bitmap.h" />
<ClInclude Include="..\..\..\src\common\classes\stack.h" />
<ClInclude Include="..\..\..\src\common\classes\Switches.h" />
+ <ClInclude Include="..\..\..\src\common\classes\Synchronize.h" />
+ <ClInclude Include="..\..\..\src\common\classes\SyncObject.h" />
<ClInclude Include="..\..\..\src\common\classes\TempFile.h" />
<ClInclude Include="..\..\..\src\common\classes\timestamp.h" />
<ClInclude Include="..\..\..\src\common\classes\tree.h" />
Modified: firebird/trunk/builds/win32/msvc10/common.vcxproj.filters
===================================================================
--- firebird/trunk/builds/win32/msvc10/common.vcxproj.filters 2011-04-28 03:16:44 UTC (rev 52831)
+++ firebird/trunk/builds/win32/msvc10/common.vcxproj.filters 2011-04-28 14:35:58 UTC (rev 52832)
@@ -186,6 +186,12 @@
<ClCompile Include="..\..\..\src\common\StatementMetadata.cpp">
<Filter>common</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\src\common\classes\Synchronize.cpp">
+ <Filter>common</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\..\src\common\classes\SyncObject.cpp">
+ <Filter>common</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\common\xdr_proto.h">
@@ -365,9 +371,6 @@
<ClInclude Include="..\..\..\src\common\classes\init.h">
<Filter>headers</Filter>
</ClInclude>
- <ClInclude Include="..\..\..\src\common\classes\Interface.h">
- <Filter>headers</Filter>
- </ClInclude>
<ClInclude Include="..\..\..\src\common\classes\Interlock.h">
<Filter>headers</Filter>
</ClInclude>
@@ -482,5 +485,11 @@
<ClInclude Include="..\..\..\src\common\StatementMetadata.h">
<Filter>headers</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\src\common\classes\SyncObject.h">
+ <Filter>headers</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\..\src\common\classes\Synchronize.h">
+ <Filter>headers</Filter>
+ </ClInclude>
</ItemGroup>
</Project>
\ No newline at end of file
Modified: firebird/trunk/builds/win32/msvc8/common.vcproj
===================================================================
--- firebird/trunk/builds/win32/msvc8/common.vcproj 2011-04-28 03:16:44 UTC (rev 52831)
+++ firebird/trunk/builds/win32/msvc8/common.vcproj 2011-04-28 14:35:58 UTC (rev 52832)
@@ -281,7 +281,7 @@
</File>
<File
RelativePath="..\..\..\src\common\config\os\win32\config_root.cpp"
- >
+ >
</File>
<File
RelativePath="..\..\..\src\common\config\ConfigCache.cpp"
@@ -317,7 +317,7 @@
</File>
<File
RelativePath="..\..\..\src\common\dllinst.cpp"
- >
+ >
</File>
<File
RelativePath="..\..\..\src\common\dsc.cpp"
@@ -496,6 +496,14 @@
>
</File>
<File
+ RelativePath="..\..\..\src\common\classes\Synchronize.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\common\classes\SyncObject.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\common\classes\TempFile.cpp"
>
</File>
@@ -689,10 +697,6 @@
>
</File>
<File
- RelativePath="..\..\..\src\common\classes\Interface.h"
- >
- </File>
- <File
RelativePath="..\..\..\src\common\classes\Interlock.h"
>
</File>
@@ -845,6 +849,14 @@
>
</File>
<File
+ RelativePath="..\..\..\src\common\classes\Synchronize.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\common\classes\SyncObject.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\common\classes\TempFile.h"
>
</File>
Modified: firebird/trunk/builds/win32/msvc9/common.vcproj
===================================================================
--- firebird/trunk/builds/win32/msvc9/common.vcproj 2011-04-28 03:16:44 UTC (rev 52831)
+++ firebird/trunk/builds/win32/msvc9/common.vcproj 2011-04-28 14:35:58 UTC (rev 52832)
@@ -496,6 +496,14 @@
>
</File>
<File
+ RelativePath="..\..\..\src\common\classes\Synchronize.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\common\classes\SyncObject.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\common\classes\TempFile.cpp"
>
</File>
@@ -689,10 +697,6 @@
>
</File>
<File
- RelativePath="..\..\..\src\common\classes\Interface.h"
- >
- </File>
- <File
RelativePath="..\..\..\src\common\classes\Interlock.h"
>
</File>
@@ -845,6 +849,14 @@
>
</File>
<File
+ RelativePath="..\..\..\src\common\classes\Synchronize.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\common\classes\SyncObject.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\common\classes\TempFile.h"
>
</File>
Modified: firebird/trunk/src/common/ThreadStart.cpp
===================================================================
--- firebird/trunk/src/common/ThreadStart.cpp 2011-04-28 03:16:44 UTC (rev 52831)
+++ firebird/trunk/src/common/ThreadStart.cpp 2011-04-28 14:35:58 UTC (rev 52832)
@@ -48,6 +48,7 @@
#include "../common/classes/locks.h"
#include "../common/classes/rwlock.h"
+#include "../common/classes/Synchronize.h"
namespace
@@ -57,6 +58,7 @@
THREAD_ENTRY_DECLARE threadStart(THREAD_ENTRY_PARAM arg)
{
fb_assert(arg);
+ Firebird::ThreadSync thread("threadStart");
MemoryPool::setContextPool(getDefaultMemoryPool());
{
ThreadPriorityScheduler* tps = static_cast<ThreadPriorityScheduler*>(arg);
@@ -107,6 +109,7 @@
THREAD_ENTRY_DECLARE threadStart(THREAD_ENTRY_PARAM arg)
{
fb_assert(arg);
+ Firebird::ThreadSync thread("threadStart");
MemoryPool::setContextPool(getDefaultMemoryPool());
ThreadArgs localArgs(*static_cast<ThreadArgs*>(arg));
delete static_cast<ThreadArgs*>(arg);
Added: firebird/trunk/src/common/classes/SyncObject.cpp
===================================================================
--- firebird/trunk/src/common/classes/SyncObject.cpp (rev 0)
+++ firebird/trunk/src/common/classes/SyncObject.cpp 2011-04-28 14:35:58 UTC (rev 52832)
@@ -0,0 +1,490 @@
+/*
+ *
+ * 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
+ * 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.
+ *
+ * The \xD1ode was ported into Firebird Open Source RDBMS project by
+ * Vladyslav Khorsun at 2010
+ *
+ * Contributor(s):
+ */
+
+#include "../../common/common.h"
+#include "../../common/gdsassert.h"
+#include "fb_exception.h"
+
+#include "SyncObject.h"
+#include "Synchronize.h"
+#include "Interlock.h"
+
+namespace Firebird {
+
+
+void SyncObject::lock(Sync *sync, LockType type)
+{
+ ThreadSync *thread = NULL;
+
+ if (type == Shared)
+ {
+ //while (true)
+ while (waiters == 0)
+ {
+ const AtomicCounter::counter_type oldState = lockState;
+ if (oldState < 0)
+ break;
+
+ const AtomicCounter::counter_type newState = oldState + 1;
+ if (lockState.compareExchange(oldState, newState))
+ {
+ WAIT_FOR_FLUSH_CACHE
+ return;
+ }
+ }
+
+ mutex.enter();
+ ++waiters;
+
+ //while (true)
+ while (waitingThreads == NULL)
+ {
+ const AtomicCounter::counter_type oldState = lockState;
+ if (oldState < 0)
+ break;
+
+ const AtomicCounter::counter_type newState = oldState + 1;
+ if (lockState.compareExchange(oldState, newState))
+ {
+ --waiters;
+ mutex.leave();
+ return;
+ }
+ }
+
+ thread = ThreadSync::findThread();
+ fb_assert(thread);
+ }
+ else
+ {
+ thread = ThreadSync::findThread();
+ fb_assert(thread);
+
+ if (thread == exclusiveThread)
+ {
+ ++monitorCount;
+ return;
+ }
+
+ while (waiters == 0)
+ {
+ const AtomicCounter::counter_type oldState = lockState;
+ if (oldState != 0)
+ break;
+
+ if (lockState.compareExchange(oldState, -1))
+ {
+ exclusiveThread = thread;
+ WAIT_FOR_FLUSH_CACHE
+ return;
+ }
+ }
+
+ mutex.enter();
+ ++waiters;
+
+ while (waitingThreads == NULL)
+ {
+ const AtomicCounter::counter_type oldState = lockState;
+ if (oldState != 0)
+ break;
+
+ if (lockState.compareExchange(oldState, -1))
+ {
+ exclusiveThread = thread;
+ --waiters;
+ mutex.leave();
+ return;
+ }
+ }
+ }
+
+ wait(type, thread, sync);
+}
+
+bool SyncObject::lockConditional(LockType type)
+{
+ if (waitingThreads)
+ return false;
+
+ if (type == Shared)
+ {
+ while (true)
+ {
+ const AtomicCounter::counter_type oldState = lockState;
+ if (oldState < 0)
+ break;
+
+ const AtomicCounter::counter_type newState = oldState + 1;
+ if (lockState.compareExchange(oldState, newState))
+ {
+ WAIT_FOR_FLUSH_CACHE
+ return true;
+ }
+ }
+
+ return false;
+ }
+ else
+ {
+ ThreadSync *thread = ThreadSync::findThread();
+ fb_assert(thread);
+
+ if (thread == exclusiveThread)
+ {
+ ++monitorCount;
+ return true;
+ }
+
+ while (waiters == 0)
+ {
+ const AtomicCounter::counter_type oldState = lockState;
+ if (oldState != 0)
+ break;
+
+ if (lockState.compareExchange(oldState, -1))
+ {
+ WAIT_FOR_FLUSH_CACHE
+ exclusiveThread = thread;
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
+
+void SyncObject::unlock(Sync *sync, LockType type)
+{
+ fb_assert((type == Shared && lockState > 0) ||
+ (type == Exclusive && lockState == -1));
+
+ if (monitorCount)
+ {
+ fb_assert(monitorCount > 0);
+ --monitorCount;
+ return;
+ }
+
+ while (true)
+ {
+ const AtomicCounter::counter_type oldState = lockState;
+ const AtomicCounter::counter_type newState = (type == Shared) ? oldState - 1 : 0;
+ exclusiveThread = NULL;
+
+ FLUSH_CACHE
+
+ if (lockState.compareExchange(oldState, newState))
+ {
+ if (waiters) {
+ grantLocks();
+ }
+ return;
+ }
+ }
+}
+
+void SyncObject::unlock()
+{
+ if (lockState > 0) {
+ unlock(NULL, Shared);
+ }
+ else if (lockState == -1) {
+ unlock(NULL, Exclusive);
+ }
+ else {
+ fb_assert(false);
+ }
+}
+
+void SyncObject::downGrade(LockType type)
+{
+ fb_assert(monitorCount == 0);
+ fb_assert(type == Shared);
+ fb_assert(lockState == -1);
+ fb_assert(exclusiveThread);
+ fb_assert(exclusiveThread == ThreadSync::findThread());
+
+ FLUSH_CACHE
+
+ while (true)
+ {
+ if (lockState.compareExchange(-1, 1))
+ {
+ if (waiters) {
+ grantLocks();
+ }
+ return;
+ }
+ }
+}
+
+void SyncObject::wait(LockType type, ThreadSync *thread, Sync *sync)
+{
+/*
+ ThreadSync *volatile *ptr = &waitingThreads;
+
+ for (; *ptr; ptr = &(*ptr)->nextWaiting)
+ {
+ if (*ptr == thread)
+ {
+ LOG_DEBUG ("Apparent single thread deadlock for thread %d (%x)\n", thread->threadId, thread);
+ //for (ThreadSync *thread = que; thread; thread = thread->que)
+ // thread->print();
+ mutex.leave();
+ fatal_exception::raise("single thread deadlock");
+ }
+ }
+*/
+ if (thread->nextWaiting)
+ {
+ mutex.leave();
+ fatal_exception::raise("single thread deadlock");
+ }
+
+ if (waitingThreads)
+ {
+ thread->prevWaiting = waitingThreads->prevWaiting;
+ thread->nextWaiting = waitingThreads;
+
+ waitingThreads->prevWaiting->nextWaiting = thread;
+ waitingThreads->prevWaiting = thread;
+ }
+ else
+ {
+ thread->prevWaiting = thread->nextWaiting = thread;
+ waitingThreads = thread;
+ }
+
+// thread->nextWaiting = NULL;
+ thread->lockType = type;
+// *ptr = thread;
+ thread->lockGranted = false;
+ thread->lockPending = sync;
+ mutex.leave();
+
+ while (!thread->lockGranted)
+ {
+ const bool wakeup = thread->sleep(10000);
+ if (thread->lockGranted)
+ break;
+
+ if (!wakeup)
+ {
+ // stalled(thread);
+ break;
+ }
+ }
+
+ while (!thread->lockGranted)
+ thread->sleep();
+}
+
+
+/**
+void SyncObject::grantLocks(void)
+{
+ mutex.enter();
+ fb_assert((waiters && waitingThreads) || (!waiters && !waitingThreads));
+
+ ThreadSync *volatile *ptr = &waitingThreads;
+ ThreadSync *thread = *ptr;
+ while (thread = *ptr)
+ {
+ bool granted = false;
+
+ if (thread->lockType == Shared)
+ {
+ AtomicCounter::counter_type oldState = lockState;
+ while (oldState >= 0)
+ {
+ const AtomicCounter::counter_type newState = oldState + 1;
+ if (lockState.compareExchange(oldState, newState))
+ {
+ *ptr = thread->nextWaiting;
+ granted = true;
+ --waiters;
+ thread->grantLock(this);
+ break;
+ }
+ oldState = lockState;
+ }
+ }
+ else
+ {
+ while (lockState == 0)
+ {
+ if (lockState.compareExchange(0, -1))
+ {
+ *ptr = thread->nextWaiting;
+ granted = true;
+ exclusiveThread = thread;
+ --waiters;
+ thread->grantLock(this);
+ break;
+ }
+ }
+ }
+
+ if (!granted) {
+ break;
+ ptr = &thread->nextWaiting;
+ }
+ }
+
+ mutex.leave();
+}
+**/
+
+ThreadSync* SyncObject::grantThread(ThreadSync *thread)
+{
+ ThreadSync* next = NULL;
+ if (thread == thread->nextWaiting)
+ {
+ thread->nextWaiting = thread->prevWaiting = NULL;
+ waitingThreads = NULL;
+ }
+ else
+ {
+ next = thread->nextWaiting;
+
+ thread->prevWaiting->nextWaiting = next;
+ next->prevWaiting = thread->prevWaiting;
+
+ thread->nextWaiting = thread->prevWaiting = NULL;
+ if (waitingThreads == thread)
+ waitingThreads = next;
+ }
+
+ --waiters;
+ thread->grantLock(this);
+ return next;
+}
+
+void SyncObject::grantLocks(void)
+{
+ mutex.enter();
+ fb_assert((waiters && waitingThreads) || (!waiters && !waitingThreads));
+
+ ThreadSync *thread = waitingThreads;
+ while (thread)
+ {
+ bool granted = false;
+
+ if (thread->lockType == Shared)
+ {
+ AtomicCounter::counter_type oldState = lockState;
+ while (oldState >= 0)
+ {
+ const AtomicCounter::counter_type newState = oldState + 1;
+ if (lockState.compareExchange(oldState, newState))
+ {
+ granted = true;
+ thread = grantThread(thread);
+ break;
+ }
+ oldState = lockState;
+ }
+ }
+ else
+ {
+ while (lockState == 0)
+ {
+ if (lockState.compareExchange(0, -1))
+ {
+ granted = true;
+ exclusiveThread = thread;
+ thread = grantThread(thread);
+ break;
+ }
+ }
+ }
+
+ if (!granted) {
+ break;
+ //thread = thread->nextWaiting;
+ //if (thread == waitingThreads)
+ // break;
+ }
+ }
+
+ mutex.leave();
+}
+
+
+void SyncObject::validate(LockType lockType)
+{
+ switch (lockType)
+ {
+ case None:
+ fb_assert(lockState == 0);
+ break;
+
+ case Shared:
+ fb_assert(lockState > 0);
+ break;
+
+ case Exclusive:
+ fb_assert(lockState == -1);
+ break;
+ }
+}
+
+
+bool SyncObject::ourExclusiveLock(void) const
+{
+ if (lockState != -1)
+ return false;
+
+// fb_assert(exclusiveThread);
+ return (exclusiveThread == ThreadSync::findThread());
+}
+
+/**
+void SyncObject::sysServiceFailed(const char* service, int code)
+{
+ throw OSRIException (isc_sys_request,
+ isc_arg_string, service,
+ SYS_ARG, code,
+ isc_arg_end);
+}
+
+void SyncObject::assertionFailed(void)
+{
+ throw OSRIException (isc_sys_request,
+ isc_arg_string, "SyncObject assertion failed",
+ SYS_ARG, lockState,
+ isc_arg_end);
+}
+**/
+
+
+} // namespace Firebird
Property changes on: firebird/trunk/src/common/classes/SyncObject.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:eol-style
+ native
Added: firebird/trunk/src/common/classes/SyncObject.h
===================================================================
--- firebird/trunk/src/common/classes/SyncObject.h (rev 0)
+++ firebird/trunk/src/common/classes/SyncObject.h 2011-04-28 14:35:58 UTC (rev 52832)
@@ -0,0 +1,478 @@
+/*
+ *
+ * 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
+ * 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.
+ *
+ * The \xD1ode 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 {
+
+#define LOG_DEBUG
+#define ASSERT fb_assert
+
+enum LockType {
+ None,
+ Exclusive,
+ Shared,
+ Invalid
+};
+
+class Sync;
+class ThreadSync;
+
+class SynchronizationObject
+{
+public:
+ virtual void lock(Sync *sync, LockType type) = 0;
+ virtual void unlock(Sync *sync, LockType type) = 0;
+ virtual void downGrade(LockType type) = 0;
+};
+
+class SyncObject : public SynchronizationObject
+{
+public:
+ SyncObject()
+ {
+ waiters = 0;
+ monitorCount = 0;
+ exclusiveThread = NULL;
+ waitingThreads = NULL;
+ }
+
+ virtual ~SyncObject()
+ {}
+
+ virtual void lock(Sync *sync, LockType type);
+ bool lockConditional(LockType type);
+
+ virtual void unlock(Sync *sync, LockType type);
+ void unlock(void);
+
+ virtual void downGrade(LockType type);
+
+ LockType getState(void) const
+ {
+ if (lockState.value() == 0)
+ return None;
+
+ if (lockState.value() < 0)
+ return Exclusive;
+
+ return Shared;
+ }
+
+ bool isLocked() const
+ {
+ return lockState.value() != 0;
+ }
+
+ bool hasContention() const
+ {
+ return (waiters.value() > 0);
+ }
+
+ bool ourExclusiveLock(void) const;
+
+ void sysServiceFailed(const char* service, int code);
+ void assertionFailed(void);
+
+protected:
+ void wait(LockType type, ThreadSync *thread, Sync *sync);
+ ThreadSync* grantThread(ThreadSync *thread);
+ void grantLocks(void);
+ void validate(LockType lockType);
+
+ AtomicCounter lockState;
+ AtomicCounter waiters;
+ //int waiters;
+ int monitorCount;
+ Mutex mutex;
+ ThreadSync *volatile exclusiveThread;
+ ThreadSync *volatile waitingThreads;
+};
+
+
+class Sync
+{
+public:
+ Sync(SynchronizationObject *obj, const char *fromWhere)
+ {
+ ASSERT(obj);
+ syncObject = obj;
+ prior = NULL;
+ where = fromWhere;
+ state = request = None;
+ }
+
+ ~Sync()
+ {
+ ASSERT(state != Invalid);
+
+ if (syncObject && state != None)
+ {
+ syncObject->unlock(this, state);
+ state = Invalid;
+ }
+ }
+
+ void lock(LockType type)
+ {
+ request = type;
+ syncObject->lock(this, type);
+ state = type;
+ }
+
+ void lock(LockType type, const char *fromWhere)
+ {
+ where = fromWhere;
+ lock(type);
+ }
+
+ void unlock()
+ {
+ ASSERT(state != None);
+ syncObject->unlock(this, state);
+ state = None;
+ }
+
+ void downGrade(LockType type)
+ {
+ ASSERT(state == Exclusive);
+ syncObject->downGrade(type);
+ state = Shared;
+ }
+
+ void setObject(SynchronizationObject *obj)
+ {
+ if (syncObject && state != None)
+ syncObject->unlock(this, state);
+
+ state = None;
+ syncObject = obj;
+ }
+
+
+protected:
+ LockType state;
+ LockType request;
+ SynchronizationObject *syncObject;
+ Sync *prior; // not used
+ const char *where;
+
+friend class ThreadSync;
+};
+
+
+class SyncLockGuard : public Sync
+{
+public:
+ SyncLockGuard(SynchronizationObject *obj, LockType type, const char *fromWhere) :
+ Sync(obj, fromWhere)
+ {
+ lock(type);
+ }
+
+ ~SyncLockGuard()
+ {
+ //ASSERT(state != None);
+ if (state != None)
+ unlock();
+ }
+};
+
+class SyncUnlockGuard : public Sync
+{
+public:
+ SyncUnlockGuard(SynchronizationObject *obj, const char *fromWhere) :
+ Sync(obj, fromWhere)
+ {
+ oldState = state;
+
+ ASSERT(oldState != None);
+ if (oldState != None)
+ unlock();
+ }
+
+ ~SyncUnlockGuard()
+ {
+ if (oldState != None)
+ lock(oldState);
+ }
+
+private:
+ LockType oldState;
+};
+
+} // namespace Firebird
+
+#endif // CLASSES_SYNCOBJECT_H
+
+/*
+ *
+ * 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
+ * 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.
+ *
+ * The \xD1ode 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 {
+
+#define LOG_DEBUG
+#define ASSERT fb_assert
+
+enum LockType {
+ None,
+ Exclusive,
+ Shared,
+ Invalid
+};
+
+class Sync;
+class ThreadSync;
+
+class SynchronizationObject
+{
+public:
+ virtual void lock(Sync *sync, LockType type) = 0;
+ virtual void unlock(Sync *sync, LockType type) = 0;
+ virtual void downGrade(LockType type) = 0;
+};
+
+class SyncObject : public SynchronizationObject
+{
+public:
+ SyncObject()
+ {
+ waiters = 0;
+ monitorCount = 0;
+ exclusiveThread = NULL;
+ waitingThreads = NULL;
+ }
+
+ virtual ~SyncObject()
+ {}
+
+ virtual void lock(Sync *sync, LockType type);
+ bool lockConditional(LockType type);
+
+ virtual void unlock(Sync *sync, LockType type);
+ void unlock(void);
+
+ virtual void downGrade(LockType type);
+
+ LockType getState(void) const
+ {
+ if (lockState.value() == 0)
+ return None;
+
+ if (lockState.value() < 0)
+ return Exclusive;
+
+ return Shared;
+ }
+
+ bool isLocked() const
+ {
+ return lockState.value() != 0;
+ }
+
+ bool hasContention() const
+ {
+ return (waiters.value() > 0);
+ }
+
+ bool ourExclusiveLock(void) const;
+
+ void sysServiceFailed(const char* service, int code);
+ void assertionFailed(void);
+
+protected:
+ void wait(LockType type, ThreadSync *thread, Sync *sync);
+ ThreadSync* grantThread(ThreadSync *thread);
+ void grantLocks(void);
+ void validate(LockType lockType);
+
+ AtomicCounter lockState;
+ AtomicCounter waiters;
+ //int waiters;
+ int monitorCount;
+ Mutex mutex;
+ ThreadSync *volatile exclusiveThread;
+ ThreadSync *volatile waitingThreads;
+};
+
+
+class Sync
+{
+public:
+ Sync(SynchronizationObject *obj, const char *fromWhere)
+ {
+ ASSERT(obj);
+ syncObject = obj;
+ prior = NULL;
+ where = fromWhere;
+ state = request = None;
+ }
+
+ ~Sync()
+ {
+ ASSERT(state != Invalid);
+
+ if (syncObject && state != None)
+ {
+ syncObject->unlock(this, state);
+ state = Invalid;
+ }
+ }
+
+ void lock(LockType type)
+ {
+ request = type;
+ syncObject->lock(this, type);
+ state = type;
+ }
+
+ void lock(LockType type, const char *fromWhere)
+ {
+ where = fromWhere;
+ lock(type);
+ }
+
+ void unlock()
+ {
+ ASSERT(state != None);
+ syncObject->unlock(this, state);
+ state = None;
+ }
+
+ void downGrade(LockType type)
+ {
+ ASSERT(state == Exclusive);
+ syncObject->downGrade(type);
+ state = Shared;
+ }
+
+ void setObject(SynchronizationObject *obj)
+ {
+ if (syncObject && state != None)
+ syncObject->unlock(this, state);
+
+ state = None;
+ syncObject = obj;
+ }
+
+
+protected:
+ LockType state;
+ LockType request;
+ SynchronizationObject *syncObject;
+ Sync *prior; // not used
+ const char *where;
+
+friend class ThreadSync;
+};
+
+
+class SyncLockGuard : public Sync
+{
+public:
+ SyncLockGuard(SynchronizationObject *obj, LockType type, const char *fromWhere) :
+ Sync(obj, fromWhere)
+ {
+ lock(type);
+ }
+
+ ~SyncLockGuard()
+ {
+ //ASSERT(state != None);
+ if (state != None)
+ unlock();
+ }
+};
+
+class SyncUnlockGuard : public Sync
+{
+public:
+ SyncUnlockGuard(SynchronizationObject *obj, const char *fromWhere) :
+ Sync(obj, fromWhere)
+ {
+ oldState = state;
+
+ ASSERT(oldState != None);
+ if (oldState != None)
+ unlock();
+ }
+
+ ~SyncUnlockGuard()
+ {
+ if (oldState != None)
+ lock(oldState);
+ }
+
+private:
+ LockType oldState;
+};
+
+} // namespace Firebird
+
+#endif // CLASSES_SYNCOBJECT_H
+
Property changes on: firebird/trunk/src/common/classes/SyncObject.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:eol-style
+ native
Added: firebird/trunk/src/common/classes/Synchronize.cpp
===================================================================
--- firebird/trunk/src/common/classes/Synchronize.cpp (rev 0)
+++ firebird/trunk/src/common/classes/Synchronize.cpp 2011-04-28 14:35:58 UTC (rev 52832)
@@ -0,0 +1,327 @@
+/*
+*
+* 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
+* 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.
+*
+* The \xD1ode was ported into Firebird Open Source RDBMS project by
+* Vladyslav Khorsun at 2010
+*
+* Contributor(s):
+*/
+
+#include "../../common/common.h"
+#include "fb_tls.h"
+#include "../thd.h"
+
+#include "SyncObject.h"
+#include "Synchronize.h"
+
+#define NANO 1000000000
+#define MICRO 1000000
+
+namespace Firebird {
+
+Synchronize::Synchronize()
+{
+ shutdownInProgress = false;
+ sleeping = false;
+ wakeup = false;
+
+#ifdef _WIN32
+ evnt = CreateEvent(NULL, false, false, NULL);
+#endif
+
+#ifdef _PTHREADS
+ int ret = pthread_mutex_init(&mutex, NULL);
+ pthread_cond_init(&condition, NULL);
+#endif
+
+#ifdef SOLARIS_MT
+ int ret = mutex_init(&mutex, USYNC_THREAD, NULL);
+ cond_init(&condition, USYNC_THREAD, NULL);
+#endif
+}
+
+Synchronize::~Synchronize()
+{
+#ifdef _WIN32
+ CloseHandle(evnt);
+#endif
+
+#ifdef _PTHREADS
+ int ret = pthread_mutex_destroy(&mutex);
+ ret = pthread_cond_destroy(&condition);
+#endif
+
+#ifdef SOLARIS_MT
+ int ret = mutex_destroy(&mutex);
+#endif
+}
+
+
+void Synchronize::sleep()
+{
+ sleeping = true;
+#ifdef _WIN32
+#ifdef _DEBUG
+ for (;;)
+ {
+ const int n = WaitForSingleObject(evnt, 10000);
+ if (n != WAIT_TIMEOUT)
+ break;
+ }
+#else
+ sleep (INFINITE);
+#endif
+#endif
+
+#ifdef _PTHREADS
+ int ret = pthread_mutex_lock(&mutex);
+ CHECK_RET("pthread_mutex_lock failed, errno %d", errno);
+
+ while (!wakeup)
+ pthread_cond_wait(&condition, &mutex);
+
+ wakeup = false;
+ ret = pthread_mutex_unlock(&mutex);
+ CHECK_RET("pthread_mutex_unlock failed, errno %d", errno);
+#endif
+
+#ifdef SOLARIS_MT
+ int ret = mutex_lock(&mutex);
+ CHECK_RET("mutex_lock failed, errno %d", errno);
+
+ while (!wakeup)
+ cond_wait(&condition, &mutex);
+
+ wakeup = false;
+ ret = mutex_unlock(&mutex);
+ CHECK_RET("mutex_unlock failed, errno %d", errno);
+#endif
+
+ sleeping = false;
+}
+
+bool Synchronize::sleep(int milliseconds)
+{
+ sleeping = true;
+
+#ifdef _WIN32
+ const int n = WaitForSingleObject(evnt, milliseconds);
+ sleeping = false;
+
+ return n != WAIT_TIMEOUT;
+#endif
+
+#ifdef _PTHREADS
+ struct timeval microTime;
+ int ret = gettimeofday(µTime, NULL);
+ SINT64 nanos = (SINT64) microTime.tv_sec * NANO + microTime.tv_usec * 1000 +
+ (SINT64) milliseconds * 1000000;
+ struct timespec nanoTime;
+ nanoTime.tv_sec = nanos / NANO;
+ nanoTime.tv_nsec = nanos % NANO;
+ ret = pthread_mutex_lock (&mutex);
+ CHECK_RET("pthread_mutex_lock failed, errno %d", errno);
+ int seconds = nanoTime.tv_sec - microTime.tv_sec;
+
+ while (!wakeup)
+ {
+#ifdef MVS
+ ret = pthread_cond_timedwait(&condition, &mutex, &nanoTime);
+ if (ret == -1 && errno == EAGAIN)
+ ret = ETIMEDOUT;
+ break;
+#else
+ ret = pthread_cond_timedwait(&condition, &mutex, &nanoTime);
+ if (ret == ETIMEDOUT)
+ break;
+#endif
+ /***
+ if (!wakeup)
+ Log::debug ("Synchronize::sleep(milliseconds): unexpected wakeup, ret %d\n", ret);
+ ***/
+ }
+
+ sleeping = false;
+ wakeup = false;
+ pthread_mutex_unlock(&mutex);
+ return ret != ETIMEDOUT;
+#endif
+
+#ifdef SOLARIS_MT
+ struct timeval microTime;
+ int ret = gettimeofday(µTime, NULL);
+ SINT64 nanos = (SINT64) microTime.tv_sec * NANO + microTime.tv_usec * 1000 +
+ (SINT64) milliseconds * 1000000;
+ struct timespec nanoTime;
+ nanoTime.tv_sec = nanos / NANO;
+ nanoTime.tv_nsec = nanos % NANO;
+ ret = mutex_lock (&mutex);
+ CHECK_RET("mutex_lock failed, errno %d", errno);
+ int seconds = nanoTime.tv_sec - microTime.tv_sec;
+
+ while (!wakeup)
+ {
+ ret = cond_timedwait(&condition, &mutex, &nanoTime);
+ if (ret == ETIMEDOUT)
+ break;
+ /***
+ if (!wakeup)
+ Log::debug ("Synchronize::sleep(milliseconds): unexpected wakeup, ret %d\n", ret);
+ ***/
+ }
+
+ sleeping = false;
+ wakeup = false;
+ mutex_unlock(&mutex);
+
+ return ret != ETIMEDOUT;
+#endif
+}
+
+void Synchronize::wake()
+{
+#ifdef _WIN32
+ SetEvent (evnt);
+#endif
+
+#ifdef _PTHREADS
+ int ret = pthread_mutex_lock(&mutex);
+ CHECK_RET("pthread_mutex_lock failed, errno %d", errno);
+ wakeup = true;
+ pthread_cond_broadcast(&condition);
+ ret = pthread_mutex_unlock(&mutex);
+ CHECK_RET("pthread_mutex_unlock failed, errno %d", errno);
+#endif
+
+#ifdef SOLARIS_MT
+ int ret = mutex_lock(&mutex);
+ CHECK_RET("mutex_lock failed, errno %d", errno);
+ wakeup = true;
+ cond_broadcast(&condition);
+ ret = mutex_unlock(&mutex);
+ CHECK_RET("mutex_unlock failed, errno %d", errno);
+#endif
+}
+
+void Synchronize::shutdown()
+{
+ shutdownInProgress = true;
+ wake();
+}
+
+
+
+/// ThreadSync
+
+TLS_DECLARE (ThreadSync*, threadIndex);
+
+ThreadSync::ThreadSync(const char *desc)
+{
+ init(desc);
+ setThread(this);
+}
+
+void ThreadSync::init(const char *desc)
+{
+ description = desc;
+ threadId = getCurrentThreadId();
+ prevWaiting = nextWaiting = NULL;
+ lockType = None;
+ lockGranted = false;
+ lockPending = NULL;
+ locks = NULL;
+}
+
+ThreadSync::~ThreadSync()
+{
+ setThread (NULL);
+}
+
+
+ThreadSync* ThreadSync::findThread()
+{
+ return TLS_GET(threadIndex);
+}
+
+
+ThreadSync* ThreadSync::getThread(const char *desc)
+{
+ ThreadSync *thread = findThread();
+
+ if (!thread)
+ {
+ thread = new ThreadSync (desc);
+ setThread(thread);
+ }
+
+ return thread;
+}
+
+void ThreadSync::setThread(ThreadSync *thread)
+{
+ TLS_SET(threadIndex, thread);
+}
+
+FB_THREAD_ID ThreadSync::getCurrentThreadId(void)
+{
+ return getThreadId();
+}
+
+
+const char* ThreadSync::getWhere()
+{
+ if (lockPending && lockPending->where)
+ return lockPending->where;
+
+ return "";
+}
+
+
+void ThreadSync::validateLocks()
+{
+ ThreadSync *thread = getThread("ThreadSync::validateLocks");
+
+ // hvlad: not worked
+ if (thread->locks)
+ {
+ LOG_DEBUG ("thread %d has active locks:\n", thread->threadId);
+ for (Sync *sync = thread->locks; sync; sync = sync->prior)
+ LOG_DEBUG (" %s\n", sync->where);
+ }
+}
+
+
+void ThreadSync::grantLock(SyncObject *lock)
+{
+ ASSERT(!lockGranted);
+ ASSERT(!lockPending || lockPending->syncObject == lock);
+
+ lockGranted = true;
+ lockPending = NULL;
+
+ wake();
+}
+
+} // namespace Firebird
Property changes on: firebird/trunk/src/common/classes/Synchronize.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:eol-style
+ native
Added: firebird/trunk/src/common/classes/Synchronize.h
===================================================================
--- firebird/trunk/src/common/classes/Synchronize.h (rev 0)
+++ firebird/trunk/src/common/classes/Synchronize.h 2011-04-28 14:35:58 UTC (rev 52832)
@@ -0,0 +1,111 @@
+/*
+ *
+ * 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
+ * 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.
+ *
+ * The \xD1ode was ported into Firebird Open Source RDBMS project by
+ * Vladyslav Khorsun at 2010
+ *
+ * Contributor(s):
+ */
+
+#ifndef CLASSES_SYNCHRONIZE_H
+#define CLASSES_SYNCHRONIZE_H
+
+#include "../../common/common.h"
+#include "../../common/classes/SyncObject.h"
+
+
+namespace Firebird {
+
+class Synchronize
+{
+public:
+ Synchronize();
+ virtual ~Synchronize();
+
+ virtual void shutdown();
+ void wake();
+ bool sleep(int milliseconds);
+ void sleep();
+
+protected:
+ bool shutdownInProgress;
+ bool sleeping;
+ volatile bool wakeup;
+ SINT64 waitTime;
+
+#ifdef _WIN32
+ void *evnt;
+#endif
+
+#ifdef _PTHREADS
+ pthread_cond_t condition;
+ pthread_mutex_t mutex;
+#endif
+
+#ifdef SOLARIS_MT
+ cond_t condition;
+ mutex_t mutex;
+#endif
+};
+
+
+class Sync;
+class SyncObject;
+
+class ThreadSync : public Synchronize
+{
+public:
+ ThreadSync(const char *desc);
+ virtual ~ThreadSync();
+
+ void init(const char *description);
+
+ static ThreadSync* findThread();
+ static ThreadSync* getThread(const char *desc);
+ static FB_THREAD_ID getCurrentThreadId(void);
+
+ const char* getWhere();
+
+ static void validateLocks();
+ void grantLock(SyncObject *lock);
+
+ FB_THREAD_ID threadId;
+ ThreadSync *nextWaiting; // next thread in sleep que (see SyncObject)
+ ThreadSync *prevWaiting; // previous thread in sleep que (see SyncObject)
+ LockType lockType; // requested lock type (see SyncObject)
+ volatile bool lockGranted;
+ Sync *lockPending;
+ Sync *locks;
+ const char *description;
+
+protected:
+ static void setThread (ThreadSync *thread);
+};
+
+
+} // namespace Firebird
+
+#endif // CLASSES_SYNCHRONIZE_H
+
Property changes on: firebird/trunk/src/common/classes/Synchronize.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:eol-style
+ native
Modified: firebird/trunk/src/common/classes/alloc.h
===================================================================
--- firebird/trunk/src/common/classes/alloc.h 2011-04-28 03:16:44 UTC (rev 52831)
+++ firebird/trunk/src/common/classes/alloc.h 2011-04-28 14:35:58 UTC (rev 52832)
@@ -130,7 +130,7 @@
{
for (MemoryStats* statistics = this; statistics; statistics = statistics->mst_parent)
{
- const size_t temp = statistics->mst_usage += size;
+ const size_t temp = statistics->mst_usage.exchangeAdd(size) + size;
if (temp > statistics->mst_max_usage)
statistics->mst_max_usage = temp;
}
@@ -148,7 +148,7 @@
{
for (MemoryStats* statistics = this; statistics; statistics = statistics->mst_parent)
{
- const size_t temp = statistics->mst_mapped += size;
+ const size_t temp = statistics->mst_mapped.exchangeAdd(size) + size;
if (temp > statistics->mst_max_mapped)
statistics->mst_max_mapped = temp;
}
Modified: firebird/trunk/src/common/classes/fb_atomic.h
===================================================================
--- firebird/trunk/src/common/classes/fb_atomic.h 2011-04-28 03:16:44 UTC (rev 52831)
+++ firebird/trunk/src/common/classes/fb_atomic.h 2011-04-28 14:35:58 UTC (rev 52832)
@@ -35,9 +35,23 @@
typedef SLONG AtomicType;
#endif
+// IMPORTANT !
+// Most of the interlocked functions returns "old" value of operand (except of
+// InterlockedIncrement and InterlockedDecrement on Windows) and this is correct
+// as "old" value impossible to restore from "new" value and operation parameters
+// and "new" value could be changed at time when code looks at it.
+// This (returning of original value) is not how operators such as "=", "+=",
+// "&=" etc, usually works. Therefore overloaded operators in AtomicCounter class
+// are void and all of them have corresponding equivalent functions returning
+// "old" value of operand.
+// The only exceptions from this rule is unary increment and decrement (for
+// historical reasons). Use it with care ! If one need old value of just
+// incremented atomic variable he should use exchangeAdd, not operator++.
+
#if defined(WIN_NT)
#include <windows.h>
+#include <intrin.h>
namespace Firebird {
@@ -55,60 +69,165 @@
explicit AtomicCounter(counter_type val = 0) : counter(val) {}
~AtomicCounter() {}
+ // returns old value
counter_type exchangeAdd(counter_type val)
{
#ifdef _WIN64
- return InterlockedExchangeAdd64(&counter, val);
+ return _InterlockedExchangeAdd64(&counter, val);
#else
- return InterlockedExchangeAdd(&counter, val);
+ return _InterlockedExchangeAdd(&counter, val);
#endif
}
- counter_type operator +=(counter_type val)
+ bool compareExchange(counter_type oldVal, counter_type newVal)
{
- return exchangeAdd(val) + val;
+#ifdef _WIN64
+ return (_InterlockedCompareExchange64(&counter, newVal, oldVal) == oldVal);
+#else
+ return (_InterlockedCompareExchange(&counter, newVal, oldVal) == oldVal);
+#endif
}
- counter_type operator -=(counter_type val)
+ void setValue(counter_type val)
{
- return exchangeAdd(-val) - val;
+#ifdef _WIN64
+ _InterlockedExchange64(&counter, val);
+#else
+ _InterlockedExchange(&counter, val);
+#endif
}
+// platform-independent code
+
+ counter_type value() const { return counter; }
+
+ // returns old value
+ counter_type exchangeBitAnd(counter_type val)
+ {
+ while (true)
+ {
+ volatile counter_type oldVal = counter;
+
+ if (compareExchange(oldVal, oldVal & val))
+ return oldVal;
+ }
+ }
+
+ // returns old value
+ counter_type exchangeBitOr(counter_type val)
+ {
+ while (true)
+ {
+ volatile counter_type oldVal = counter;
+
+ if (compareExchange(oldVal, oldVal | val))
+ return oldVal;
+ }
+ }
+
+
+ // returns old value
+ counter_type exchangeGreater(counter_type val)
+ {
+ while (true)
+ {
+ volatile counter_type oldVal = counter;
+
+ if (oldVal >= val)
+ return oldVal;
+
+ if (compareExchange(oldVal, val))
+ return oldVal;
+ }
+ }
+
+ operator counter_type () const
+ {
+ return value();
+ }
+
+ void operator =(counter_type val)
+ {
+ setValue(val);
+ }
+
+ // returns new value !
counter_type operator ++()
{
-#ifdef _WIN64
- return InterlockedIncrement64(&counter);
-#else
- return InterlockedIncrement(&counter);
-#endif
+ return exchangeAdd(1) + 1;
}
+ // returns new value !
counter_type operator --()
{
+ return exchangeAdd(-1) - 1;
+ }
+
+ void operator +=(counter_type val)
+ {
+ exchangeAdd(val);
+ }
+
+ void operator -=(counter_type val)
+ {
+ exchangeAdd(-val);
+ }
+
+ void operator &=(counter_type val)
+ {
+ exchangeBitAnd(val);
+ }
+
+ void operator |=(counter_type val)
+ {
+ exchangeBitOr(val);
+ }
+
+private:
+#if defined(MINGW)
+ counter_type counter;
+#else
+ volatile counter_type counter;
+#endif
+};
+
+
+
+template <typename T>
+class AtomicPointer
+{
+public:
+ explicit AtomicPointer(T* val = NULL) : pointer(val) {}
+ ~AtomicPointer() {}
+
+ T* value() const { return (T*)pointer; }
+
+ void setValue(T* val)
+ {
#ifdef _WIN64
- return InterlockedDecrement64(&counter);
+ _InterlockedExchangePointer((volatile PVOID*)&pointer, val);
#else
- return InterlockedDecrement(&counter);
+ //InterlockedExchangePointer((volatile PVOID*)&pointer, val);
+ _InterlockedExchange((LONG volatile*)&pointer, (LONG)val);
#endif
}
- counter_type value() const { return counter; }
-
- counter_type setValue(counter_type val)
+ bool compareExchange(T* oldVal, T* newVal)
{
#ifdef _WIN64
- return InterlockedExchange64(&counter, val);
+ return (_InterlockedCompareExchangePointer((PVOID volatile*)&pointer, newVal, oldVal) == oldVal);
#else
- return InterlockedExchange(&counter, val);
+ //return (InterlockedCompareExchangePointer((PVOID volatile*)&pointer, newVal, oldVal) == oldVal);
+ return ((PVOID)(LONG_PTR)_InterlockedCompareExchange((LONG volatile*)&pointer, (LONG)newVal, (LONG)oldVal)) == oldVal;
#endif
}
+ operator T* () const { return value(); }
+ T* operator ->() const { return value(); }
+ void operator =(T* val) { setValue(val); }
+
private:
-# if defined(MINGW)
- counter_type counter;
-# else
- volatile counter_type counter;
-# endif
+ volatile T* pointer;
};
} // namespace Firebird
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|