aboutsummaryrefslogtreecommitdiff
path: root/dep/src/zthread
diff options
context:
space:
mode:
authorNeo2003 <none@none>2008-10-02 16:23:55 -0500
committerNeo2003 <none@none>2008-10-02 16:23:55 -0500
commit9b1c0e006f20091f28f3f468cfcab1feb51286bd (patch)
treeb5d1ba94a656e6679f8737f9ea6bed1239b73b14 /dep/src/zthread
[svn] * Proper SVN structureinit
--HG-- branch : trunk
Diffstat (limited to 'dep/src/zthread')
-rw-r--r--dep/src/zthread/AtomicCount.cxx57
-rw-r--r--dep/src/zthread/ConcurrentExecutor.cxx54
-rw-r--r--dep/src/zthread/Condition.cxx80
-rw-r--r--dep/src/zthread/ConditionImpl.h377
-rw-r--r--dep/src/zthread/CountingSemaphore.cxx92
-rw-r--r--dep/src/zthread/Debug.h32
-rw-r--r--dep/src/zthread/DeferredInterruptionScope.h63
-rw-r--r--dep/src/zthread/FastLock.h71
-rw-r--r--dep/src/zthread/FastMutex.cxx53
-rw-r--r--dep/src/zthread/FastRecursiveLock.h74
-rw-r--r--dep/src/zthread/FastRecursiveMutex.cxx53
-rw-r--r--dep/src/zthread/IntrusivePtr.h99
-rw-r--r--dep/src/zthread/Makefile.am132
-rw-r--r--dep/src/zthread/Monitor.cxx39
-rw-r--r--dep/src/zthread/Monitor.h60
-rw-r--r--dep/src/zthread/Mutex.cxx68
-rw-r--r--dep/src/zthread/MutexImpl.h377
-rw-r--r--dep/src/zthread/PoolExecutor.cxx629
-rw-r--r--dep/src/zthread/PriorityCondition.cxx80
-rw-r--r--dep/src/zthread/PriorityInheritanceMutex.cxx109
-rw-r--r--dep/src/zthread/PriorityMutex.cxx69
-rw-r--r--dep/src/zthread/PrioritySemaphore.cxx104
-rw-r--r--dep/src/zthread/RecursiveMutex.cxx61
-rw-r--r--dep/src/zthread/RecursiveMutexImpl.cxx286
-rw-r--r--dep/src/zthread/RecursiveMutexImpl.h78
-rw-r--r--dep/src/zthread/Scheduling.h96
-rw-r--r--dep/src/zthread/Semaphore.cxx101
-rw-r--r--dep/src/zthread/SemaphoreImpl.h348
-rw-r--r--dep/src/zthread/State.h151
-rw-r--r--dep/src/zthread/Status.h179
-rw-r--r--dep/src/zthread/SynchronousExecutor.cxx90
-rw-r--r--dep/src/zthread/TSS.h52
-rw-r--r--dep/src/zthread/Thread.cxx127
-rw-r--r--dep/src/zthread/ThreadImpl.cxx470
-rw-r--r--dep/src/zthread/ThreadImpl.h122
-rw-r--r--dep/src/zthread/ThreadLocalImpl.cxx66
-rw-r--r--dep/src/zthread/ThreadOps.cxx54
-rw-r--r--dep/src/zthread/ThreadOps.h67
-rw-r--r--dep/src/zthread/ThreadQueue.cxx266
-rw-r--r--dep/src/zthread/ThreadQueue.h134
-rw-r--r--dep/src/zthread/ThreadedExecutor.cxx464
-rw-r--r--dep/src/zthread/Time.cxx45
-rw-r--r--dep/src/zthread/TimeStrategy.h86
-rw-r--r--dep/src/zthread/config.h95
-rw-r--r--dep/src/zthread/linux/AtomicCount.cxx73
-rw-r--r--dep/src/zthread/linux/AtomicFastLock.h117
-rw-r--r--dep/src/zthread/linux/FastRecursiveLock.h83
-rw-r--r--dep/src/zthread/macos/FastLock.h139
-rw-r--r--dep/src/zthread/macos/Monitor.cxx280
-rw-r--r--dep/src/zthread/macos/Monitor.h156
-rw-r--r--dep/src/zthread/macos/TSS.h120
-rw-r--r--dep/src/zthread/macos/ThreadOps.cxx103
-rw-r--r--dep/src/zthread/macos/ThreadOps.h167
-rw-r--r--dep/src/zthread/macos/UpTimeStrategy.h86
-rw-r--r--dep/src/zthread/posix/ConditionRecursiveLock.h146
-rw-r--r--dep/src/zthread/posix/FastLock.h121
-rw-r--r--dep/src/zthread/posix/FtimeStrategy.h84
-rw-r--r--dep/src/zthread/posix/GetTimeOfDayStrategy.h75
-rw-r--r--dep/src/zthread/posix/Monitor.cxx257
-rw-r--r--dep/src/zthread/posix/Monitor.h153
-rw-r--r--dep/src/zthread/posix/PriorityOps.h51
-rw-r--r--dep/src/zthread/posix/TSS.h104
-rw-r--r--dep/src/zthread/posix/ThreadOps.cxx147
-rw-r--r--dep/src/zthread/posix/ThreadOps.h154
-rw-r--r--dep/src/zthread/solaris/FastRecursiveLock.h122
-rw-r--r--dep/src/zthread/vanilla/DualMutexRecursiveLock.h173
-rw-r--r--dep/src/zthread/vanilla/SimpleAtomicCount.cxx100
-rw-r--r--dep/src/zthread/vanilla/SimpleRecursiveLock.h130
-rw-r--r--dep/src/zthread/win32/AtomicCount.cxx60
-rw-r--r--dep/src/zthread/win32/AtomicFastLock.h122
-rw-r--r--dep/src/zthread/win32/AtomicFastRecursiveLock.h158
-rw-r--r--dep/src/zthread/win32/FastLock.h146
-rw-r--r--dep/src/zthread/win32/FastRecursiveLock.h109
-rw-r--r--dep/src/zthread/win32/Monitor.cxx242
-rw-r--r--dep/src/zthread/win32/Monitor.h153
-rw-r--r--dep/src/zthread/win32/PerformanceCounterStrategy.h108
-rw-r--r--dep/src/zthread/win32/TSS.h108
-rw-r--r--dep/src/zthread/win32/ThreadOps.cxx197
-rw-r--r--dep/src/zthread/win32/ThreadOps.h152
-rw-r--r--dep/src/zthread/win9x/AtomicCount.cxx115
-rw-r--r--dep/src/zthread/win9x/AtomicFastLock.h130
81 files changed, 11151 insertions, 0 deletions
diff --git a/dep/src/zthread/AtomicCount.cxx b/dep/src/zthread/AtomicCount.cxx
new file mode 100644
index 00000000000..ac0d0773b12
--- /dev/null
+++ b/dep/src/zthread/AtomicCount.cxx
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTATOMICCOUNTSELECT_H__
+#define __ZTATOMICCOUNTSELECT_H__
+
+#include "zthread/AtomicCount.h"
+#include "zthread/Config.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+// Select the correct AtomicCount implementation based on
+// what the compilation environment has defined
+
+#ifndef ZT_VANILLA
+
+#if defined(HAVE_ATOMIC_LINUX)
+# include "linux/AtomicCount.cxx"
+#elif defined(ZT_WIN32)
+# include "win32/AtomicCount.cxx"
+#elif defined(ZT_WIN9X)
+# include "win9x/AtomicCount.cxx"
+#endif
+
+#endif
+
+// Default to an AtomicCount that just uses a FastLock
+#ifndef __ZTATOMICCOUNTIMPL_H__
+# include "vanilla/SimpleAtomicCount.cxx"
+#endif
+*/
+
+# include "vanilla/SimpleAtomicCount.cxx"
+
+#endif // __ZTATOMICCOUNTSELECT_H__
diff --git a/dep/src/zthread/ConcurrentExecutor.cxx b/dep/src/zthread/ConcurrentExecutor.cxx
new file mode 100644
index 00000000000..a65e9c5e909
--- /dev/null
+++ b/dep/src/zthread/ConcurrentExecutor.cxx
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "zthread/ConcurrentExecutor.h"
+
+namespace ZThread {
+
+ ConcurrentExecutor::ConcurrentExecutor()
+ : _executor(1) {}
+
+ void ConcurrentExecutor::interrupt() {
+ _executor.interrupt();
+ }
+
+ void ConcurrentExecutor::execute(const Task& task) {
+ _executor.execute(task);
+ }
+
+ void ConcurrentExecutor::cancel() {
+ _executor.cancel();
+ }
+
+ bool ConcurrentExecutor::isCanceled() {
+ return _executor.isCanceled();
+ }
+
+ void ConcurrentExecutor::wait() {
+ _executor.wait();
+ }
+
+ bool ConcurrentExecutor::wait(unsigned long timeout) {
+ return _executor.wait(timeout);
+ }
+
+}
diff --git a/dep/src/zthread/Condition.cxx b/dep/src/zthread/Condition.cxx
new file mode 100644
index 00000000000..39485fb5ca4
--- /dev/null
+++ b/dep/src/zthread/Condition.cxx
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "zthread/Condition.h"
+#include "ConditionImpl.h"
+
+namespace ZThread {
+
+ class FifoConditionImpl : public ConditionImpl<fifo_list> {
+ public:
+ FifoConditionImpl(Lockable& l) : ConditionImpl<fifo_list>(l) {}
+
+ };
+
+ Condition::Condition(Lockable& lock) {
+
+ _impl = new FifoConditionImpl(lock);
+
+ }
+
+
+ Condition::~Condition() {
+
+ if(_impl != 0)
+ delete _impl;
+
+ }
+
+
+
+ void Condition::wait() {
+
+ _impl->wait();
+
+ }
+
+
+
+ bool Condition::wait(unsigned long ms) {
+
+ return _impl->wait(ms);
+
+ }
+
+
+
+ void Condition::signal() {
+
+ _impl->signal();
+
+ }
+
+
+ void Condition::broadcast() {
+
+ _impl->broadcast();
+
+ }
+
+} // namespace ZThread
+
diff --git a/dep/src/zthread/ConditionImpl.h b/dep/src/zthread/ConditionImpl.h
new file mode 100644
index 00000000000..eeeaba10bbc
--- /dev/null
+++ b/dep/src/zthread/ConditionImpl.h
@@ -0,0 +1,377 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTCONDITIONIMPL_H__
+#define __ZTCONDITIONIMPL_H__
+
+#include "zthread/Guard.h"
+
+#include "Debug.h"
+#include "Scheduling.h"
+#include "DeferredInterruptionScope.h"
+
+namespace ZThread {
+
+/**
+ * @class ConditionImpl
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-18T08:15:37-0400>
+ * @version 2.2.11
+ *
+ * The ConditionImpl template allows how waiter lists are sorted
+ * to be parameteized
+ */
+template <typename List>
+class ConditionImpl {
+
+ //! Waiters currently blocked
+ List _waiters;
+
+ //! Serialize access to this object
+ FastLock _lock;
+
+ //! External lock
+ Lockable& _predicateLock;
+
+ public:
+
+ /**
+ * Create a new ConditionImpl.
+ *
+ * @exception Initialization_Exception thrown if resources could not be
+ * allocated
+ */
+ ConditionImpl(Lockable& predicateLock) : _predicateLock(predicateLock) {
+
+ }
+
+ /**
+ * Destroy this ConditionImpl, release its resources
+ */
+ ~ConditionImpl();
+
+ void signal();
+
+ void broadcast();
+
+ void wait();
+
+ bool wait(unsigned long timeout);
+
+};
+
+
+template <typename List>
+ConditionImpl<List>::~ConditionImpl() {
+
+#ifndef NDEBUG
+
+ // It is an error to destroy a condition with threads waiting on it.
+ if(!_waiters.empty()) {
+
+ ZTDEBUG("** You are destroying a condition variable which still has waiting threads. **\n");
+ assert(0);
+
+ }
+
+#endif
+
+ }
+
+
+/**
+ * Signal the condition variable, waking one thread if any.
+ */
+template <typename List>
+void ConditionImpl<List>::signal() {
+
+ Guard<FastLock> g1(_lock);
+
+ // Try to find a waiter with a backoff & retry scheme
+ for(;;) {
+
+ // Go through the list, attempt to notify() a waiter.
+ for(typename List::iterator i = _waiters.begin(); i != _waiters.end();) {
+
+ // Try the monitor lock, if it cant be locked skip to the next waiter
+ ThreadImpl* impl = *i;
+ Monitor& m = impl->getMonitor();
+
+ if(m.tryAcquire()) {
+
+ // Notify the monitor & remove from the waiter list so time isn't
+ // wasted checking it again.
+ i = _waiters.erase(i);
+
+ // If notify() is not sucessful, it is because the wait() has already
+ // been ended (killed/interrupted/notify'd)
+ bool woke = m.notify();
+
+ m.release();
+
+ // Once notify() succeeds, return
+ if(woke)
+ return;
+
+ } else ++i;
+
+ }
+
+ if(_waiters.empty())
+ return;
+
+ { // Backoff and try again
+
+ Guard<FastLock, UnlockedScope> g2(g1);
+ ThreadImpl::yield();
+
+ }
+
+ }
+
+ }
+
+/**
+ * Broadcast to the condition variable, waking all threads waiting at the time of
+ * the broadcast.
+ */
+template <typename List>
+void ConditionImpl<List>::broadcast() {
+
+ Guard<FastLock> g1(_lock);
+
+ // Try to find a waiter with a backoff & retry scheme
+ for(;;) {
+
+ // Go through the list, attempt to notify() a waiter.
+ for(typename List::iterator i = _waiters.begin(); i != _waiters.end();) {
+
+ // Try the monitor lock, if it cant be locked skip to the next waiter
+ ThreadImpl* impl = *i;
+ Monitor& m = impl->getMonitor();
+
+ if(m.tryAcquire()) {
+
+ // Notify the monitor & remove from the waiter list so time isn't
+ // wasted checking it again.
+ i = _waiters.erase(i);
+
+ // Try to wake the waiter, it doesn't matter if this is successful
+ // or not (only fails when the monitor is already going to stop waiting).
+ m.notify();
+
+ m.release();
+
+ } else ++i;
+
+ }
+
+ if(_waiters.empty())
+ return;
+
+ { // Backoff and try again
+
+ Guard<FastLock, UnlockedScope> g2(g1);
+ ThreadImpl::yield();
+
+ }
+
+ }
+
+ }
+
+/**
+ * Cause the currently executing thread to block until this ConditionImpl has
+ * been signaled, the threads state changes.
+ *
+ * @param predicate Lockable&
+ *
+ * @exception Interrupted_Exception thrown when the caller status is interrupted
+ * @exception Synchronization_Exception thrown if there is some other error.
+ */
+template <typename List>
+void ConditionImpl<List>::wait() {
+
+ // Get the monitor for the current thread
+ ThreadImpl* self = ThreadImpl::current();
+ Monitor& m = self->getMonitor();
+
+ Monitor::STATE state;
+
+ {
+
+ Guard<FastLock> g1(_lock);
+
+ // Release the _predicateLock
+ _predicateLock.release();
+
+ // Stuff the waiter into the list
+ _waiters.insert(self);
+
+ // Move to the monitor's lock
+ m.acquire();
+
+ {
+
+ Guard<FastLock, UnlockedScope> g2(g1);
+ state = m.wait();
+
+ }
+
+ // Move back to the Condition's lock
+ m.release();
+
+ // Remove from waiter list, regarless of weather release() is called or
+ // not. The monitor is sticky, so its possible a state 'stuck' from a
+ // previous operation and will leave the wait() w/o release() having
+ // been called.
+ typename List::iterator i = std::find(_waiters.begin(), _waiters.end(), self);
+ if(i != _waiters.end())
+ _waiters.erase(i);
+
+ }
+
+ // Defer interruption until the external lock is acquire()d
+ Guard<Monitor, DeferredInterruptionScope> g3(m);
+ {
+
+#if !defined(NDEBUG)
+ try {
+#endif
+ _predicateLock.acquire(); // Should not throw
+#if !defined(NDEBUG)
+ } catch(...) { assert(0); }
+#endif
+
+ }
+
+ switch(state) {
+
+ case Monitor::SIGNALED:
+ break;
+
+ case Monitor::INTERRUPTED:
+ throw Interrupted_Exception();
+
+ default:
+ throw Synchronization_Exception();
+ }
+
+ }
+
+
+/**
+ * Cause the currently executing thread to block until this ConditionImpl has
+ * been signaled, or the timeout expires or the threads state changes.
+ *
+ * @param _predicateLock Lockable&
+ * @param timeout maximum milliseconds to block.
+ *
+ * @return bool
+ *
+ * @exception Interrupted_Exception thrown when the caller status is interrupted
+ * @exception Synchronization_Exception thrown if there is some other error.
+ */
+template <typename List>
+bool ConditionImpl<List>::wait(unsigned long timeout) {
+
+ // Get the monitor for the current thread
+ ThreadImpl* self = ThreadImpl::current();
+ Monitor& m = self->getMonitor();
+
+ Monitor::STATE state;
+
+ {
+
+ Guard<FastLock> g1(_lock);
+
+ // Release the _predicateLock
+ _predicateLock.release();
+
+ // Stuff the waiter into the list
+ _waiters.insert(self);
+
+ state = Monitor::TIMEDOUT;
+
+ // Don't bother waiting if the timeout is 0
+ if(timeout) {
+
+ m.acquire();
+
+ {
+
+ Guard<FastLock, UnlockedScope> g2(g1);
+ state = m.wait(timeout);
+
+ }
+
+ m.release();
+
+ }
+
+ // Remove from waiter list, regarless of weather release() is called or
+ // not. The monitor is sticky, so its possible a state 'stuck' from a
+ // previous operation and will leave the wait() w/o release() having
+ // been called.
+ typename List::iterator i = std::find(_waiters.begin(), _waiters.end(), self);
+ if(i != _waiters.end())
+ _waiters.erase(i);
+
+ }
+
+
+ // Defer interruption until the external lock is acquire()d
+ Guard<Monitor, DeferredInterruptionScope> g3(m);
+ {
+
+#if !defined(NDEBUG)
+ try {
+#endif
+ _predicateLock.acquire(); // Should not throw
+#if !defined(NDEBUG)
+ } catch(...) { assert(0); }
+#endif
+
+ }
+
+ switch(state) {
+
+ case Monitor::SIGNALED:
+ break;
+
+ case Monitor::INTERRUPTED:
+ throw Interrupted_Exception();
+
+ case Monitor::TIMEDOUT:
+ return false;
+
+ default:
+ throw Synchronization_Exception();
+ }
+
+ return true;
+
+ }
+
+} // namespace ZThread
+
+#endif // __ZTCONDITIONIMPL_H__
diff --git a/dep/src/zthread/CountingSemaphore.cxx b/dep/src/zthread/CountingSemaphore.cxx
new file mode 100644
index 00000000000..43e8b8cfba7
--- /dev/null
+++ b/dep/src/zthread/CountingSemaphore.cxx
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "zthread/CountingSemaphore.h"
+#include "SemaphoreImpl.h"
+
+using namespace ZThread;
+
+namespace ZThread {
+
+
+ CountingSemaphore::CountingSemaphore(int initialCount) {
+
+ _impl = new FifoSemaphoreImpl(initialCount, 0 , false);
+
+ }
+
+
+ CountingSemaphore::~CountingSemaphore() {
+
+ try {
+
+ if(_impl != 0)
+ delete _impl;
+
+ } catch(...) { }
+
+ }
+
+
+ void CountingSemaphore::wait() {
+ _impl->acquire();
+ }
+
+
+ bool CountingSemaphore::tryWait(unsigned long ms) {
+
+ return _impl->tryAcquire(ms);
+
+ }
+
+
+ void CountingSemaphore::post() {
+
+ _impl->release();
+
+ }
+
+ int CountingSemaphore::count() {
+
+ return _impl->count();
+
+ }
+
+ void CountingSemaphore::acquire() {
+
+ _impl->acquire();
+
+ }
+
+ bool CountingSemaphore::tryAcquire(unsigned long ms) {
+
+ return _impl->tryAcquire(ms);
+
+ }
+
+ void CountingSemaphore::release() {
+
+ _impl->release();
+
+ }
+
+} // namespace ZThread
diff --git a/dep/src/zthread/Debug.h b/dep/src/zthread/Debug.h
new file mode 100644
index 00000000000..484b37f7d6f
--- /dev/null
+++ b/dep/src/zthread/Debug.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef ZTDEBUG
+
+#ifndef NDEBUG
+# include <stdio.h>
+# define ZTDEBUG printf
+#else
+# define ZTDEBUG(x)
+#endif
+
+#endif
diff --git a/dep/src/zthread/DeferredInterruptionScope.h b/dep/src/zthread/DeferredInterruptionScope.h
new file mode 100644
index 00000000000..041d1e427f6
--- /dev/null
+++ b/dep/src/zthread/DeferredInterruptionScope.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTDEFERREDINTERRUPTIONSCOPE_H__
+#define __ZTDEFERREDINTERRUPTIONSCOPE_H__
+
+#include "ThreadImpl.h"
+#include <cassert>
+
+namespace ZThread {
+
+/**
+ * @class DeferredInterruptionScope
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T19:45:18-0400>
+ * @version 2.3.0
+ *
+ * Locking policy for a Guard that will defer any state reported
+ * for the reported Status of a thread except SIGNALED until the
+ * scope has ended. This allows a Guard to be used to create an
+ * uninterruptible region in code.
+ */
+class DeferredInterruptionScope {
+ public:
+
+ template <class LockType>
+ static void createScope(LockHolder<LockType>& l) {
+
+ l.getLock().interest(Monitor::SIGNALED);
+
+ }
+
+ template <class LockType>
+ static void destroyScope(LockHolder<LockType>& l) {
+
+ l.getLock().interest(Monitor::ANYTHING);
+
+ }
+
+};
+
+}
+
+#endif // __ZTDEFERREDINTERRUPTIONSCOPE_H__
diff --git a/dep/src/zthread/FastLock.h b/dep/src/zthread/FastLock.h
new file mode 100644
index 00000000000..4d7f34a086d
--- /dev/null
+++ b/dep/src/zthread/FastLock.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTFASTLOCKSELECT_H__
+#define __ZTFASTLOCKSELECT_H__
+
+#include "zthread/Config.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+// Select the correct FastLock implementation based on
+// what the compilation environment has defined
+
+#if defined(ZT_POSIX)
+
+# if defined(HAVE_ATOMIC_LINUX)
+
+# if defined(ZTHREAD_USE_SPIN_LOCKS)
+# include "linux/AtomicFastLock.h"
+# endif
+
+# endif
+
+# include "posix/FastLock.h"
+
+// Use spin locks
+#elif defined(ZTHREAD_USE_SPIN_LOCKS)
+
+# if defined(ZT_WIN9X)
+# include "win9x/AtomicFastLock.h"
+# elif defined(ZT_WIN32)
+# include "win32/AtomicFastLock.h"
+# endif
+
+// Use normal Mutex objects
+#elif defined(ZT_WIN9X) || defined(ZT_WIN32)
+
+# include "win32/FastLock.h"
+
+#elif defined(ZT_MACOS)
+
+# include "macos/FastLock.h"
+
+#endif
+
+#ifndef __ZTFASTLOCK_H__
+#error "No FastLock implementation could be selected"
+#endif
+
+#endif // __ZTFASTLOCKSELECT_H__
diff --git a/dep/src/zthread/FastMutex.cxx b/dep/src/zthread/FastMutex.cxx
new file mode 100644
index 00000000000..464dd83e5e0
--- /dev/null
+++ b/dep/src/zthread/FastMutex.cxx
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "zthread/FastMutex.h"
+#include "FastLock.h"
+
+namespace ZThread {
+
+ FastMutex::FastMutex() : _lock(new FastLock) { }
+
+ FastMutex::~FastMutex() {
+ delete _lock;
+ }
+
+
+ void FastMutex::acquire() {
+
+ _lock->acquire();
+
+ }
+
+ bool FastMutex::tryAcquire(unsigned long timeout) {
+
+ return _lock->tryAcquire(timeout);
+
+ }
+
+ void FastMutex::release() {
+
+ _lock->release();
+
+ }
+
+} // namespace ZThread
diff --git a/dep/src/zthread/FastRecursiveLock.h b/dep/src/zthread/FastRecursiveLock.h
new file mode 100644
index 00000000000..0a36f62d5f8
--- /dev/null
+++ b/dep/src/zthread/FastRecursiveLock.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTFASTRECURSIVELOCKSELECT_H__
+#define __ZTFASTRECURSIVELOCKSELECT_H__
+
+#include "zthread/Config.h"
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+
+// Select the correct FastRecusriveLock implementation based on
+// what the compilation environment has defined
+
+#if defined(ZTHREAD_DUAL_LOCKS)
+# include "vanilla/DualMutexRecursiveLock.h"
+#else
+
+# ifndef ZT_VANILLA
+
+# if defined(ZT_POSIX)
+
+// Linux and Solaris have working pthreads recursive locks. These
+// are created differently, and there are some system don't seem to
+// include recursive locks at all. Several recursive implementations
+// are provided
+
+# if defined(__linux__)
+# include "linux/FastRecursiveLock.h"
+# elif defined(HAVE_MUTEXATTR_SETTYPE)
+# include "solaris/FastRecursiveLock.h"
+# elif defined(ZTHREAD_CONDITION_LOCKS)
+# include "posix/ConditionRecursiveLock.h"
+# endif
+
+// Use spin locks
+# elif defined(ZT_WIN32) && defined(ZTHREAD_USE_SPIN_LOCKS)
+# include "win32/AtomicFastRecursiveLock.h"
+
+// Use normal Mutex objects
+# elif defined(ZT_WIN32) || defined(ZT_WIN9X)
+# include "win32/FastRecursiveLock.h"
+# endif
+
+# endif
+
+#endif
+
+#ifndef __ZTFASTRECURSIVELOCK_H__
+#include "vanilla/SimpleRecursiveLock.h"
+#endif
+
+#endif // __ZTFASTRECURSIVELOCKSELECT_H__
diff --git a/dep/src/zthread/FastRecursiveMutex.cxx b/dep/src/zthread/FastRecursiveMutex.cxx
new file mode 100644
index 00000000000..5ca677a654d
--- /dev/null
+++ b/dep/src/zthread/FastRecursiveMutex.cxx
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "zthread/FastRecursiveMutex.h"
+#include "FastRecursiveLock.h"
+
+namespace ZThread {
+
+ FastRecursiveMutex::FastRecursiveMutex()
+ : _lock(new FastRecursiveLock) { }
+
+ FastRecursiveMutex::~FastRecursiveMutex()
+ { delete _lock; }
+
+
+ void FastRecursiveMutex::acquire() {
+
+ _lock->acquire();
+
+ }
+
+ bool FastRecursiveMutex::tryAcquire(unsigned long timeout) {
+
+ return _lock->tryAcquire(timeout);
+
+ }
+
+ void FastRecursiveMutex::release() {
+
+ _lock->release();
+
+ }
+
+} // namespace ZThread
diff --git a/dep/src/zthread/IntrusivePtr.h b/dep/src/zthread/IntrusivePtr.h
new file mode 100644
index 00000000000..47d5afbfcb8
--- /dev/null
+++ b/dep/src/zthread/IntrusivePtr.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTINTRUSIVEPTR_H__
+#define __ZTINTRUSIVEPTR_H__
+
+#include "zthread/Guard.h"
+#include <cstdlib>
+
+namespace ZThread {
+
+/**
+ * @class IntrusivePtr
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T17:54:23-0400>
+ * @version 2.2.0
+ *
+ * This template creates an intrusively reference counted object
+ * an IntrusivePtr starts out with a 1 count, which is updated as references are
+ * added and removed. When the reference count drops to 0, the
+ * IntrusivePtr will delete itself.
+ */
+template <typename T, class LockType>
+class IntrusivePtr : NonCopyable {
+
+ //! Intrusive reference count
+ size_t _count;
+
+ //! Synchornization object
+ LockType _lock;
+
+public:
+
+ /**
+ * Create an IntrusivePtr with a count.
+ */
+ IntrusivePtr(size_t InitialCount=1) : _count(InitialCount) { }
+
+ /**
+ * Destroy an IntrusivePtr
+ */
+ virtual ~IntrusivePtr() {}
+
+ /**
+ * Add a reference to this object, it will take one more
+ * call to delReference() for it to be deleted.
+ */
+ void addReference() {
+
+ Guard<LockType, LockedScope> g(_lock);
+ _count++;
+
+ }
+
+ /**
+ * Remove a reference from this object, if the reference count
+ * drops to 0 as a result, the object deletes itself.
+ */
+ void delReference() {
+
+ bool result = false;
+
+ {
+
+ Guard<LockType, LockedScope> g(_lock);
+ result = (--_count == 0);
+
+ }
+
+ if(result)
+ delete this;
+
+ }
+
+};
+
+
+};
+
+#endif
diff --git a/dep/src/zthread/Makefile.am b/dep/src/zthread/Makefile.am
new file mode 100644
index 00000000000..a3c91195d51
--- /dev/null
+++ b/dep/src/zthread/Makefile.am
@@ -0,0 +1,132 @@
+## Copyright (c) 2005, Eric Crahen
+## Modified for MaNGOS project <http://www.mangosproject.org>
+##
+## Permission is hereby granted, free of charge, to any person obtaining a copy
+## of this software and associated documentation files (the "Software"), to deal
+## in the Software without restriction, including without limitation the rights
+## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+## copies of the Software, and to permit persons to whom the Software is furnished
+## to do so, subject to the following conditions:
+##
+## The above copyright notice and this permission notice shall be included in all
+## copies or substantial portions of the Software.
+##
+## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+## WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+## Process this file with automake to produce Makefile.in
+
+## CPP flags for includes, defines, etc.
+AM_CPPFLAGS = -I$(srcdir)/../../include -I$(srcdir)/../../include/zthread
+
+## Build ZThread as shared library.
+# libZThread shared library will later be reused by realm list daemon
+# and world server daemon.
+lib_LTLIBRARIES = libZThread.la
+libZThread_la_SOURCES = \
+ AtomicCount.cxx \
+ Condition.cxx \
+ ConcurrentExecutor.cxx \
+ CountingSemaphore.cxx \
+ FastMutex.cxx \
+ FastRecursiveMutex.cxx \
+ Mutex.cxx \
+ RecursiveMutexImpl.cxx \
+ RecursiveMutex.cxx \
+ Monitor.cxx \
+ PoolExecutor.cxx \
+ PriorityCondition.cxx \
+ PriorityInheritanceMutex.cxx \
+ PriorityMutex.cxx \
+ PrioritySemaphore.cxx \
+ Semaphore.cxx \
+ SynchronousExecutor.cxx \
+ Thread.cxx \
+ ThreadedExecutor.cxx \
+ ThreadImpl.cxx \
+ ThreadLocalImpl.cxx \
+ ThreadQueue.cxx \
+ Time.cxx \
+ ThreadOps.cxx
+
+## libtool settings
+# API versioning
+# Link against dependencies
+# How to increase version info:
+# - only bug fixes implemented:
+# bump the version to LTZTHREAD_CURRENT:LTZTHREAD_REVISION+1:LTZTHREAD_AGE
+# - augmented the interface:
+# bump the version to LTZTHREAD_CURRENT+1:0:LTZTHREAD_AGE+1
+# - broken old interface:
+# bump the version to LTZTHREAD_CURRENT+1:0:0
+LTZTHREAD_CURRENT = 2
+LTZTHREAD_REVISION = 3
+LTZTHREAD_AGE = 2
+libZThread_la_LDFLAGS = -version-info $(LTZTHREAD_CURRENT):$(LTZTHREAD_REVISION):$(LTZTHREAD_AGE)
+
+## Additional files to include when running 'make dist'
+# Header files.
+EXTRA_DIST = \
+ ConditionImpl.h \
+ Debug.h \
+ DeferredInterruptionScope.h \
+ FastLock.h \
+ FastRecursiveLock.h \
+ IntrusivePtr.h \
+ Monitor.h \
+ MutexImpl.h \
+ RecursiveMutexImpl.h \
+ Scheduling.h \
+ SemaphoreImpl.h \
+ State.h \
+ Status.h \
+ TSS.h \
+ ThreadImpl.h \
+ ThreadOps.h \
+ ThreadQueue.h \
+ TimeStrategy.h \
+ config.h
+
+# Implementation specific files.
+EXTRA_DIST += \
+ linux/AtomicCount.cxx \
+ linux/AtomicFastLock.h \
+ linux/FastRecursiveLock.h \
+ macos/FastLock.h \
+ macos/Monitor.cxx \
+ macos/Monitor.h \
+ macos/TSS.h \
+ macos/ThreadOps.cxx \
+ macos/ThreadOps.h \
+ macos/UpTimeStrategy.h \
+ posix/ConditionRecursiveLock.h \
+ posix/FastLock.h \
+ posix/FtimeStrategy.h \
+ posix/GetTimeOfDayStrategy.h \
+ posix/Monitor.cxx \
+ posix/Monitor.h \
+ posix/PriorityOps.h \
+ posix/TSS.h \
+ posix/ThreadOps.cxx \
+ posix/ThreadOps.h \
+ solaris/FastRecursiveLock.h \
+ vanilla/DualMutexRecursiveLock.h \
+ vanilla/SimpleAtomicCount.cxx \
+ vanilla/SimpleRecursiveLock.h \
+ win32/AtomicCount.cxx \
+ win32/AtomicFastLock.h \
+ win32/AtomicFastRecursiveLock.h \
+ win32/FastLock.h \
+ win32/FastRecursiveLock.h \
+ win32/Monitor.cxx \
+ win32/Monitor.h \
+ win32/PerformanceCounterStrategy.h \
+ win32/TSS.h \
+ win32/ThreadOps.cxx \
+ win32/ThreadOps.h \
+ win9x/AtomicCount.cxx \
+ win9x/AtomicFastLock.h
diff --git a/dep/src/zthread/Monitor.cxx b/dep/src/zthread/Monitor.cxx
new file mode 100644
index 00000000000..9a578e796ed
--- /dev/null
+++ b/dep/src/zthread/Monitor.cxx
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTMONITORIMPLSELECT_CXX__
+#define __ZTMONITORIMPLSELECT_CXX__
+
+#include "Monitor.h"
+
+// This file will select an implementation for a Monitor based on
+// what Monitor.h selects. This method is for selecting the
+// source files, to improve portability. Currently, the project is
+// based on the autoconf tool-set, which doesn't support conditional
+// compilation well. Additionally, this should make the library
+// easier to port since its working around conditional compilation
+// by using C++ features and people won't have to fiddle around with
+// their make tool as much to compile the source
+
+#include ZT_MONITOR_IMPLEMENTATION
+
+#endif
diff --git a/dep/src/zthread/Monitor.h b/dep/src/zthread/Monitor.h
new file mode 100644
index 00000000000..6f9492fe32c
--- /dev/null
+++ b/dep/src/zthread/Monitor.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTMONITORSELECT_H__
+#define __ZTMONITORSELECT_H__
+
+#include "zthread/Config.h"
+
+#if defined(ZT_MONITOR_IMPLEMENTATION)
+# error "Reserved symbol defined"
+#endif
+
+// Include the dependencies for a Montior
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+// Select the correct Monitor implementation based on
+// what the compilation environment has defined
+#if defined(ZT_POSIX)
+
+# include "posix/Monitor.h"
+# define ZT_MONITOR_IMPLEMENTATION "posix/Monitor.cxx"
+
+#elif defined(ZT_WIN32) || defined(ZT_WIN9X)
+
+# include "win32/Monitor.h"
+# define ZT_MONITOR_IMPLEMENTATION "win32/Monitor.cxx"
+
+#elif defined(ZT_MACOS)
+
+# include "macos/Monitor.h"
+# define ZT_MONITOR_IMPLEMENTATION "macos/Monitor.cxx"
+
+#endif
+
+#ifndef __ZTMONITOR_H__
+#error "No Monitor implementation could be selected"
+#endif
+
+#endif // __ZTMONITORSELECT_H__
diff --git a/dep/src/zthread/Mutex.cxx b/dep/src/zthread/Mutex.cxx
new file mode 100644
index 00000000000..eca38ba89c6
--- /dev/null
+++ b/dep/src/zthread/Mutex.cxx
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "zthread/Mutex.h"
+#include "MutexImpl.h"
+
+namespace ZThread {
+
+ class FifoMutexImpl : public MutexImpl<fifo_list, NullBehavior> { };
+
+
+ Mutex::Mutex() {
+
+ _impl = new FifoMutexImpl();
+
+ }
+
+ Mutex::~Mutex() {
+
+ if(_impl != 0)
+ delete _impl;
+ }
+
+ // P
+ void Mutex::acquire() {
+
+ _impl->acquire();
+
+ }
+
+
+ // P
+ bool Mutex::tryAcquire(unsigned long ms) {
+
+ return _impl->tryAcquire(ms);
+
+ }
+
+ // V
+ void Mutex::release() {
+
+ _impl->release();
+
+ }
+
+
+
+} // namespace ZThread
+
diff --git a/dep/src/zthread/MutexImpl.h b/dep/src/zthread/MutexImpl.h
new file mode 100644
index 00000000000..10a9160ce5a
--- /dev/null
+++ b/dep/src/zthread/MutexImpl.h
@@ -0,0 +1,377 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "zthread/Exceptions.h"
+#include "zthread/Guard.h"
+
+#include "Debug.h"
+#include "FastLock.h"
+#include "Scheduling.h"
+
+#include <assert.h>
+#include <errno.h>
+
+namespace ZThread {
+
+
+/**
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T19:52:12-0400>
+ * @version 2.2.11
+ * @class NullBehavior
+ */
+class NullBehavior {
+protected:
+
+ inline void waiterArrived(ThreadImpl*) { }
+
+ inline void waiterDeparted(ThreadImpl*) { }
+
+ inline void ownerAcquired(ThreadImpl*) { }
+
+ inline void ownerReleased(ThreadImpl*) { }
+
+};
+
+/**
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T19:52:12-0400>
+ * @version 2.2.11
+ * @class MutexImpl
+ *
+ * The MutexImpl template allows how waiter lists are sorted, and
+ * what actions are taken when a thread interacts with the mutex
+ * to be parametized.
+ */
+template <typename List, typename Behavior>
+class MutexImpl : Behavior {
+
+ //! List of Events that are waiting for notification
+ List _waiters;
+
+ //! Serialize access to this Mutex
+ FastLock _lock;
+
+ //! Current owner
+ volatile ThreadImpl* _owner;
+
+ public:
+
+
+ /**
+ * Create a new MutexImpl
+ *
+ * @exception Initialization_Exception thrown if resources could not be
+ * properly allocated
+ */
+ MutexImpl() : _owner(0) { }
+
+ ~MutexImpl();
+
+ void acquire();
+
+ void release();
+
+ bool tryAcquire(unsigned long timeout);
+
+};
+
+ /**
+ * Destroy this MutexImpl and release its resources
+ */
+template<typename List, typename Behavior>
+MutexImpl<List, Behavior>::~MutexImpl() {
+
+#ifndef NDEBUG
+
+ // It is an error to destroy a mutex that has not been released
+ if(_owner != 0) {
+
+ ZTDEBUG("** You are destroying a mutex which was never released. **\n");
+ assert(0); // Destroyed mutex while in use
+
+ }
+
+ if(!_waiters.empty()) {
+
+ ZTDEBUG("** You are destroying a mutex which is blocking %d threads. **\n", _waiters.size());
+ assert(0); // Destroyed mutex while in use
+
+ }
+
+#endif
+
+ }
+
+
+ /**
+ * Acquire a lock on the mutex. If this operation succeeds the calling
+ * thread holds an exclusive lock on this mutex, otherwise it is blocked
+ * until the lock can be acquired.
+ *
+ * @exception Deadlock_Exception thrown when the caller attempts to acquire() more
+ * than once, If the checking flag is set.
+ * @exception Interrupted_Exception thrown when the caller status is interrupted
+ * @exception Synchronization_Exception thrown if there is some other error.
+ */
+template<typename List, typename Behavior>
+void MutexImpl<List, Behavior>::acquire() {
+
+ ThreadImpl* self = ThreadImpl::current();
+ Monitor& m = self->getMonitor();
+
+ Monitor::STATE state;
+
+ Guard<FastLock> g1(_lock);
+
+ // Deadlock will occur if the current thread is the owner
+ // and there is no entry count.
+ if(_owner == self)
+ throw Deadlock_Exception();
+
+ // Acquire the lock if it is free and there are no waiting threads
+ if(_owner == 0 && _waiters.empty()) {
+
+ _owner = self;
+
+ this->ownerAcquired(self);
+
+ }
+
+ // Otherwise, wait for a signal from a thread releasing its
+ // ownership of the lock
+ else {
+
+ _waiters.insert(self);
+ m.acquire();
+
+ this->waiterArrived(self);
+
+ {
+
+ Guard<FastLock, UnlockedScope> g2(g1);
+ state = m.wait();
+
+ }
+
+ this->waiterDeparted(self);
+
+ m.release();
+
+ // Remove from waiter list, regardless of wether release() is called or
+ // not. The monitor is sticky, so its possible a state 'stuck' from a
+ // previous operation and will leave the wait() w/o release() having
+ // been called (e.g. interrupted)
+ typename List::iterator i = std::find(_waiters.begin(), _waiters.end(), self);
+ if(i != _waiters.end())
+ _waiters.erase(i);
+
+ // If awoke due to a notify(), take ownership.
+ switch(state) {
+ case Monitor::SIGNALED:
+
+ assert(_owner == 0);
+ _owner = self;
+
+ this->ownerAcquired(self);
+
+ break;
+
+ case Monitor::INTERRUPTED:
+ throw Interrupted_Exception();
+
+ default:
+ throw Synchronization_Exception();
+ }
+
+ }
+
+ }
+
+
+ /**
+ * Acquire a lock on the mutex. If this operation succeeds the calling
+ * thread holds an exclusive lock on this mutex. If the lock cannot be
+ * obtained before the timeout expires, the caller returns false.
+ *
+ * @exception Deadlock_Exception thrown when the caller attempts to acquire() more
+ * than once, If the checking flag is set.
+ * @exception Interrupted_Exception thrown when the caller status is interrupted
+ * @exception Synchronization_Exception thrown if there is some other error.
+ */
+template<typename List, typename Behavior>
+bool MutexImpl<List, Behavior>::tryAcquire(unsigned long timeout) {
+
+ ThreadImpl* self = ThreadImpl::current();
+ Monitor& m = self->getMonitor();
+
+ Guard<FastLock> g1(_lock);
+
+ // Deadlock will occur if the current thread is the owner
+ // and there is no entry count.
+ if(_owner == self)
+ throw Deadlock_Exception();
+
+ // Acquire the lock if it is free and there are no waiting threads
+ if(_owner == 0 && _waiters.empty()) {
+
+ _owner = self;
+
+ this->ownerAcquired(self);
+
+ }
+
+ // Otherwise, wait for a signal from a thread releasing its
+ // ownership of the lock
+ else {
+
+ _waiters.insert(self);
+
+ Monitor::STATE state = Monitor::TIMEDOUT;
+
+ // Don't bother waiting if the timeout is 0
+ if(timeout) {
+
+ m.acquire();
+
+ this->waiterArrived(self);
+
+ {
+
+ Guard<FastLock, UnlockedScope> g2(g1);
+ state = m.wait(timeout);
+
+ }
+
+ this->waiterDeparted(self);
+
+ m.release();
+
+ }
+
+
+ // Remove from waiter list, regarless of weather release() is called or
+ // not. The monitor is sticky, so its possible a state 'stuck' from a
+ // previous operation and will leave the wait() w/o release() having
+ // been called.
+ typename List::iterator i = std::find(_waiters.begin(), _waiters.end(), self);
+ if(i != _waiters.end())
+ _waiters.erase(i);
+
+ // If awoke due to a notify(), take ownership.
+ switch(state) {
+ case Monitor::SIGNALED:
+
+ assert(0 == _owner);
+ _owner = self;
+
+ this->ownerAcquired(self);
+
+ break;
+
+ case Monitor::INTERRUPTED:
+ throw Interrupted_Exception();
+
+ case Monitor::TIMEDOUT:
+ return false;
+
+ default:
+ throw Synchronization_Exception();
+ }
+
+ }
+
+ return true;
+
+ }
+
+ /**
+ * Release a lock on the mutex. If this operation succeeds the calling
+ * thread no longer holds an exclusive lock on this mutex. If there are
+ * waiting threads, one will be selected, assigned ownership and specifically
+ * awakened.
+ *
+ * @exception InvalidOp_Exception - thrown if an attempt is made to
+ * release a mutex not owned by the calling thread.
+ */
+template<typename List, typename Behavior>
+void MutexImpl<List, Behavior>::release() {
+
+ ThreadImpl* impl = ThreadImpl::current();
+
+ Guard<FastLock> g1(_lock);
+
+ // Make sure the operation is valid
+ if(_owner != impl)
+ throw InvalidOp_Exception();
+
+ _owner = 0;
+
+ this->ownerReleased(impl);
+
+ // Try to find a waiter with a backoff & retry scheme
+ for(;;) {
+
+ // Go through the list, attempt to notify() a waiter.
+ for(typename List::iterator i = _waiters.begin(); i != _waiters.end();) {
+
+ // Try the monitor lock, if it cant be locked skip to the next waiter
+ impl = *i;
+ Monitor& m = impl->getMonitor();
+
+ if(m.tryAcquire()) {
+
+ // If notify() is not sucessful, it is because the wait() has already
+ // been ended (killed/interrupted/notify'd)
+ bool woke = m.notify();
+
+ m.release();
+
+ // Once notify() succeeds, return
+ if(woke)
+ return;
+
+ } else ++i;
+
+ }
+
+ if(_waiters.empty())
+ return;
+
+ { // Backoff and try again
+
+ Guard<FastLock, UnlockedScope> g2(g1);
+ ThreadImpl::yield();
+
+ }
+
+ }
+
+ }
+
+} // namespace ZThread
+
+
+
+
+
+
diff --git a/dep/src/zthread/PoolExecutor.cxx b/dep/src/zthread/PoolExecutor.cxx
new file mode 100644
index 00000000000..cf84e145453
--- /dev/null
+++ b/dep/src/zthread/PoolExecutor.cxx
@@ -0,0 +1,629 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "ThreadImpl.h"
+#include "zthread/PoolExecutor.h"
+#include "zthread/MonitoredQueue.h"
+#include "zthread/FastMutex.h"
+#include "ThreadImpl.h"
+#include "ThreadQueue.h"
+
+#include <algorithm>
+#include <deque>
+#include <utility>
+
+using namespace ZThread;
+
+namespace ZThread {
+
+ namespace {
+
+ /**
+ */
+ class WaiterQueue {
+
+ typedef std::deque<ThreadImpl*> ThreadList;
+
+ typedef struct group_t {
+ size_t id;
+ size_t count;
+ ThreadList waiters;
+ group_t(size_t n) : id(n), count(0) {}
+ } Group;
+
+ typedef std::deque<Group> GroupList;
+
+ //! Predicate to find a specific group
+ struct by_id : public std::unary_function<bool, Group> {
+ size_t id;
+ by_id(size_t n) : id(n) {}
+ bool operator()(const Group& grp) {
+ return grp.id == id;
+ }
+ };
+
+ //! Functor to count groups
+ struct counter : public std::unary_function<void, Group> {
+ size_t count;
+ counter() : count(0) {}
+ void operator()(const Group& grp) { count += grp.count; }
+ operator size_t() { return count; }
+ };
+
+ FastMutex _lock;
+ GroupList _list;
+ size_t _id;
+ size_t _generation;
+
+ public:
+
+ WaiterQueue() : _id(0), _generation(0) {
+ // At least one empty-group exists
+ _list.push_back( Group(_id++) );
+ }
+
+ /**
+ * Insert the current thread into the current waiter list
+ *
+ * @pre At least one empty group exists
+ * @post At least one empty group exists
+ */
+ bool wait(unsigned long timeout) {
+
+ ThreadImpl* current = ThreadImpl::current();
+ Monitor& m = current->getMonitor();
+
+ Monitor::STATE state;
+
+ Guard<FastMutex> g1(_lock);
+
+ // At least one empty-group exists
+ assert(!_list.empty());
+
+ // Return w/o waiting if there are no executing tasks
+ if((size_t)std::for_each(_list.begin(), _list.end(), counter()) < 1)
+ return true;
+
+ // Update the waiter list for the active group
+ _list.back().waiters.push_back(current);
+ size_t n = _list.back().id;
+
+ m.acquire();
+
+ {
+
+ Guard<FastMutex, UnlockedScope> g2(g1);
+ state = timeout == 0 ? m.wait() : m.wait(timeout);
+
+ }
+
+ m.release();
+
+ // If awoke due to a reason other than the last task in the group 'n' completing,
+ // then then find the group 'current' is waiting in
+ GroupList::iterator i = std::find_if(_list.begin(), _list.end(), by_id(n));
+ if(i != _list.end()) {
+
+ // Remove 'current' from that list if it is still a member
+ ThreadList::iterator j = std::find(i->waiters.begin(), i->waiters.end(), current);
+ if(j != i->waiters.end())
+ i->waiters.erase(j);
+
+ }
+
+ // At least one empty-group exists
+ assert(!_list.empty());
+
+ switch(state) {
+ case Monitor::SIGNALED:
+ break;
+ case Monitor::TIMEDOUT:
+ return false;
+ case Monitor::INTERRUPTED:
+ throw Interrupted_Exception();
+ default:
+ throw Synchronization_Exception();
+ }
+
+ return true;
+
+ }
+
+ /**
+ * Increment the active group count
+ *
+ * @pre at least 1 empty group exists
+ * @post at least 1 non-empty group exists
+ */
+ std::pair<size_t, size_t> increment() {
+
+ Guard<FastMutex> g(_lock);
+
+ // At least one empty-group exists
+ assert(!_list.empty());
+
+ GroupList::iterator i = --_list.end();
+ size_t n = i->id;
+
+ if(i == _list.end()) {
+
+ // A group should never have been removed until
+ // the final task in that group completed
+ assert(0);
+
+ }
+
+ i->count++;
+
+ // When the active group is being incremented, insert a new active group
+ // to replace it if there were waiting threads
+ if(i == --_list.end() && !i->waiters.empty())
+ _list.push_back(Group(_id++));
+
+ // At least 1 non-empty group exists
+ assert((size_t)std::for_each(_list.begin(), _list.end(), counter()) > 0);
+
+ return std::make_pair(n, _generation);
+
+ }
+
+
+ /**
+ * Decrease the count for the group with the given id.
+ *
+ * @param n group id
+ *
+ * @pre At least 1 non-empty group exists
+ * @post At least 1 empty group exists
+ */
+ void decrement(size_t n) {
+
+ Guard<FastMutex> g1(_lock);
+
+ // At least 1 non-empty group exists
+ assert((size_t)std::for_each(_list.begin(), _list.end(), counter()) > 0);
+
+ // Find the requested group
+ GroupList::iterator i = std::find_if(_list.begin(), _list.end(), by_id(n));
+ if(i == _list.end()) {
+
+ // A group should never have been removed until
+ // the final task in that group completed
+ assert(0);
+
+ }
+
+ // Decrease the count for tasks in this group,
+ if(--i->count == 0 && i == _list.begin()) {
+
+ do {
+
+ // When the first group completes, wake all waiters for every
+ // group, starting from the first until a group that is not
+ // complete is reached
+
+ /*
+ // Don't remove the empty active group
+ if(i == --_list.end() && i->waiters.empty())
+ break;
+ */
+
+ if( awaken(*i) ) {
+
+ // If all waiters were awakened, remove the group
+ i = _list.erase(i);
+
+ } else {
+
+ {
+
+ // Otherwise, unlock and yield allowing the waiter
+ // lists to be updated if other threads are busy
+ Guard<FastLock, UnlockedScope> g2(g1);
+ ThreadImpl::yield();
+
+ }
+
+ i = _list.begin();
+
+ }
+
+ } while(i != _list.end() && i->count == 0);
+
+ // Ensure that an active group exists
+ if(_list.empty())
+ _list.push_back( Group(++_id) );
+
+ }
+
+ // At least one group exists
+ assert(!_list.empty());
+
+ }
+
+ /**
+ */
+ size_t generation(bool next = false) {
+
+ Guard<FastMutex> g(_lock);
+ return next ? _generation++ : _generation;
+
+ }
+
+ private:
+
+ /**
+ * Awaken all the waiters remaining in the given group
+ *
+ * @return
+ * - true if all the waiting threads were successfully awakened.
+ * - false if there were one or more threads that could not be awakened.
+ */
+ bool awaken(Group& grp) {
+
+ // Go through the waiter list in the given group;
+ for(ThreadList::iterator i = grp.waiters.begin(); i != grp.waiters.end();) {
+
+ ThreadImpl* impl = *i;
+ Monitor& m = impl->getMonitor();
+
+ // Try the monitor lock, if it cant be locked skip to the next waiter
+ if(m.tryAcquire()) {
+
+ // Notify the monitor & remove from the waiter list so time isn't
+ // wasted checking it again.
+ i = grp.waiters.erase(i);
+
+ // Try to wake the waiter, it doesn't matter if this is successful
+ // or not (only fails when the monitor is already going to stop waiting).
+ m.notify();
+ m.release();
+
+ } else ++i;
+
+ }
+
+ return grp.waiters.empty();
+
+ }
+
+ };
+
+ /**
+ * @class GroupedRunnable
+ *
+ * Wrap a task with group and generation information.
+ *
+ * - 'group' allows tasks to be grouped together so that lists of waiting
+ * threads can be managed.
+ *
+ * - 'generation' allows tasks to be interrupted
+ */
+ class GroupedRunnable : public Runnable {
+
+ Task _task;
+ WaiterQueue& _queue;
+
+ size_t _group;
+ size_t _generation;
+
+ public:
+
+ GroupedRunnable(const Task& task, WaiterQueue& queue)
+ : _task(task), _queue(queue) {
+
+ std::pair<size_t, size_t> pr( _queue.increment() );
+
+ _group = pr.first;
+ _generation = pr.second;
+
+ }
+
+ size_t group() const {
+ return _group;
+ }
+
+ size_t generation() const {
+ return _generation;
+ }
+
+ void run() {
+
+ try {
+
+ _task->run();
+
+ } catch(...) {
+
+ }
+
+ _queue.decrement( group() );
+
+ }
+
+ };
+
+ typedef CountedPtr<GroupedRunnable, size_t> ExecutorTask;
+
+ /**
+ *
+ */
+ class ExecutorImpl {
+
+ typedef MonitoredQueue<ExecutorTask, FastMutex> TaskQueue;
+ typedef std::deque<ThreadImpl*> ThreadList;
+
+ TaskQueue _taskQueue;
+ WaiterQueue _waitingQueue;
+
+ ThreadList _threads;
+ volatile size_t _size;
+
+
+ public:
+
+ ExecutorImpl() : _size(0) {}
+
+
+ void registerThread() {
+
+ Guard<TaskQueue> g(_taskQueue);
+
+ ThreadImpl* impl = ThreadImpl::current();
+ _threads.push_back(impl);
+
+ // current cancel if too many threads are being created
+ if(_threads.size() > _size)
+ impl->cancel();
+
+ }
+
+ void unregisterThread() {
+
+ Guard<TaskQueue> g(_taskQueue);
+ std::remove(_threads.begin(), _threads.end(), ThreadImpl::current());
+
+ }
+
+ void execute(const Task& task) {
+
+ // Wrap the task with a grouped task
+ GroupedRunnable* runnable = new GroupedRunnable(task, _waitingQueue);
+
+ try {
+
+ _taskQueue.add( ExecutorTask(runnable) );
+
+ } catch(...) {
+
+ // Incase the queue is canceled between the time the WaiterQueue is
+ // updated and the task is added to the TaskQueue
+ _waitingQueue.decrement( runnable->group() );
+ throw;
+
+ }
+
+ }
+
+ void interrupt() {
+
+ // Bump the generation number
+ _waitingQueue.generation(true);
+
+ Guard<TaskQueue> g(_taskQueue);
+
+ // Interrupt all threads currently running, thier tasks would be
+ // from an older generation
+ for(ThreadList::iterator i = _threads.begin(); i != _threads.end(); ++i)
+ (*i)->interrupt();
+
+ }
+
+ //! Adjust the number of desired workers and return the number of Threads needed
+ size_t workers(size_t n) {
+
+ Guard<TaskQueue> g(_taskQueue);
+
+ size_t m = (_size < n) ? (n - _size) : 0;
+ _size = n;
+
+ return m;
+
+ }
+
+ size_t workers() {
+
+ Guard<TaskQueue> g(_taskQueue);
+ return _size;
+
+ }
+
+ ExecutorTask next() {
+
+ ExecutorTask task;
+
+ // Draw the task from the queue
+ for(;;) {
+
+ try {
+
+ task = _taskQueue.next();
+ break;
+
+ } catch(Interrupted_Exception&) {
+
+ // Ignore interruption here, it can only come from
+ // another thread interrupt()ing the executor. The
+ // thread was interrupted in the hopes it was busy
+ // with a task
+
+ }
+
+ }
+
+ // Interrupt the thread running the tasks when the generation
+ // does not match the current generation
+ if( task->generation() != _waitingQueue.generation() )
+ ThreadImpl::current()->interrupt();
+
+ // Otherwise, clear the interrupted status for the thread and
+ // give it a clean slate to start with
+ else
+ ThreadImpl::current()->isInterrupted();
+
+ return task;
+
+ }
+
+ bool isCanceled() {
+ return _taskQueue.isCanceled();
+ }
+
+ void cancel() {
+ _taskQueue.cancel();
+ }
+
+ bool wait(unsigned long timeout) {
+ return _waitingQueue.wait(timeout);
+ }
+
+ };
+
+ //! Executor job
+ class Worker : public Runnable {
+
+ CountedPtr< ExecutorImpl > _impl;
+
+ public:
+
+ //! Create a Worker that draws upon the given Queue
+ Worker(const CountedPtr< ExecutorImpl >& impl)
+ : _impl(impl) { }
+
+ //! Run until Thread or Queue are canceled
+ void run() {
+
+ _impl->registerThread();
+
+ // Run until the Queue is canceled
+ while(!Thread::canceled()) {
+
+ // Draw tasks from the queue
+ ExecutorTask task( _impl->next() );
+ task->run();
+
+ }
+
+ _impl->unregisterThread();
+
+ }
+
+ }; /* Worker */
+
+
+ //! Helper
+ class Shutdown : public Runnable {
+
+ CountedPtr< ExecutorImpl > _impl;
+
+ public:
+
+ Shutdown(const CountedPtr< ExecutorImpl >& impl)
+ : _impl(impl) { }
+
+ void run() {
+ _impl->cancel();
+ }
+
+ }; /* Shutdown */
+
+ }
+
+ PoolExecutor::PoolExecutor(size_t n)
+ : _impl( new ExecutorImpl() ), _shutdown( new Shutdown(_impl) ) {
+
+ size(n);
+
+ // Request cancelation when main() exits
+ ThreadQueue::instance()->insertShutdownTask(_shutdown);
+
+ }
+
+ PoolExecutor::~PoolExecutor() {
+
+ try {
+
+ /**
+ * If the shutdown task for this executor has not already been
+ * selected to run, then run it locally
+ */
+ if(ThreadQueue::instance()->removeShutdownTask(_shutdown))
+ _shutdown->run();
+
+ } catch(...) { }
+
+ }
+
+ void PoolExecutor::interrupt() {
+ _impl->interrupt();
+ }
+
+ void PoolExecutor::size(size_t n) {
+
+ if(n < 1)
+ throw InvalidOp_Exception();
+
+ for(size_t m = _impl->workers(n); m > 0; --m)
+ Thread t(new Worker(_impl));
+
+ }
+
+ size_t PoolExecutor::size() {
+ return _impl->workers();
+ }
+
+
+ void PoolExecutor::execute(const Task& task) {
+
+ // Enqueue the task, the Queue will reject it with a
+ // Cancelation_Exception if the Executor has been canceled
+ _impl->execute(task);
+
+ }
+
+ void PoolExecutor::cancel() {
+ _impl->cancel();
+ }
+
+ bool PoolExecutor::isCanceled() {
+ return _impl->isCanceled();
+ }
+
+ void PoolExecutor::wait() {
+ _impl->wait(0);
+ }
+
+ bool PoolExecutor::wait(unsigned long timeout) {
+ return _impl->wait(timeout == 0 ? 1 : timeout);
+ }
+
+}
diff --git a/dep/src/zthread/PriorityCondition.cxx b/dep/src/zthread/PriorityCondition.cxx
new file mode 100644
index 00000000000..c43953ff73b
--- /dev/null
+++ b/dep/src/zthread/PriorityCondition.cxx
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "zthread/PriorityCondition.h"
+#include "ConditionImpl.h"
+
+namespace ZThread {
+
+ class PriorityConditionImpl : public ConditionImpl<priority_list> {
+ public:
+ PriorityConditionImpl(Lockable& l) : ConditionImpl<priority_list>(l) {}
+
+ };
+
+ PriorityCondition::PriorityCondition(Lockable& lock) {
+
+ _impl = new PriorityConditionImpl(lock);
+
+ }
+
+
+ PriorityCondition::~PriorityCondition() {
+
+ if(_impl != 0)
+ delete _impl;
+
+ }
+
+
+
+ void PriorityCondition::wait() {
+
+ _impl->wait();
+
+ }
+
+
+
+ bool PriorityCondition::wait(unsigned long ms) {
+
+ return _impl->wait(ms);
+
+ }
+
+
+
+ void PriorityCondition::signal() {
+
+ _impl->signal();
+
+ }
+
+
+ void PriorityCondition::broadcast() {
+
+ _impl->broadcast();
+
+ }
+
+} // namespace ZThread
+
diff --git a/dep/src/zthread/PriorityInheritanceMutex.cxx b/dep/src/zthread/PriorityInheritanceMutex.cxx
new file mode 100644
index 00000000000..108e4a74370
--- /dev/null
+++ b/dep/src/zthread/PriorityInheritanceMutex.cxx
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "zthread/PriorityInheritanceMutex.h"
+#include "MutexImpl.h"
+#include "ThreadOps.h"
+
+
+namespace ZThread {
+
+ class InheritPriorityBehavior : public NullBehavior {
+
+ ThreadImpl* owner;
+ Priority p;
+
+ protected:
+
+ // Temporarily raise the effective priority of the owner
+ inline void waiterArrived(ThreadImpl* impl) {
+
+ Priority q = impl->getPriority();
+ if((int)q > (int)p) {
+
+ ThreadOps::setPriority(impl, p);
+ p = q;
+
+ }
+
+ }
+
+
+ // Note the owners priority
+ inline void ownerAcquired(ThreadImpl* impl) {
+
+ p = impl->getPriority();
+ owner = impl;
+
+ }
+
+ // Restore its original priority
+ inline void ownerReleased(ThreadImpl* impl) {
+
+ if(p > owner->getPriority())
+ ThreadOps::setPriority(impl, impl->getPriority());
+
+ }
+
+ };
+
+ class PriorityInheritanceMutexImpl :
+ public MutexImpl<priority_list, InheritPriorityBehavior> { };
+
+ PriorityInheritanceMutex::PriorityInheritanceMutex() {
+
+ _impl = new PriorityInheritanceMutexImpl();
+
+ }
+
+ PriorityInheritanceMutex::~PriorityInheritanceMutex() {
+
+ if(_impl != 0)
+ delete _impl;
+
+ }
+
+ // P
+ void PriorityInheritanceMutex::acquire() {
+
+ _impl->acquire();
+
+ }
+
+
+ // P
+ bool PriorityInheritanceMutex::tryAcquire(unsigned long ms) {
+
+ return _impl->tryAcquire(ms);
+
+ }
+
+ // V
+ void PriorityInheritanceMutex::release() {
+
+ _impl->release();
+
+ }
+
+
+} // namespace ZThread
+
diff --git a/dep/src/zthread/PriorityMutex.cxx b/dep/src/zthread/PriorityMutex.cxx
new file mode 100644
index 00000000000..c25eaebc46c
--- /dev/null
+++ b/dep/src/zthread/PriorityMutex.cxx
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "zthread/PriorityMutex.h"
+#include "MutexImpl.h"
+#include "ThreadOps.h"
+
+
+namespace ZThread {
+
+ class PriorityMutexImpl : public MutexImpl<priority_list, NullBehavior> { };
+
+ PriorityMutex::PriorityMutex() {
+
+ _impl = new PriorityMutexImpl();
+
+ }
+
+ PriorityMutex::~PriorityMutex() {
+
+ if(_impl != 0)
+ delete _impl;
+
+ }
+
+ // P
+ void PriorityMutex::acquire() {
+
+ _impl->acquire();
+
+ }
+
+
+ // P
+ bool PriorityMutex::tryAcquire(unsigned long ms) {
+
+ return _impl->tryAcquire(ms);
+
+ }
+
+ // V
+ void PriorityMutex::release() {
+
+ _impl->release();
+
+ }
+
+
+} // namespace ZThread
+
diff --git a/dep/src/zthread/PrioritySemaphore.cxx b/dep/src/zthread/PrioritySemaphore.cxx
new file mode 100644
index 00000000000..15138b5f426
--- /dev/null
+++ b/dep/src/zthread/PrioritySemaphore.cxx
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "Debug.h"
+#include "zthread/PrioritySemaphore.h"
+#include "SemaphoreImpl.h"
+
+namespace ZThread {
+
+ class PrioritySemaphoreImpl : public SemaphoreImpl<priority_list> {
+ public:
+
+ PrioritySemaphoreImpl(int count, unsigned int maxCount)
+ : SemaphoreImpl<priority_list>(count, maxCount, true) { }
+
+ };
+
+ /**
+ * Create a new semaphore of a given size with a given count
+ *
+ * @param initialCount initial count to assign this semaphore
+ * @param maxCount maximum size of the semaphore count
+ */
+ PrioritySemaphore::PrioritySemaphore(int count, unsigned int maxCount) {
+
+ _impl = new PrioritySemaphoreImpl(count, maxCount);
+
+ }
+
+ PrioritySemaphore::~PrioritySemaphore() {
+
+ if(_impl != 0)
+ delete _impl;
+
+ }
+
+ void PrioritySemaphore::wait() {
+
+ _impl->acquire();
+
+ }
+
+
+ bool PrioritySemaphore::tryWait(unsigned long ms) {
+
+ return _impl->tryAcquire(ms);
+
+ }
+
+ void PrioritySemaphore::post() {
+
+ _impl->release();
+
+ }
+
+ int PrioritySemaphore::count() {
+
+ return _impl->count();
+
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Locakable compatibility
+ //
+
+ void PrioritySemaphore::acquire() {
+
+ _impl->acquire();
+
+ }
+
+ bool PrioritySemaphore::tryAcquire(unsigned long ms) {
+
+ return _impl->tryAcquire(ms);
+
+
+ }
+
+ void PrioritySemaphore::release() {
+
+ _impl->release();
+
+ }
+
+} // namespace ZThread
diff --git a/dep/src/zthread/RecursiveMutex.cxx b/dep/src/zthread/RecursiveMutex.cxx
new file mode 100644
index 00000000000..57994f55b81
--- /dev/null
+++ b/dep/src/zthread/RecursiveMutex.cxx
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "zthread/RecursiveMutex.h"
+#include "RecursiveMutexImpl.h"
+
+namespace ZThread {
+
+ RecursiveMutex::RecursiveMutex() {
+
+ _impl = new RecursiveMutexImpl();
+
+ }
+
+ RecursiveMutex::~RecursiveMutex() {
+
+ if(_impl != (RecursiveMutexImpl*)0 )
+ delete _impl;
+
+ }
+
+
+ void RecursiveMutex::acquire() {
+
+ _impl->acquire();
+
+ }
+
+
+ bool RecursiveMutex::tryAcquire(unsigned long ms) {
+
+ return _impl->tryAcquire(ms);
+
+ }
+
+ void RecursiveMutex::release() {
+
+ _impl->release();
+
+ }
+
+} // namespace ZThread
diff --git a/dep/src/zthread/RecursiveMutexImpl.cxx b/dep/src/zthread/RecursiveMutexImpl.cxx
new file mode 100644
index 00000000000..41ca03547f8
--- /dev/null
+++ b/dep/src/zthread/RecursiveMutexImpl.cxx
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "Debug.h"
+
+#include "RecursiveMutexImpl.h"
+#include "ThreadImpl.h"
+
+#include "zthread/Guard.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <algorithm>
+
+namespace ZThread {
+
+ /**
+ * Create a new RecursiveMutexImpl
+ *
+ * @exception Initialization_Exception thrown if resources could not be
+ * properly allocated
+ */
+ RecursiveMutexImpl::RecursiveMutexImpl()
+ : _owner(0), _count(0) {
+
+ }
+
+ /**
+ * Destroy this RecursiveMutexImpl and release its resources
+ */
+ RecursiveMutexImpl::~RecursiveMutexImpl() {
+
+#ifndef NDEBUG
+
+ // It is an error to destroy a mutex that has not been released
+ if(_owner != 0) {
+
+ ZTDEBUG("** You are destroying a mutex which was never released. **\n");
+ assert(0); // Destroyed mutex while in use
+
+ }
+
+ if(!_waiters.empty()) {
+
+ ZTDEBUG("** You are destroying a mutex which is blocking %d threads. **\n", _waiters.size());
+ assert(0); // Destroyed mutex while in use
+
+ }
+
+#endif
+
+ }
+
+
+ void RecursiveMutexImpl::acquire() {
+
+ // Get the monitor for the current thread
+ Monitor& m = ThreadImpl::current()->getMonitor();
+ Monitor::STATE state;
+
+ Guard<FastLock> g1(_lock);
+
+ // If there is an entry count and the current thread is
+ // the owner, increment the count and continue.
+ if(_owner == &m)
+ _count++;
+
+ else {
+
+ // Acquire the lock if it is free and there are no waiting threads
+ if(_owner == 0 && _waiters.empty()) {
+
+ assert(_count == 0);
+
+ _owner = &m;
+ _count++;
+
+ } else { // Otherwise, wait()
+
+ _waiters.push_back(&m);
+
+ m.acquire();
+
+ {
+
+ Guard<FastLock, UnlockedScope> g2(g1);
+ state = m.wait();
+
+ }
+
+ m.release();
+
+ // Remove from waiter list, regarless of weather release() is called or
+ // not. The monitor is sticky, so its possible a state 'stuck' from a
+ // previous operation and will leave the wait() w/o release() having
+ // been called.
+ List::iterator i = std::find(_waiters.begin(), _waiters.end(), &m);
+ if(i != _waiters.end())
+ _waiters.erase(i);
+
+ // If awoke due to a notify(), take ownership.
+ switch(state) {
+ case Monitor::SIGNALED:
+
+ assert(_owner == 0);
+ assert(_count == 0);
+
+ _owner = &m;
+ _count++;
+
+ break;
+
+ case Monitor::INTERRUPTED:
+ throw Interrupted_Exception();
+
+ default:
+ throw Synchronization_Exception();
+ }
+
+ }
+
+ }
+
+ }
+
+ bool RecursiveMutexImpl::tryAcquire(unsigned long timeout) {
+
+ // Get the monitor for the current thread
+ Monitor& m = ThreadImpl::current()->getMonitor();
+
+ Guard<FastLock> g1(_lock);
+
+ // If there is an entry count and the current thread is
+ // the owner, increment the count and continue.
+ if(_owner == &m)
+ _count++;
+
+ else {
+
+ // Acquire the lock if it is free and there are no waiting threads
+ if(_owner == 0 && _waiters.empty()) {
+
+ assert(_count == 0);
+
+ _owner = &m;
+ _count++;
+
+ } else { // Otherwise, wait()
+
+ _waiters.push_back(&m);
+
+ Monitor::STATE state = Monitor::TIMEDOUT;
+
+ // Don't bother waiting if the timeout is 0
+ if(timeout) {
+
+ m.acquire();
+
+ {
+
+ Guard<FastLock, UnlockedScope> g2(g1);
+ state = m.wait(timeout);
+
+ }
+
+ m.release();
+
+ }
+
+ // Remove from waiter list, regarless of weather release() is called or
+ // not. The monitor is sticky, so its possible a state 'stuck' from a
+ // previous operation and will leave the wait() w/o release() having
+ // been called.
+ List::iterator i = std::find(_waiters.begin(), _waiters.end(), &m);
+ if(i != _waiters.end())
+ _waiters.erase(i);
+
+ // If awoke due to a notify(), take ownership.
+ switch(state) {
+ case Monitor::SIGNALED:
+
+ assert(_count == 0);
+ assert(_owner == 0);
+
+ _owner = &m;
+ _count++;
+
+ break;
+
+ case Monitor::INTERRUPTED:
+ throw Interrupted_Exception();
+
+ case Monitor::TIMEDOUT:
+ return false;
+
+ default:
+ throw Synchronization_Exception();
+ }
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+ void RecursiveMutexImpl::release() {
+
+ // Get the monitor for the current thread
+ Monitor& m = ThreadImpl::current()->getMonitor();
+
+ Guard<FastLock> g1(_lock);
+
+ // Make sure the operation is valid
+ if(!(_owner == &m))
+ throw InvalidOp_Exception();
+
+ // Update the count, if it has reached 0, wake another waiter.
+ if(--_count == 0) {
+
+ _owner = 0;
+
+ // Try to find a waiter with a backoff & retry scheme
+ for(;;) {
+
+ // Go through the list, attempt to notify() a waiter.
+ for(List::iterator i = _waiters.begin(); i != _waiters.end();) {
+
+ // Try the monitor lock, if it cant be locked skip to the next waiter
+ Monitor* n = *i;
+ if(n->tryAcquire()) {
+
+ // If notify() is not sucessful, it is because the wait() has already
+ // been ended (killed/interrupted/notify'd)
+ bool woke = n->notify();
+ n->release();
+
+ // Once notify() succeeds, return
+ if(woke)
+ return;
+
+ } else ++i;
+
+ }
+
+ if(_waiters.empty())
+ return;
+
+ { // Backoff and try again
+
+ Guard<FastLock, UnlockedScope> g2(g1);
+ ThreadImpl::yield();
+
+ }
+
+ }
+
+ }
+
+ }
+
+} // namespace ZThread
+
+
+
+
diff --git a/dep/src/zthread/RecursiveMutexImpl.h b/dep/src/zthread/RecursiveMutexImpl.h
new file mode 100644
index 00000000000..9e1ae050c5b
--- /dev/null
+++ b/dep/src/zthread/RecursiveMutexImpl.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTRECURSIVEMUTEXIMPL_H__
+#define __ZTRECURSIVEMUTEXIMPL_H__
+
+#include "zthread/Exceptions.h"
+
+#include "FastLock.h"
+
+#include <vector>
+
+namespace ZThread {
+
+ class Monitor;
+
+ /**
+ * @class RecursiveMutexImpl
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T19:58:26-0400>
+ * @version 2.1.6
+ *
+ * This synchronization object provides serialized access
+ * through an acquire/release protocol.
+ */
+ class ZTHREAD_API RecursiveMutexImpl {
+
+ typedef std::vector<Monitor*> List;
+
+ //! List of Events that are waiting for notification
+ List _waiters;
+
+ //! Serialize access to this Mutex
+ FastLock _lock;
+
+ //! Current owning Event object
+ Monitor* _owner;
+
+ //! Entry count
+ size_t _count;
+
+ public:
+
+ RecursiveMutexImpl();
+
+ virtual ~RecursiveMutexImpl();
+
+ void acquire();
+
+ bool tryAcquire(unsigned long);
+
+ void release();
+
+ }; /* RecursiveMutexImpl */
+
+
+};
+
+#endif
diff --git a/dep/src/zthread/Scheduling.h b/dep/src/zthread/Scheduling.h
new file mode 100644
index 00000000000..b12f7fff0b6
--- /dev/null
+++ b/dep/src/zthread/Scheduling.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTSCHEDULING_H__
+#define __ZTSCHEDULING_H__
+
+#include "ThreadImpl.h"
+
+#include <algorithm>
+#include <functional>
+#include <deque>
+#include <utility>
+
+namespace ZThread {
+
+ /**
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T20:01:18-0400>
+ * @version 2.2.0
+ * @class fifo_list
+ */
+ class fifo_list : public std::deque<ThreadImpl*> {
+ public:
+
+ void insert(const value_type& val) { push_back(val); }
+
+ };
+
+ /**
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T20:01:18-0400>
+ * @version 2.2.0
+ * @struct priority_order
+ */
+ struct priority_order : public std::binary_function<ThreadImpl*, ThreadImpl*, bool> {
+
+ std::less<const ThreadImpl*> id;
+
+ bool operator()(const ThreadImpl* t0, const ThreadImpl* t1) const {
+
+ if(t0->getPriority() > t1->getPriority())
+ return true;
+
+ else if (t0->getPriority() < t1->getPriority())
+ return false;
+
+ return id(t0, t1);
+
+ }
+
+ };
+
+
+ /**
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T20:01:18-0400>
+ * @version 2.2.0
+ * @class priority_list
+ */
+ class priority_list : public std::deque<ThreadImpl*> {
+
+ priority_order comp;
+
+ public:
+
+ void insert(const value_type& val) {
+
+ push_back(val);
+ std::sort(begin(), end(), comp);
+
+ }
+
+ };
+
+} // namespace ZThread
+
+#endif // __ZTSCHEDULING_H__
diff --git a/dep/src/zthread/Semaphore.cxx b/dep/src/zthread/Semaphore.cxx
new file mode 100644
index 00000000000..b9fb8d0f613
--- /dev/null
+++ b/dep/src/zthread/Semaphore.cxx
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "zthread/Semaphore.h"
+#include "SemaphoreImpl.h"
+
+namespace ZThread {
+
+ /**
+ * Create a new semaphore of a given size with a given count
+ *
+ * @param initialCount initial count to assign this semaphore
+ * @param maxCount maximum size of the semaphore count
+ */
+ Semaphore::Semaphore(int count, unsigned int maxCount) {
+
+ _impl = new FifoSemaphoreImpl(count, maxCount, true);
+
+ }
+
+ Semaphore::~Semaphore() {
+
+ if(_impl != 0)
+ delete _impl;
+
+ }
+
+ void Semaphore::wait() {
+
+ _impl->acquire();
+
+ }
+
+
+ bool Semaphore::tryWait(unsigned long ms) {
+
+ return _impl->tryAcquire(ms);
+
+ }
+
+ void Semaphore::post() {
+
+ _impl->release();
+
+ }
+
+ int Semaphore::count() {
+
+ return _impl->count();
+
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Locakable compatibility
+ //
+
+ void Semaphore::acquire() {
+
+ _impl->acquire();
+
+ }
+
+ bool Semaphore::tryAcquire(unsigned long ms) {
+
+ return _impl->tryAcquire(ms);
+
+
+ }
+
+ void Semaphore::release() {
+
+ _impl->release();
+
+ }
+
+} // namespace ZThread
+
+
+
+
+
+
diff --git a/dep/src/zthread/SemaphoreImpl.h b/dep/src/zthread/SemaphoreImpl.h
new file mode 100644
index 00000000000..086c4333fd0
--- /dev/null
+++ b/dep/src/zthread/SemaphoreImpl.h
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTSEMAPHOREIMPL_H__
+#define __ZTSEMAPHOREIMPL_H__
+
+#include "zthread/Guard.h"
+
+#include "Debug.h"
+#include "FastLock.h"
+#include "Scheduling.h"
+
+#include <assert.h>
+
+namespace ZThread {
+
+ class Monitor;
+
+ /**
+ * @class SemaphoreImpl
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T20:03:20-0400>
+ * @version 2.2.11
+ *
+ * The SemaphoreImpl template allows how waiter lists are sorted
+ * to be parameteized
+ */
+ template <typename List>
+ class SemaphoreImpl {
+
+ //! List of waiting events
+ List _waiters;
+
+ //! Serialize access to this object
+ FastLock _lock;
+
+ //! Current count
+ volatile int _count;
+
+ //! Maximum count if any
+ volatile int _maxCount;
+
+ //! Flag for bounded or unbounded count
+ volatile bool _checked;
+
+ //! Entry count
+ volatile int _entryCount;
+
+ public:
+
+
+ /**
+ * Create a new SemaphoreImpl. Initialzes one pthreads mutex for
+ * internal use.
+ *
+ * @exception Initialization_Exception thrown if resources could not be
+ * properly allocated
+ */
+ SemaphoreImpl(int count, unsigned int maxCount, bool checked)
+ : _count(count), _maxCount(maxCount), _checked(checked), _entryCount(0) { }
+
+
+ ~SemaphoreImpl();
+
+ void acquire();
+
+ void release();
+
+ bool tryAcquire(unsigned long timeout);
+
+ int count();
+
+ };
+
+
+ /**
+ * Destroy this SemaphoreImpl and release its resources.
+ */
+ template <typename List>
+ SemaphoreImpl<List>::~SemaphoreImpl() {
+
+#ifndef NDEBUG
+
+ if(!_waiters.empty()) {
+
+ ZTDEBUG("** You are destroying a semaphore which is blocking %d threads. **\n", _waiters.size());
+ assert(0); // Destroyed semaphore while in use
+
+ }
+
+#endif
+
+ }
+
+
+ /**
+ * Get the count for the Semaphore
+ *
+ * @return int
+ */
+ template <typename List>
+ int SemaphoreImpl<List>::count() {
+
+ Guard<FastLock> g(_lock);
+ return _count;
+
+ }
+
+ /**
+ * Decrement the count, blocking when that count becomes 0 or less.
+ *
+ * @exception Interrupted_Exception thrown when the caller status is interrupted
+ * @exception Synchronization_Exception thrown if there is some other error.
+ */
+ template <typename List>
+ void SemaphoreImpl<List>::acquire() {
+
+ // Get the monitor for the current thread
+ ThreadImpl* self = ThreadImpl::current();
+ Monitor& m = self->getMonitor();
+
+ Monitor::STATE state;
+
+ Guard<FastLock> g1(_lock);
+
+ // Update the count without waiting if possible.
+ if(_count > 0 && _entryCount == 0)
+ _count--;
+
+ // Otherwise, wait() for the lock by placing the waiter in the list
+ else {
+
+ ++_entryCount;
+ _waiters.insert(self);
+
+ m.acquire();
+
+ {
+
+ Guard<FastLock, UnlockedScope> g2(g1);
+ state = m.wait();
+
+ }
+
+ m.release();
+
+ // Remove from waiter list, regarless of weather release() is called or
+ // not. The monitor is sticky, so its possible a state 'stuck' from a
+ // previous operation and will leave the wait() w/o release() having
+ // been called.
+ typename List::iterator i = std::find(_waiters.begin(), _waiters.end(), self);
+ if(i != _waiters.end())
+ _waiters.erase(i);
+
+ --_entryCount;
+
+ switch(state) {
+ // If awoke due to a notify(), update the count
+ case Monitor::SIGNALED:
+
+ _count--;
+ break;
+
+ case Monitor::INTERRUPTED:
+ throw Interrupted_Exception();
+
+ default:
+ throw Synchronization_Exception();
+ }
+
+ }
+
+ }
+
+ /**
+ * Decrement the count, blocking when it that count is 0 or less. If the timeout
+ * expires before the count is raise above 0, the thread will stop blocking
+ * and return.
+ *
+ * @exception Interrupted_Exception thrown when the caller status is interrupted
+ * @exception Synchronization_Exception thrown if there is some other error.
+ */
+ template <typename List>
+ bool SemaphoreImpl<List>::tryAcquire(unsigned long timeout) {
+
+ // Get the monitor for the current thread
+ ThreadImpl* self = ThreadImpl::current();
+ Monitor& m = self->getMonitor();
+
+ Guard<FastLock> g1(_lock);
+
+ // Update the count without waiting if possible.
+ if(_count > 0 && _entryCount == 0)
+ _count--;
+
+ // Otherwise, wait() for the lock by placing the waiter in the list
+ else {
+
+ ++_entryCount;
+ _waiters.push_back(self);
+
+ Monitor::STATE state = Monitor::TIMEDOUT;
+
+ // Don't bother waiting if the timeout is 0
+ if(timeout) {
+
+ m.acquire();
+
+ {
+
+ Guard<FastLock, UnlockedScope> g2(g1);
+ state = m.wait(timeout);
+
+ }
+
+ m.release();
+
+ }
+
+ // Remove from waiter list, regarless of weather release() is called or
+ // not. The monitor is sticky, so its possible a state 'stuck' from a
+ // previous operation and will leave the wait() w/o release() having
+ // been called.
+ typename List::iterator i = std::find(_waiters.begin(), _waiters.end(), self);
+ if(i != _waiters.end())
+ _waiters.erase(i);
+
+ --_entryCount;
+
+ switch(state) {
+ // If awoke due to a notify(), update the count
+ case Monitor::SIGNALED:
+
+ _count--;
+ break;
+
+ case Monitor::INTERRUPTED:
+ throw Interrupted_Exception();
+
+ case Monitor::TIMEDOUT:
+ return false;
+
+ default:
+ throw Synchronization_Exception();
+ }
+
+ }
+
+ return true;
+
+ }
+
+ /**
+ * Increment the count and release a waiter if there are any. If the semaphore
+ * is checked, then an exception will be raised if the maximum count is about to
+ * be exceeded.
+ *
+ * @exception InvalidOp_Exception thrown if the maximum count is exceeded while
+ * the checked flag is set.
+ */
+ template <typename List>
+ void SemaphoreImpl<List>::release() {
+
+ Guard<FastLock> g1(_lock);
+
+ // Make sure the operation is valid
+ if(_checked && _count == _maxCount)
+ throw InvalidOp_Exception();
+
+ // Increment the count
+ _count++;
+
+ // Try to find a waiter with a backoff & retry scheme
+ for(;;) {
+
+ // Go through the list, attempt to notify() a waiter.
+ for(typename List::iterator i = _waiters.begin(); i != _waiters.end();) {
+
+ // Try the monitor lock, if it cant be locked skip to the next waiter
+ ThreadImpl* impl = *i;
+ Monitor& m = impl->getMonitor();
+
+ if(m.tryAcquire()) {
+
+ // Notify the monitor & remove from the waiter list so time isn't
+ // wasted checking it again.
+ i = _waiters.erase(i);
+
+ // If notify() is not sucessful, it is because the wait() has already
+ // been ended (killed/interrupted/notify'd)
+ bool woke = m.notify();
+
+ m.release();
+
+ // Once notify() succeeds, return
+ if(woke)
+ return;
+
+ } else ++i;
+
+ }
+
+ if(_waiters.empty())
+ return;
+
+ { // Backoff and try again
+
+ Guard<FastLock, UnlockedScope> g2(g1);
+ ThreadImpl::yield();
+
+ }
+
+ }
+
+ }
+
+ class FifoSemaphoreImpl : public SemaphoreImpl<fifo_list> {
+ public:
+
+ FifoSemaphoreImpl(int count, unsigned int maxCount, bool checked)
+ /* throw(Synchronization_Exception) */
+ : SemaphoreImpl<fifo_list>(count, maxCount, checked) { }
+
+ };
+
+
+} // namespace ZThread
+
+#endif // __ZTSEMAPHOREIMPL_H__
diff --git a/dep/src/zthread/State.h b/dep/src/zthread/State.h
new file mode 100644
index 00000000000..85279f4bde8
--- /dev/null
+++ b/dep/src/zthread/State.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTSTATE_H__
+#define __ZTSTATE_H__
+
+namespace ZThread {
+
+/**
+ * @class State
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T20:04:01-0400>
+ * @version 2.2.1
+ *
+ * Class to encapsulate the current state of the threads life-cycle.
+ */
+class State {
+ public:
+
+ //! Various states
+ typedef enum { REFERENCE, IDLE, RUNNING, JOINED } STATE;
+
+ /**
+ * Create State with the given flag set.
+ */
+ State(STATE initialState) : _state(initialState) {}
+
+ /**
+ * Test for the IDLE state. No task has yet run.
+ */
+ bool isIdle() const {
+ return _state == IDLE;
+ }
+
+ /**
+ * Test for the JOINED state. A task has completed and
+ * the thread is join()ed.
+ *
+ * @return bool
+ */
+ bool isJoined() const {
+ return _state == JOINED;
+ }
+
+ /**
+ * Test for the RUNNING state. A task is in progress.
+ *
+ * @return bool
+ */
+ bool isRunning() const {
+ return _state == RUNNING;
+ }
+
+ /**
+ * Test for the REFERENCE state. A task is in progress but not
+ * under control of this library.
+ *
+ * @return bool
+ */
+ bool isReference() const {
+ return _state == REFERENCE;
+ }
+
+ /**
+ * Transition to the IDLE state.
+ *
+ * @return bool true if successful
+ */
+ bool setIdle() {
+
+ if(_state != RUNNING)
+ return false;
+
+ _state = IDLE;
+ return true;
+
+ }
+
+ /**
+ * Transition to the RUNNING state.
+ *
+ * @return bool true if successful
+ */
+ bool setRunning() {
+
+ if(_state != IDLE)
+ return false;
+
+ _state = RUNNING;
+ return true;
+
+ }
+
+ /**
+ * Transition to the REFERENCE state.
+ *
+ * @return bool true if successful
+ */
+ bool setReference() {
+
+ if(_state != IDLE)
+ return false;
+
+ _state = REFERENCE;
+ return true;
+
+ }
+
+
+ /**
+ * Transition to the JOINED state.
+ *
+ * @return bool true if successful
+ */
+ bool setJoined() {
+
+ _state = JOINED;
+ return true;
+
+ }
+
+ private:
+
+ //! Current state
+ STATE _state;
+
+};
+
+
+};
+
+#endif
diff --git a/dep/src/zthread/Status.h b/dep/src/zthread/Status.h
new file mode 100644
index 00000000000..4735e352861
--- /dev/null
+++ b/dep/src/zthread/Status.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTBLOCKINGSTATE_H__
+#define __ZTBLOCKINGSTATE_H__
+
+#include <assert.h>
+
+namespace ZThread {
+
+ /**
+ * @class Status
+ * @version 2.3.0
+ *
+ * A Status is associated with each Thread's Monitor. Monitors rely on a
+ * Status object for providing information that will affect a blocking operations.
+ */
+ class Status {
+ public:
+ //! Aggregate of pending status changes
+ volatile unsigned short _pending;
+
+ //! Interest mask
+ volatile unsigned short _mask;
+
+ public:
+
+ //! State for the monitor
+ typedef enum {
+
+ // Default
+ INVALID = 0x00,
+
+ // Valid states
+ SIGNALED = 0x01,
+ INTERRUPTED = 0x02,
+ TIMEDOUT = 0x04,
+ CANCELED = 0x08,
+
+ // Mask
+ ANYTHING = (~INVALID & ~CANCELED)
+
+ } STATE;
+
+ Status() : _pending((unsigned short)INVALID), _mask((unsigned short)ANYTHING) { }
+
+ /**
+ * Set the mask for the STATE's that next() will report.
+ * STATE's not covered by the interest mask can still be
+ * set, they just aren't reported until the mask is changed
+ * to cover that STATE.
+ *
+ * @param STATE
+ * @pre accessed ONLY by the owning thread.
+ */
+ void interest(STATE mask) {
+ _mask = static_cast<unsigned short>(mask);
+ }
+
+ bool masked(STATE mask) {
+ return (_mask & static_cast<unsigned short>(mask)) == 0;
+ }
+
+ /**
+ * Return true if next() will return a STATE covered
+ * by the current interest mask and by the mask given
+ * to this function.
+ *
+ * @param unsigned short
+ * @pre accessed ONLY by the owning thread.
+ */
+ bool pending(unsigned short mask) {
+
+ assert(mask != INVALID);
+ return ((_pending & _mask) & mask) != INVALID;
+
+ }
+
+ /**
+ * Check the state without the interest mask.
+ *
+ * @param state
+ * @return true if the flag is set
+ * @pre access must be serial
+ */
+ bool examine(STATE state) {
+ return (_pending & static_cast<unsigned short>(state)) != INVALID;
+ }
+
+ /**
+ * Add the flags to the current state.
+ *
+ * @param interest - the flags to add to the current state.
+ * @pre access must be serial
+ */
+ void push(STATE interest) {
+ _pending |= interest;
+ }
+
+ /**
+ * Clear the flags from the current state
+ *
+ * @param interest - the flags to clear from the current state.
+ * @pre access must be serial
+ */
+ void clear(STATE interest) {
+
+ assert(interest != INVALID);
+ assert(interest != ANYTHING);
+ assert(interest != CANCELED);
+
+ _pending &= ~interest;
+
+ }
+
+ /**
+ * Get the next state from set that has accumulated. The order STATES are
+ * reported in is SIGNALED, TIMEOUT, or INTERRUPTED. Setting the
+ * intrest mask allows certain state to be selectively ignored for
+ * a time - but not lost. The states will become visible again as soon
+ * as the interest mask is changed appropriately. The interest mask is
+ * generally used to create uninterruptable waits (waiting for threads
+ * to start, reacquiring a conditions predicate lock, etc)
+ *
+ * @return STATE
+ * @pre access must be serial
+ */
+ STATE next() {
+
+ STATE state = INVALID;
+
+ if(((_pending & _mask) & SIGNALED) != 0) {
+
+ // Absorb the timeout if it happens when a signal
+ // is available at the same time
+ _pending &= ~(SIGNALED|TIMEDOUT);
+ state = SIGNALED;
+
+ } else if(((_pending & _mask) & TIMEDOUT) != 0) {
+
+ _pending &= ~TIMEDOUT;
+ state = TIMEDOUT;
+
+ } else if(((_pending & _mask) & INTERRUPTED) != 0) {
+
+ _pending &= ~INTERRUPTED;
+ state = INTERRUPTED;
+
+ }
+
+ assert(state != INVALID);
+ return state;
+
+ }
+
+ };
+
+}; // namespace ZThread
+
+#endif
diff --git a/dep/src/zthread/SynchronousExecutor.cxx b/dep/src/zthread/SynchronousExecutor.cxx
new file mode 100644
index 00000000000..0dc75b5f676
--- /dev/null
+++ b/dep/src/zthread/SynchronousExecutor.cxx
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "zthread/SynchronousExecutor.h"
+
+namespace ZThread {
+
+ SynchronousExecutor::SynchronousExecutor()
+ : _canceled(false) {}
+
+ SynchronousExecutor::~SynchronousExecutor() {
+ }
+
+ void SynchronousExecutor::cancel() {
+
+ Guard<Mutex> g(_lock);
+ _canceled = true;
+
+ }
+
+ bool SynchronousExecutor::isCanceled() {
+
+ Guard<Mutex> g(_lock);
+ return _canceled;
+
+ }
+
+ void SynchronousExecutor::interrupt() {
+ }
+
+ void SynchronousExecutor::execute(const Task& task) {
+
+ // Canceled Executors will not accept new tasks, quick
+ // check to avoid excessive locking in the canceled state
+ if(_canceled)
+ throw Cancellation_Exception();
+
+ Guard<Mutex> g(_lock);
+
+ if(_canceled) // Double check
+ throw Cancellation_Exception();
+
+ // Run the task.
+ Task(task)->run();
+
+ }
+
+ void SynchronousExecutor::wait() {
+
+ if(Thread::interrupted())
+ throw Interrupted_Exception();
+
+ Guard<Mutex> g(_lock);
+
+ }
+
+ /**
+ * @see Executor::wait(unsigned long)
+ */
+ bool SynchronousExecutor::wait(unsigned long) {
+
+ if(Thread::interrupted())
+ throw Interrupted_Exception();
+
+ Guard<Mutex> g(_lock);
+ return true;
+
+ }
+
+
+}
diff --git a/dep/src/zthread/TSS.h b/dep/src/zthread/TSS.h
new file mode 100644
index 00000000000..ed29230ec57
--- /dev/null
+++ b/dep/src/zthread/TSS.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTTSSSELECT_H__
+#define __ZTTSSSELECT_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+// Select the correct TSS implementation based on
+// what the compilation environment has defined
+
+#if defined(ZT_POSIX)
+
+#include "posix/TSS.h"
+
+#elif defined(ZT_WIN32) || defined(ZT_WIN9X)
+
+#include "win32/TSS.h"
+
+#elif defined(ZT_MACOS)
+
+#include "macos/TSS.h"
+
+#endif
+
+
+#ifndef __ZTTSS_H__
+#error "No TSS implementation could be selected"
+#endif
+
+#endif // __ZTTSSSELECT_H__
diff --git a/dep/src/zthread/Thread.cxx b/dep/src/zthread/Thread.cxx
new file mode 100644
index 00000000000..25cde79969c
--- /dev/null
+++ b/dep/src/zthread/Thread.cxx
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "zthread/Runnable.h"
+#include "zthread/Thread.h"
+#include "ThreadImpl.h"
+
+namespace ZThread {
+
+
+ Thread::Thread()
+ : _impl( ThreadImpl::current() ) {
+
+ // ThreadImpl's start out life with a reference count
+ // of one, and the they are added to the ThreadQueue.
+ _impl->addReference();
+
+ }
+
+ Thread::Thread(const Task& task, bool autoCancel)
+ : _impl( new ThreadImpl(task, autoCancel) ) {
+
+ _impl->addReference();
+
+ }
+
+ bool Thread::operator==(const Thread& t) const {
+ return (t._impl == _impl);
+ }
+
+ Thread::~Thread() {
+
+ _impl->delReference();
+
+ }
+
+ void Thread::wait() {
+ _impl->join(0);
+ }
+
+ bool Thread::wait(unsigned long timeout) {
+
+ return _impl->join(timeout == 0 ? 1 : timeout);
+
+ }
+
+ bool Thread::interrupted() {
+
+ return ThreadImpl::current()->isInterrupted();
+
+ }
+
+
+ bool Thread::canceled() {
+
+ return ThreadImpl::current()->isCanceled();
+
+ }
+
+ void Thread::setPriority(Priority n) {
+
+ _impl->setPriority(n);
+
+ }
+
+
+ Priority Thread::getPriority() {
+
+ return _impl->getPriority();
+
+ }
+
+ bool Thread::interrupt() {
+
+ return _impl->interrupt();
+
+ }
+
+ void Thread::cancel() {
+
+ if(ThreadImpl::current() == _impl)
+ throw InvalidOp_Exception();
+
+ _impl->cancel();
+
+ }
+
+ bool Thread::isCanceled() {
+
+ return _impl->isCanceled();
+
+ }
+
+
+ void Thread::sleep(unsigned long ms) {
+
+ ThreadImpl::sleep(ms);
+
+ }
+
+
+ void Thread::yield() {
+
+ ThreadImpl::yield();
+
+ }
+
+} // namespace ZThread
diff --git a/dep/src/zthread/ThreadImpl.cxx b/dep/src/zthread/ThreadImpl.cxx
new file mode 100644
index 00000000000..c7c22883b5e
--- /dev/null
+++ b/dep/src/zthread/ThreadImpl.cxx
@@ -0,0 +1,470 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "Debug.h"
+
+#include "zthread/Runnable.h"
+#include "ThreadImpl.h"
+#include "ThreadQueue.h"
+#include "DeferredInterruptionScope.h"
+
+#include <assert.h>
+
+namespace ZThread {
+
+ TSS<ThreadImpl*> ThreadImpl::_threadMap;
+
+ namespace {
+
+ class Launcher : public Runnable {
+
+ ThreadImpl* x;
+ ThreadImpl* y;
+ Task z;
+
+ public:
+
+ Launcher(ThreadImpl* a, ThreadImpl* b, const Task& c) : x(a), y(b), z(c) {}
+
+ void run() {
+ y->dispatch(x,y,z);
+ }
+
+ };
+
+ }
+
+ ThreadImpl::ThreadImpl()
+ : _state(State::REFERENCE), _priority(Medium), _autoCancel(false) {
+
+ ZTDEBUG("Reference thread created.\n");
+
+ }
+
+ ThreadImpl::ThreadImpl(const Task& task, bool autoCancel)
+ : _state(State::IDLE), _priority(Medium), _autoCancel(autoCancel) {
+
+ ZTDEBUG("User thread created.\n");
+
+ start(task);
+
+ }
+
+
+ ThreadImpl::~ThreadImpl() {
+
+ _tls.clear();
+
+ if(isActive()) {
+
+ ZTDEBUG("You are destroying an executing thread!\n");
+ abort();
+
+ }
+
+ ZTDEBUG("Thread destroyed.\n");
+
+ }
+
+ Monitor& ThreadImpl::getMonitor() {
+ return _monitor;
+ }
+
+ void ThreadImpl::cancel(bool autoCancel) {
+ if(!autoCancel || _autoCancel)
+ _monitor.cancel();
+ }
+
+ bool ThreadImpl::interrupt() {
+ return _monitor.interrupt();
+ }
+
+ bool ThreadImpl::isInterrupted() {
+ return _monitor.isInterrupted();
+ }
+
+ bool ThreadImpl::isCanceled() {
+ return _monitor.isCanceled();
+ }
+
+ Priority ThreadImpl::getPriority() const {
+ return _priority;
+ }
+
+
+
+ bool ThreadImpl::isReference() {
+ return _state.isReference();
+ }
+
+ /**
+ * Join the thread, blocking the caller until it is interrupted or until
+ * the thread represented by this object exits.
+ *
+ * Reference threads are not under the control of ZThreads and cannot be
+ * joined.
+ */
+ bool ThreadImpl::join(unsigned long timeout) {
+
+ // Serial access to this ThreadImpl's state
+ Guard<Monitor> g1(_monitor);
+
+ // Make sure a thread is not trying to join() itself.
+ if(ThreadOps::isCurrent(this))
+ throw Deadlock_Exception("Cannot join self.");
+
+ // Reference threads can't be joined.
+ if(_state.isReference())
+ throw InvalidOp_Exception("Can not join this thread.");
+
+ /*
+
+ TODO: Insert cyclic join check.
+
+ */
+
+ // If the task has not completed yet, wait for completion
+ if(!_state.isJoined()) {
+
+ // Add the current thread to the joiner list
+ ThreadImpl* impl = current();
+ _joiners.push_back(impl);
+
+ Monitor::STATE result;
+
+ { // Release this ThreadImpl's lock while the joiner sleeps
+
+ _monitor.release();
+ Guard<Monitor> g3(impl->getMonitor());
+
+ result = impl->_monitor.wait(timeout);
+
+ _monitor.acquire();
+
+ }
+
+ // Update the joiner list
+ List::iterator i = std::find(_joiners.begin(), _joiners.end(), impl);
+ if(i != _joiners.end())
+ _joiners.erase(i);
+
+
+ switch(result) {
+
+ case Monitor::TIMEDOUT:
+ return false;
+
+ case Monitor::INTERRUPTED:
+ throw Interrupted_Exception();
+
+ default:
+ break;
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+
+ /**
+ * Translate the priority into a pthread value, and update the thread priority.
+ *
+ * This is not available on all platforms, and probably works differently
+ * the platforms that do support it. Pthreads does not have very portable
+ * priority support as far I am aware.
+ *
+ * If SCHED_OTHER is not supported priority values are still set but
+ * dont not actually in affect anything.
+ *
+ * @param prio PRIORITY value
+ *
+ * @exception Killed_Exception thrown by KILLED threads.
+ * @exception InvalidOp_Exception thrown by IDLE, JOINING or JOINED threads.
+ */
+ void ThreadImpl::setPriority(Priority p) {
+
+ Guard<Monitor> g(_monitor);
+
+ // Only set the native priority when the thread is running
+ if(_state.isRunning())
+ ThreadOps::setPriority(this, p);
+
+ _priority = p;
+
+ }
+
+
+ /**
+ * Test the state Monitor of this thread to determine if the thread
+ * is an active thread created by zthreads.
+ *
+ * @return bool indicating the activity of the thread.
+ */
+ bool ThreadImpl::isActive() {
+
+ Guard<Monitor> g(_monitor);
+ return _state.isRunning();
+
+ }
+
+
+ /**
+ * Get a reference to an implmenetation that maps to the current thread.
+ * Accomplished by checking the TLS map. This will always return a valid
+ * ThreadImpl instance.
+ *
+ * @return ThreadImpl* current implementation that maps to the
+ * executing thread.
+ */
+ ThreadImpl* ThreadImpl::current() {
+
+ // Get the ThreadImpl previously mapped onto the executing thread.
+ ThreadImpl* impl = _threadMap.get();
+
+ // Create a reference thread for any threads that have been 'discovered'
+ // because they are not created by ZThreads.
+ if(impl == 0) {
+
+ // Create a ThreadImpl to represent this thread.
+ impl = new ThreadImpl();
+ impl->_state.setReference();
+
+ ThreadOps::activate(impl);
+
+ // Map a reference thread and insert it into the queue
+ _threadMap.set(impl);
+
+ ThreadQueue::instance()->insertReferenceThread(impl);
+
+ }
+
+ assert(impl != 0);
+ return impl;
+
+ }
+
+ /**
+ * Make current thread sleep for the given number of milliseconds.
+ * This sleep can be interrupt()ed.
+ *
+ * @param ms timeout for the sleep.
+ *
+ * @post the calling thread is blocked by waiting on the internal condition
+ * variable. This can be signaled in the monitor of an interrupt
+ */
+ void ThreadImpl::sleep(unsigned long ms) {
+
+ // Make sleep()ing for 0 milliseconds equivalent to a yield.
+ if(ms == 0) {
+
+ yield();
+ return;
+
+ }
+
+ // Get the monitor for the current thread
+ Monitor& monitor = current()->getMonitor();
+
+ // Acquire that threads Monitor with a Guard
+ Guard<Monitor> g(monitor);
+
+ for(;;) {
+
+ switch(monitor.wait(ms)) {
+
+ case Monitor::INTERRUPTED:
+ throw Interrupted_Exception();
+
+ default:
+ return;
+
+ }
+
+ }
+
+ }
+
+
+ /**
+ * Yield the current timeslice to another thread.
+ * If sched_yield() is available it is used.
+ * Otherwise, the state Monitor for this thread is used to simiulate a
+ * yield by blocking for 1 millisecond, which should give the
+ * scheduler a chance to schedule another thread.
+ */
+ void ThreadImpl::yield() {
+
+ // Try to yield with the native operation. If it fails, then
+ // simulate with a short wait() on the monitor.
+ if(!ThreadOps::yield()) {
+
+ // Get the monitor for the current thread
+ Monitor& monitor = current()->getMonitor();
+
+ // Attempt a wait().
+ Guard<Monitor> g(monitor);
+ monitor.wait(1);
+
+ }
+
+ }
+
+ void ThreadImpl::start(const Task& task) {
+
+ Guard<Monitor> g1(_monitor);
+
+ // A Thread must be idle in order to be eligable to run a task.
+ if(!_state.isIdle())
+ throw InvalidOp_Exception("Thread is not idle.");
+
+ _state.setRunning();
+
+ // Spawn a new thread, blocking the parent (current) thread until
+ // the child starts.
+
+ ThreadImpl* parent = current();
+ Launcher launch(parent, this, task);
+
+ // Attempt to start the child thread
+ Guard<Monitor> g2(parent->_monitor);
+
+ if(!spawn(&launch)) {
+
+ // Return to the idle state & report the error if it doesn't work out.
+ _state.setIdle();
+ throw Synchronization_Exception();
+
+
+ }
+
+ // Wait, uninterruptably, for the child's signal. The parent thread
+ // still can be interrupted and killed; it just won't take effect
+ // until the child has started.
+
+ Guard<Monitor, DeferredInterruptionScope> g3(parent->_monitor);
+
+ if(parent->_monitor.wait() != Monitor::SIGNALED) {
+ assert(0);
+ }
+
+
+ }
+
+
+ void ThreadImpl::dispatch(ThreadImpl* parent, ThreadImpl* impl, Task task) {
+
+ // Map the implementation object onto the running thread.
+ _threadMap.set(impl);
+
+ // Update the reference count on a ThreadImpl before the 'Thread'
+ // that owns it can go out of scope (by signaling the parent)
+ impl->addReference();
+
+ // Update the priority of the thread
+ if(parent->_state.isReference())
+ ThreadOps::setPriority(impl,
+ parent->_state.isReference() ? impl->_priority : parent->_priority);
+
+ // Inherit ThreadLocal values from the parent
+ typedef ThreadLocalMap::const_iterator It;
+
+ for(It i = parent->getThreadLocalMap().begin(); i != parent->getThreadLocalMap().end(); ++i)
+ if( (i->second)->isInheritable() )
+ impl->getThreadLocalMap()[ i->first ] = (i->second)->clone();
+
+ // Insert a user-thread mapping
+ ThreadQueue::instance()->insertUserThread(impl);
+ // Wake the parent once the thread is setup
+ parent->_monitor.notify();
+
+ ZTDEBUG("Thread starting...\n");
+
+ // not catch exceptions, let program terminate
+ //try {
+
+ task->run();
+
+ //} catch(...) {
+
+ // Result of running a task that threw an exception.
+ // ZTDEBUG("The task has thrown an unhandled exception\n");
+ //assert(0); // UQ1: Go to debugger...
+
+ //}
+
+ ZTDEBUG("Thread joining...\n");
+
+ { // Update the state of the thread
+
+ Guard<Monitor> g(impl->_monitor);
+ impl->_state.setJoined();
+
+ // Wake the joiners that will be easy to join first
+ for(List::iterator i = impl->_joiners.begin(); i != impl->_joiners.end();) {
+
+ ThreadImpl* joiner = *i;
+ Monitor& m = joiner->getMonitor();
+
+ if(m.tryAcquire()) {
+
+ m.notify();
+ m.release();
+
+ i = impl->_joiners.erase(i);
+
+ } else
+ ++i;
+
+ }
+
+ // Wake the joiners that might take a while next
+ for(List::iterator i = impl->_joiners.begin(); i != impl->_joiners.end(); ++i) {
+
+ ThreadImpl* joiner = *i;
+ Monitor& m = joiner->getMonitor();
+
+ m.acquire();
+ m.notify();
+ m.release();
+
+ }
+
+ }
+
+ ZTDEBUG("Thread exiting...\n");
+
+ // Insert a pending-thread mapping, allowing the resources to be reclaimed
+ ThreadQueue::instance()->insertPendingThread(impl);
+
+ // Cleanup ThreadLocal values
+ impl->getThreadLocalMap().clear();
+
+ // Update the reference count allowing it to be destroyed
+ impl->delReference();
+
+ }
+
+
+} // namespace ZThread
diff --git a/dep/src/zthread/ThreadImpl.h b/dep/src/zthread/ThreadImpl.h
new file mode 100644
index 00000000000..ae2c8f23960
--- /dev/null
+++ b/dep/src/zthread/ThreadImpl.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTTHREADIMPL_H__
+#define __ZTTHREADIMPL_H__
+
+#include "zthread/ThreadLocalImpl.h"
+#include "zthread/Thread.h"
+#include "zthread/Exceptions.h"
+#include "IntrusivePtr.h"
+
+#include "Monitor.h"
+#include "TSS.h"
+#include "ThreadOps.h"
+#include "State.h"
+
+#include <map>
+#include <deque>
+
+namespace ZThread {
+
+/**
+ * @class ThreadImpl
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-27T13:39:03-0400>
+ * @version 2.3.0
+ */
+class ThreadImpl : public IntrusivePtr<ThreadImpl, FastLock>, public ThreadOps {
+
+ typedef std::deque<ThreadImpl*> List;
+
+ //! TSS to store implementation to current thread mapping.
+ static TSS<ThreadImpl*> _threadMap;
+
+ //! The Monitor for controlling this thread
+ Monitor _monitor;
+
+ //! Current state for the thread
+ State _state;
+
+ //! Joining threads
+ List _joiners;
+
+ public:
+
+ typedef std::map<const ThreadLocalImpl*, ThreadLocalImpl::ValuePtr > ThreadLocalMap;
+
+ private:
+
+ ThreadLocalMap _tls;
+
+ //! Cached thread priority
+ Priority _priority;
+
+ //! Request cancel() when main() goes out of scope
+ bool _autoCancel;
+
+ void start(const Task& task);
+
+ public:
+
+ ThreadImpl();
+
+ ThreadImpl(const Task&, bool);
+
+ ~ThreadImpl();
+
+ Monitor& getMonitor();
+
+ void cancel(bool autoCancel = false);
+
+ bool interrupt();
+
+ bool isInterrupted();
+
+ bool isCanceled();
+
+ Priority getPriority() const;
+
+ // ThreadLocalMap& getThreadLocalMap();
+ ThreadLocalMap& getThreadLocalMap() { return _tls; }
+
+ bool join(unsigned long);
+
+ void setPriority(Priority);
+
+ bool isActive();
+
+ bool isReference();
+
+ static void sleep(unsigned long);
+
+ static void yield();
+
+ static ThreadImpl* current();
+
+ static void dispatch(ThreadImpl*, ThreadImpl*, Task);
+
+};
+
+} // namespace ZThread
+
+#endif // __ZTTHREADIMPL_H__
diff --git a/dep/src/zthread/ThreadLocalImpl.cxx b/dep/src/zthread/ThreadLocalImpl.cxx
new file mode 100644
index 00000000000..25682e66325
--- /dev/null
+++ b/dep/src/zthread/ThreadLocalImpl.cxx
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "zthread/ThreadLocalImpl.h"
+#include "ThreadImpl.h"
+
+namespace ZThread {
+
+ ThreadLocalImpl::ThreadLocalImpl() {}
+
+ ThreadLocalImpl::~ThreadLocalImpl() {}
+
+ void ThreadLocalImpl::clearAll() {
+
+ typedef ThreadImpl::ThreadLocalMap Map;
+ Map& m = ThreadImpl::current()->getThreadLocalMap();
+
+ m.clear();
+
+ }
+
+ void ThreadLocalImpl::clear() const {
+
+ typedef ThreadImpl::ThreadLocalMap Map;
+ Map& m = ThreadImpl::current()->getThreadLocalMap();
+
+ Map::iterator i = m.find(this);
+ if(i != m.end())
+ m.erase(i);
+
+ }
+
+ ThreadLocalImpl::ValuePtr ThreadLocalImpl::value( ValuePtr(*pfn)() ) const {
+
+ typedef ThreadImpl::ThreadLocalMap Map;
+ Map& m = ThreadImpl::current()->getThreadLocalMap();
+
+ Map::iterator i = m.find(this);
+ if(i != m.end())
+ return i->second;
+
+ m[ this ] = ValuePtr( pfn() );
+ return m[ this ];
+
+ }
+
+} // namespace ZThread
diff --git a/dep/src/zthread/ThreadOps.cxx b/dep/src/zthread/ThreadOps.cxx
new file mode 100644
index 00000000000..53a3e4457bc
--- /dev/null
+++ b/dep/src/zthread/ThreadOps.cxx
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTTHREADOPSIMPLSELECT_CXX__
+#define __ZTTHREADOPSIMPLSELECT_CXX__
+
+#include "ThreadOps.h"
+
+// This file will select an implementation for a ThreadOps based on
+// what ThreadOps.h selects. This method is for selecting the
+// source files, to improve portability. Currently, the project is
+// based on the autoconf tool-set, which doesn't support conditional
+// compilation well. Additionally, this should make the library
+// easier to port since its working around conditional compilation
+// by using C++ features and people won't have to fiddle around with
+// their make tool as much to compile the source
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+// Check for sched_yield()
+
+#if !defined(HAVE_SCHED_YIELD)
+# if defined(HAVE_UNISTD_H)
+# include <unistd.h>
+# if defined(_POSIX_PRIORITY_SCHEDULING)
+# define HAVE_SCHED_YIELD 1
+# endif
+# endif
+#endif
+
+#include ZT_THREADOPS_IMPLEMENTATION
+
+#endif
diff --git a/dep/src/zthread/ThreadOps.h b/dep/src/zthread/ThreadOps.h
new file mode 100644
index 00000000000..eef9f3c6e31
--- /dev/null
+++ b/dep/src/zthread/ThreadOps.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTTHREADOPSSELECT_H__
+#define __ZTTHREADOPSSELECT_H__
+
+#include "zthread/Config.h"
+
+#if defined(ZT_THREADOPS_IMPLEMENTATION)
+# error "Reserved symbol defined"
+#endif
+
+
+// Select the correct implementation
+#if defined(ZT_POSIX)
+
+# include "posix/ThreadOps.h"
+# define ZT_THREADOPS_IMPLEMENTATION "posix/ThreadOps.cxx"
+
+#elif defined(ZT_WIN32) || defined(ZT_WIN9X)
+
+// Visual C provides the _beginthreadex function, other compilers
+// might not have this if they don't use Microsoft's C runtime.
+// _beginthreadex is similar to in effect defining REENTRANT on a
+// POSIX system. CreateThreadEx doesn't use reentrant parts of the
+// Microsfot C runtime, but if your not using that runtime, no problem.
+
+# if !defined(HAVE_BEGINTHREADEX)
+# if defined(_MSC_VER)
+# define HAVE_BEGINTHREADEX
+# endif
+# endif
+
+# include "win32/ThreadOps.h"
+# define ZT_THREADOPS_IMPLEMENTATION "win32/ThreadOps.cxx"
+
+#elif defined(ZT_MACOS)
+
+# include "macos/ThreadOps.h"
+# define ZT_THREADOPS_IMPLEMENTATION "macos/ThreadOps.cxx"
+
+#endif
+
+#ifndef __ZTTHREADOPS_H__
+#error "No ThreadOps implementation could be selected"
+#endif
+
+#endif // __ZTTHREADOPSSELECT_H__
diff --git a/dep/src/zthread/ThreadQueue.cxx b/dep/src/zthread/ThreadQueue.cxx
new file mode 100644
index 00000000000..02349504641
--- /dev/null
+++ b/dep/src/zthread/ThreadQueue.cxx
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "DeferredInterruptionScope.h"
+#include "Debug.h"
+#include "ThreadImpl.h"
+#include "ThreadQueue.h"
+
+#include <algorithm>
+#include <deque>
+
+namespace ZThread {
+
+ ThreadQueue::ThreadQueue()
+ : _waiter(0) {
+
+ ZTDEBUG("ThreadQueue created\n");
+
+ }
+
+ ThreadQueue::~ThreadQueue() {
+
+ ZTDEBUG("ThreadQueue waiting on remaining threads...\n");
+
+ // Ensure the current thread is mapped.
+ ThreadImpl* impl = ThreadImpl::current();
+
+ bool threadsWaiting = false;
+ bool waitRequired = false;
+
+ {
+
+ TaskList shutdownTasks;
+
+ { // Check the queue to for pending user threads
+
+ Guard<FastLock> g(_lock);
+
+ waitRequired = (_waiter != (ThreadImpl*)1);
+ _waiter = impl;
+
+ threadsWaiting = !_userThreads.empty() || !_pendingThreads.empty();
+
+ //ZTDEBUG("Wait required: %d\n", waitRequired);
+ //ZTDEBUG("Threads waiting: %d\n", threadsWaiting);
+
+ // Auto-cancel any active threads at the time main() goes out of scope
+ // "force" a gentle exit from the executing tasks; eventually the user-
+ // threads will transition into pending-threads
+ pollUserThreads();
+
+ // Remove all the tasks about to be run from the task list so an indication
+ // can be given to threads calling removeShutdownTask() too late.
+ std::remove_copy(_shutdownTasks.begin(),
+ _shutdownTasks.end(),
+ std::back_inserter(shutdownTasks),
+ Task((Runnable*)0));
+
+ //ZTDEBUG("Threads waiting: %d\n", threadsWaiting);
+
+ }
+
+ // Execute the shutdown tasks
+ for(TaskList::iterator i = shutdownTasks.begin(); i != shutdownTasks.end(); ++i) {
+ try {
+ (*i)->run();
+ } catch(...) { }
+ }
+
+ }
+
+ // Wait for all the users threads to get into the appropriate state
+ if(threadsWaiting) {
+
+
+ Monitor& m = _waiter->getMonitor();
+
+ // Defer interruption while this thread waits for a signal from
+ // the last pending user thread
+ Guard<Monitor, CompoundScope<DeferredInterruptionScope, LockedScope> > g(m);
+ //ZTDEBUG("Threads waiting: %d %d\n", _userThreads.size(), _pendingThreads.size());
+
+ // Avoid race-condition where the last threads are done with thier tasks, but
+ // only begin the final part of the clean up phase after this destructor begins
+ // to run. Takes advantage of the fact that if all remaining threads have transitioned
+ // into a pending state by the time execution reaches this point, then there is no
+ // need to wait.
+ waitRequired = waitRequired && !(_userThreads.empty() && !_pendingThreads.empty());
+
+ // Reference threads can't be interrupted or otherwise
+ // manipulated. The only signal this monitor will receive
+ // at this point will be from the last pending thread.
+ if(waitRequired && m.wait() != Monitor::SIGNALED) {
+ assert(0);
+ }
+
+ // Join those pending threads
+ pollPendingThreads();
+
+ }
+
+ // Clean up the reference threads
+ pollReferenceThreads();
+
+ ZTDEBUG("ThreadQueue destroyed\n");
+
+ }
+
+
+ void ThreadQueue::insertPendingThread(ThreadImpl* impl) {
+ ZTDEBUG("insertPendingThread()\n");
+ Guard<FastLock> g(_lock);
+
+ // Move from the user-thread list to the pending-thread list
+ ThreadList::iterator i = std::find(_userThreads.begin(), _userThreads.end(), impl);
+ if(i != _userThreads.end())
+ _userThreads.erase(i);
+
+ _pendingThreads.push_back(impl);
+
+ // Wake the main thread,if its waiting, when the last pending-thread becomes available;
+ // Otherwise, take note that no wait for pending threads to finish is needed
+ if(_userThreads.empty())
+ if(_waiter && _waiter != (ThreadImpl*)1)
+ _waiter->getMonitor().notify();
+ else
+ _waiter = (ThreadImpl*)!_waiter;
+
+ ZTDEBUG("1 pending-thread added.\n");
+
+ }
+
+ void ThreadQueue::insertReferenceThread(ThreadImpl* impl) {
+
+ Guard<FastLock> g(_lock);
+ _referenceThreads.push_back(impl);
+
+ ZTDEBUG("1 reference-thread added.\n");
+
+ }
+
+ void ThreadQueue::insertUserThread(ThreadImpl* impl) {
+
+ Guard<FastLock> g(_lock);
+ _userThreads.push_back(impl);
+
+ // Reclaim pending-threads
+ pollPendingThreads();
+
+ // Auto-cancel threads that are started when main() is out of scope
+ if(_waiter)
+ impl->cancel(true);
+
+ ZTDEBUG("1 user-thread added.\n");
+
+ }
+
+
+ void ThreadQueue::pollPendingThreads() {
+
+ ZTDEBUG("pollPendingThreads()\n");
+
+ for(ThreadList::iterator i = _pendingThreads.begin(); i != _pendingThreads.end();) {
+
+ ThreadImpl* impl = (ThreadImpl*)*i;
+ ThreadOps::join(impl);
+
+ impl->delReference();
+
+ i = _pendingThreads.erase(i);
+
+ ZTDEBUG("1 pending-thread reclaimed.\n");
+
+ }
+
+ }
+
+ void ThreadQueue::pollReferenceThreads() {
+
+ ZTDEBUG("pollReferenceThreads()\n");
+
+ for(ThreadList::iterator i = _referenceThreads.begin(); i != _referenceThreads.end(); ++i) {
+
+ ThreadImpl* impl = (ThreadImpl*)*i;
+ impl->delReference();
+
+ ZTDEBUG("1 reference-thread reclaimed.\n");
+
+ }
+
+ }
+
+ void ThreadQueue::pollUserThreads() {
+
+ ZTDEBUG("pollUserThreads()\n");
+
+ for(ThreadList::iterator i = _userThreads.begin(); i != _userThreads.end(); ++i) {
+
+ ThreadImpl* impl = *i;
+ impl->cancel(true);
+
+ ZTDEBUG("1 user-thread reclaimed.\n");
+
+ }
+
+ }
+
+ void ThreadQueue::insertShutdownTask(Task& task) {
+
+ bool hasWaiter = false;
+
+ {
+
+ Guard<FastLock> g(_lock);
+
+ // Execute later when the ThreadQueue is destroyed
+ if( !(hasWaiter = (_waiter != 0)) ) {
+
+ _shutdownTasks.push_back(task);
+ //ZTDEBUG("1 shutdown task added. %d\n", _shutdownTasks.size());
+
+ }
+
+ }
+
+ // Execute immediately if things are shutting down
+ if(hasWaiter)
+ task->run();
+
+ }
+
+ bool ThreadQueue::removeShutdownTask(const Task& task) {
+
+ Guard<FastLock> g(_lock);
+
+ TaskList::iterator i = std::find(_shutdownTasks.begin(), _shutdownTasks.end(), task);
+ bool removed = (i != _shutdownTasks.end());
+ if(removed)
+ _shutdownTasks.erase(i);
+
+ //ZTDEBUG("1 shutdown task removed (%d)-%d\n", removed, _shutdownTasks.size());
+
+ return removed;
+
+ }
+
+};
diff --git a/dep/src/zthread/ThreadQueue.h b/dep/src/zthread/ThreadQueue.h
new file mode 100644
index 00000000000..044f8263026
--- /dev/null
+++ b/dep/src/zthread/ThreadQueue.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTTHREADQUEUE_H__
+#define __ZTTHREADQUEUE_H__
+
+#include "zthread/Singleton.h"
+#include "zthread/Guard.h"
+#include "FastLock.h"
+
+
+namespace ZThread {
+
+ class ThreadImpl;
+
+ /**
+ * @class ThreadQueue
+ * @version 2.3.0
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-27T20:52:05-0400>
+ *
+ * A ThreadQueue accumulates references to user and reference threads.
+ * These are threads that are running outside the scope of the Thread
+ * object that created them. ZThreads doesn't have a central manager for
+ * all threads (partly why I renamed the ThreadManager to someting more
+ * appropriate). Instead, ZThreads will discover threads it did not create
+ * and create a reference thread that allows ZThreads to interact with it.
+ * Non user threads that are created by the user never have to touch the
+ * ThreadQueue.
+ */
+ class ThreadQueue : public Singleton<ThreadQueue, StaticInstantiation> {
+
+ typedef std::deque<ThreadImpl*> ThreadList;
+ typedef std::deque<Task> TaskList;
+
+ //! Managed thread lists
+ ThreadList _pendingThreads;
+ ThreadList _referenceThreads;
+ ThreadList _userThreads;
+
+ //! Shutdown handlers
+ TaskList _shutdownTasks;
+
+ //! Serilize access to the thread list
+ FastLock _lock;
+
+ //! Reference thread waiting to cleanup any user & reference threads
+ ThreadImpl* _waiter;
+
+ public:
+
+ ThreadQueue();
+
+ /**
+ * The thread destroys a ThreadQueue will be a reference thread,
+ * probably the main thread; but it could be another thread that
+ * started and loaded the library.
+ */
+ ~ThreadQueue();
+
+ /**
+ * Insert a user-thread into the queue. User-threads are inserted as they
+ * begin thier task. Once that task completes, user-threads are automatically
+ * transitioned to pending-threads via <i>insertPendingThread()</i>.
+ *
+ * User-threads are known to be executing thier tasks and will be cancel()ed
+ * as the ThreadQueue is destroyed when main() goes out of scope. This sends
+ * a request to the task to complete soon. Once the task exits, the thread is
+ * transitioned to pending-thread status.
+ */
+ void insertUserThread(ThreadImpl*);
+
+ /**
+ * Insert a pending-thread into the queue.
+ *
+ * Pending-threads are known to have completed thier tasks and thier
+ * resources are reclaimed (lazily) as more threads are started or as the
+ * ThreadQueue is destroyed.
+ */
+ void insertPendingThread(ThreadImpl*);
+
+
+ /**
+ * Insert reference thread. Reference threads are not removed until
+ * the ThreadQueue goes out of scope.
+ */
+ void insertReferenceThread(ThreadImpl*);
+
+ /**
+ * Insert a task to be run before threads are joined.
+ * Any items inserted after the ThreadQueue desctructor has begun to
+ * execute will be run() immediately.
+ */
+ void insertShutdownTask(Task&);
+
+ /**
+ * Remove an existing shutdown task.
+ */
+ bool removeShutdownTask(const Task&);
+
+ private:
+
+ void pollPendingThreads();
+
+ void pollUserThreads();
+
+ void pollReferenceThreads();
+
+ };
+
+
+} // namespace ZThread
+
+
+#endif // __ZTTHREADQUEUE_H__
diff --git a/dep/src/zthread/ThreadedExecutor.cxx b/dep/src/zthread/ThreadedExecutor.cxx
new file mode 100644
index 00000000000..44a213e8daa
--- /dev/null
+++ b/dep/src/zthread/ThreadedExecutor.cxx
@@ -0,0 +1,464 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "zthread/ThreadedExecutor.h"
+#include "zthread/Guard.h"
+#include "zthread/FastMutex.h"
+#include "zthread/Time.h"
+
+#include "ThreadImpl.h"
+
+namespace ZThread {
+
+ namespace {
+
+ //!
+ class WaiterQueue {
+
+ typedef std::deque<ThreadImpl*> ThreadList;
+
+ typedef struct group_t {
+ size_t id;
+ size_t count;
+ ThreadList waiters;
+ group_t(size_t n) : id(n), count(0) {}
+ } Group;
+
+ typedef std::deque<Group> GroupList;
+
+ //! Predicate to find a specific group
+ struct by_id : public std::unary_function<bool, Group> {
+ size_t id;
+ by_id(size_t n) : id(n) {}
+ bool operator()(const Group& grp) {
+ return grp.id == id;
+ }
+ };
+
+ //! Functor to count groups
+ struct counter : public std::unary_function<void, Group> {
+ size_t count;
+ counter() : count(0) {}
+ void operator()(const Group& grp) { count += grp.count; }
+ operator size_t() { return count; }
+ };
+
+ FastMutex _lock;
+ GroupList _list;
+ size_t _id;
+ size_t _generation;
+
+ public:
+
+ WaiterQueue() : _id(0), _generation(0) {
+ // At least one empty-group exists
+ _list.push_back( Group(_id++) );
+ }
+
+ /**
+ * Insert the current thread into the current waiter list
+ *
+ * @pre At least one empty group exists
+ * @post At least one empty group exists
+ */
+ bool wait(unsigned long timeout) {
+
+ ThreadImpl* self = ThreadImpl::current();
+ Monitor& m = self->getMonitor();
+
+ Monitor::STATE state;
+
+ Guard<Lockable> g1(_lock);
+
+ // At least one empty-group exists
+ assert(!_list.empty());
+
+ // Return w/o waiting if there are no executing tasks
+ if((size_t)std::for_each(_list.begin(), _list.end(), counter()) < 1)
+ return true;
+
+ // Update the waiter list for the active group
+ _list.back().waiters.push_back(self);
+ size_t n = _list.back().id;
+
+ m.acquire();
+
+ {
+
+ Guard<Lockable, UnlockedScope> g2(g1);
+ state = timeout == 0 ? m.wait() : m.wait(timeout);
+
+ }
+
+ m.release();
+
+ // If awoke due to a reason other than the last task in the group 'n' completing,
+ // then then find the group 'self' is waiting in
+ GroupList::iterator i = std::find_if(_list.begin(), _list.end(), by_id(n));
+ if(i != _list.end()) {
+
+ // Remove 'self' from that list if it is still a member
+ ThreadList::iterator j = std::find(i->waiters.begin(), i->waiters.end(), self);
+ if(j != i->waiters.end())
+ i->waiters.erase(j);
+
+ }
+
+ // At least one empty-group exists
+ assert(!_list.empty());
+
+ switch(state) {
+ case Monitor::SIGNALED:
+ break;
+ case Monitor::TIMEDOUT:
+ return false;
+ case Monitor::INTERRUPTED:
+ throw Interrupted_Exception();
+ default:
+ throw Synchronization_Exception();
+ }
+
+ return true;
+
+ }
+
+ /**
+ * Increment the active group count
+ *
+ * @pre at least 1 empty group exists
+ * @post at least 1 non-empty group exists
+ */
+ std::pair<size_t, size_t> increment() {
+
+ Guard<FastMutex> g(_lock);
+
+ // At least one empty-group exists
+ assert(!_list.empty());
+
+ GroupList::iterator i = --_list.end();
+ size_t n = i->id;
+
+ if(i == _list.end()) {
+
+ // A group should never have been removed until
+ // the final task in that group completed
+ assert(0);
+
+ }
+
+ i->count++;
+
+ // When the active group is being incremented, insert a new active group
+ // to replace it if there were waiting threads
+ if(i == --_list.end() && !i->waiters.empty())
+ _list.push_back(Group(_id++));
+
+ // At least 1 non-empty group exists
+ assert((size_t)std::for_each(_list.begin(), _list.end(), counter()) > 0);
+
+ return std::make_pair(n, _generation);
+
+ }
+
+
+ /**
+ * Decrease the count for the group with the given id.
+ *
+ * @param n group id
+ *
+ * @pre At least 1 non-empty group exists
+ * @post At least 1 empty group exists
+ */
+ void decrement(size_t n) {
+
+ Guard<FastMutex> g1(_lock);
+
+ // At least 1 non-empty group exists
+ assert((size_t)std::for_each(_list.begin(), _list.end(), counter()) > 0);
+
+ // Find the requested group
+ GroupList::iterator i = std::find_if(_list.begin(), _list.end(), by_id(n));
+ if(i == _list.end()) {
+
+ // A group should never have been removed until
+ // the final task in that group completed
+ assert(0);
+
+ }
+
+ // Decrease the count for tasks in this group,
+ if(--i->count == 0 && i == _list.begin()) {
+
+ do {
+
+ // When the first group completes, wake all waiters for every
+ // group, starting from the first until a group that is not
+ // complete is reached
+
+ /*
+ // Don't remove the empty active group
+ if(i == --_list.end() && i->waiters.empty())
+ break;
+ */
+
+ if( awaken(*i) ) {
+
+ // If all waiters were awakened, remove the group
+ i = _list.erase(i);
+
+ } else {
+
+ {
+
+ // Otherwise, unlock and yield allowing the waiter
+ // lists to be updated if other threads are busy
+ Guard<FastLock, UnlockedScope> g2(g1);
+ ThreadImpl::yield();
+
+ }
+
+ i = _list.begin();
+
+ }
+
+ } while(i != _list.end() && i->count == 0);
+
+ // Ensure that an active group exists
+ if(_list.empty())
+ _list.push_back( Group(++_id) );
+
+ }
+
+ // At least one group exists
+ assert(!_list.empty());
+
+ }
+
+ /**
+ */
+ size_t generation(bool next = false) {
+
+ Guard<FastMutex> g(_lock);
+ return next ? _generation++ : _generation;
+
+ }
+
+ private:
+
+ /**
+ * Awaken all the waiters remaining in the given group
+ *
+ * @return
+ * - true if all the waiting threads were successfully awakened.
+ * - false if there were one or more threads that could not be awakened.
+ */
+ bool awaken(Group& grp) {
+
+ // Go through the waiter list in the given group;
+ for(ThreadList::iterator i = grp.waiters.begin(); i != grp.waiters.end();) {
+
+ ThreadImpl* impl = *i;
+ Monitor& m = impl->getMonitor();
+
+ // Try the monitor lock, if it cant be locked skip to the next waiter
+ if(m.tryAcquire()) {
+
+ // Notify the monitor & remove from the waiter list so time isn't
+ // wasted checking it again.
+ i = grp.waiters.erase(i);
+
+ // Try to wake the waiter, it doesn't matter if this is successful
+ // or not (only fails when the monitor is already going to stop waiting).
+ m.notify();
+ m.release();
+
+ } else ++i;
+
+ }
+
+ return grp.waiters.empty();
+
+ }
+
+ };
+
+ //! Synchronization point for the Executor
+ class ExecutorImpl {
+
+ typedef std::deque<ThreadImpl*> ThreadList;
+
+ bool _canceled;
+ FastMutex _lock;
+
+ //! Worker threads
+ ThreadList _threads;
+
+ WaiterQueue _queue;
+
+ public:
+
+ ExecutorImpl() : _canceled(false) {}
+
+ WaiterQueue& getWaiterQueue() {
+ return _queue;
+ }
+
+ void registerThread(size_t generation) {
+
+ // Interrupt slow starting threads
+ if(getWaiterQueue().generation() != generation)
+ ThreadImpl::current()->interrupt();
+
+ // Enqueue for possible future interrupt()
+ else {
+
+ Guard<FastMutex> g(_lock);
+ _threads.push_back( ThreadImpl::current() );
+
+ }
+
+ }
+
+ void unregisterThread() {
+
+ Guard<FastMutex> g(_lock);
+ std::remove(_threads.begin(), _threads.end(), ThreadImpl::current() );
+
+ }
+
+ void cancel() {
+
+ Guard<FastMutex> g(_lock);
+ _canceled = true;
+
+ }
+
+ bool isCanceled() {
+
+ if(_canceled)
+ return true;
+
+ Guard<FastMutex> g(_lock);
+ return _canceled;
+
+ }
+
+ void interrupt() {
+
+ Guard<FastMutex> g(_lock);
+
+ // Interrupt all the registered threads
+ for(ThreadList::iterator i = _threads.begin(); i != _threads.end(); ++i)
+ (*i)->interrupt();
+
+ // Bump the generation up, ensuring slow starting threads get this interrupt
+ getWaiterQueue().generation( true );
+
+ }
+
+ }; /* ExecutorImpl */
+
+ //! Wrap a generation and a group around a task
+ class Worker : public Runnable {
+
+ CountedPtr< ExecutorImpl > _impl;
+ Task _task;
+
+ size_t _generation;
+ size_t _group;
+
+ public:
+
+ Worker(const CountedPtr< ExecutorImpl >& impl, const Task& task)
+ : _impl(impl), _task(task) {
+
+ std::pair<size_t, size_t> pr( _impl->getWaiterQueue().increment() );
+
+ _group = pr.first;
+ _generation = pr.second;
+
+ }
+
+ size_t group() const {
+ return _group;
+ }
+
+ size_t generation() const {
+ return _generation;
+ }
+
+ void run() {
+
+ // Register this thread once its begun; the generation is used to ensure
+ // threads that are slow starting are properly interrupted
+
+ _impl->registerThread( generation() );
+
+ try {
+ _task->run();
+ } catch(...) {
+ /* consume the exceptions the work propogates */
+ }
+
+ _impl->getWaiterQueue().decrement( group() );
+
+ // Unregister this thread
+
+ _impl->unregisterThread();
+
+ }
+
+ }; /* Worker */
+
+ }
+
+ ThreadedExecutor::ThreadedExecutor() : _impl(new ExecutorImpl) {}
+
+ ThreadedExecutor::~ThreadedExecutor() {}
+
+ void ThreadedExecutor::execute(const Task& task) {
+
+ Thread t( new Worker(_impl, task) );
+
+ }
+
+ void ThreadedExecutor::interrupt() {
+ _impl->interrupt();
+ }
+
+ void ThreadedExecutor::cancel() {
+ _impl->cancel();
+ }
+
+ bool ThreadedExecutor::isCanceled() {
+ return _impl->isCanceled();
+ }
+
+ void ThreadedExecutor::wait() {
+ _impl->getWaiterQueue().wait(0);
+ }
+
+ bool ThreadedExecutor::wait(unsigned long timeout) {
+ return _impl->getWaiterQueue().wait(timeout == 0 ? 1 : timeout);
+ }
+
+}
diff --git a/dep/src/zthread/Time.cxx b/dep/src/zthread/Time.cxx
new file mode 100644
index 00000000000..2409d93cb79
--- /dev/null
+++ b/dep/src/zthread/Time.cxx
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "zthread/Time.h"
+#include "TimeStrategy.h"
+
+
+using namespace ZThread;
+
+Time::Time() {
+
+ // System startup time
+ static TimeStrategy firstHelper;
+ TimeStrategy helper;
+
+ Time then(firstHelper.seconds(), firstHelper.milliseconds());
+ Time now(helper.seconds(), helper.milliseconds());
+
+ now -= then;
+
+ _seconds = now.seconds();
+ _milliseconds = now.milliseconds();
+
+}
+
+
diff --git a/dep/src/zthread/TimeStrategy.h b/dep/src/zthread/TimeStrategy.h
new file mode 100644
index 00000000000..0b9ad1e22ba
--- /dev/null
+++ b/dep/src/zthread/TimeStrategy.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTTIMESELECT_H__
+#define __ZTTIMESELECT_H__
+
+#include "zthread/Config.h"
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+// Select the correct TimeOps implementation based on
+// what the complilation environment has defined
+
+#ifndef HAVE_FTIME
+
+# if defined(ZT_WIN32) || defined(ZT_WIN9X)
+
+# if !defined(__MWERKS__)
+
+# ifndef HAVE_FTIME
+# define HAVE_FTIME
+# endif
+
+# elif defined(__MWERKS__)
+
+# ifndef HAVE_PERFORMANCECOUNTER
+# define HAVE_PERFORMANCECOUNTER
+# endif
+
+# endif
+
+# endif
+
+#endif
+
+// Some systems require this to complete the definition of timespec
+// which is needed by pthreads.
+#if defined(HAVE_SYS_TYPES_H)
+# include <sys/types.h>
+#endif
+
+#if defined(ZT_MACOS)
+
+# include "macos/UpTimeStrategy.h"
+
+#elif defined(HAVE_PERFORMANCECOUNTER)
+
+# include "win32/PerformanceCounterStrategy.h"
+
+#elif defined(HAVE_FTIME)
+
+# include "posix/FtimeStrategy.h"
+
+#else
+
+# include "posix/GetTimeOfDayStrategy.h"
+
+#endif
+
+
+#ifndef __ZTTIMESTRATEGY_H__
+#error "No TimeStrategy implementation could be selected"
+#endif
+
+#endif // __ZTTIMESELECT_H__
diff --git a/dep/src/zthread/config.h b/dep/src/zthread/config.h
new file mode 100644
index 00000000000..0b630dcc36c
--- /dev/null
+++ b/dep/src/zthread/config.h
@@ -0,0 +1,95 @@
+/* src/config.h. Generated by configure. */
+/* src/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Defined if <bits/atomicity.h> is usable */
+/* #undef HAVE_ATOMIC_GCC */
+
+/* Defined if <asm/atomic.h> is usable */
+/* #undef HAVE_ATOMIC_LINUX */
+
+/* _beginthreadex() */
+/* #undef HAVE_BEGINTHREADEX */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* defined when pthreads is available */
+#define HAVE_POSIX_THREADS
+
+/* Defined if pthread_keycreate() is available */
+/* #undef HAVE_PTHREADKEYCREATE */
+
+/* Defined if pthread_key_create() is available */
+#define HAVE_PTHREADKEY_CREATE
+
+/* Defined if pthread_yield() is available */
+#define HAVE_PTHREAD_YIELD
+
+/* Defined if -lrt is needed for RT scheduling */
+#define HAVE_SCHED_RT
+
+/* Defined if sched_yield() is available */
+#define HAVE_SCHED_YIELD
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Name of package */
+//#define PACKAGE "ZThread"
+
+/* Define to the address where bug reports for this package should be sent. */
+//#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+//#define PACKAGE_NAME ""
+
+/* Define to the full name and version of this package. */
+//#define PACKAGE_STRING ""
+
+/* Define to the one symbol short name of this package. */
+//#define PACKAGE_TARNAME ""
+
+/* Define to the version of this package. */
+//#define PACKAGE_VERSION ""
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Defined if ftime()/_ftime() is usable */
+#define SYSTEM_FTIME ftime
+
+/* Version number of package */
+//#define VERSION "2.3.2"
+
+/* No interrupt() hooks */
+/* #undef ZTHREAD_DISABLE_INTERRUPT */
+
+/* No OS priority support */
+/* #undef ZTHREAD_DISABLE_PRIORITY */
diff --git a/dep/src/zthread/linux/AtomicCount.cxx b/dep/src/zthread/linux/AtomicCount.cxx
new file mode 100644
index 00000000000..28c2381c3b4
--- /dev/null
+++ b/dep/src/zthread/linux/AtomicCount.cxx
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTATOMICCOUNTIMPL_H__
+#define __ZTATOMICCOUNTIMPL_H__
+
+#include <asm/atomic.h>
+#include <assert.h>
+
+namespace ZThread {
+
+typedef struct atomic_count_t {
+
+ atomic_t count;
+
+ atomic_count_t() {
+ atomic_t init = ATOMIC_INIT(0);
+ count = init;
+ }
+
+ ~atomic_count_t() {
+ assert(atomic_read(&count) == 0);
+ }
+
+} ATOMIC_COUNT;
+
+
+AtomicCount::AtomicCount() {
+
+ _value = reinterpret_cast<void*>(new ATOMIC_COUNT);
+
+}
+
+AtomicCount::~AtomicCount() {
+
+ delete reinterpret_cast<ATOMIC_COUNT*>(_value);
+
+}
+
+void AtomicCount::increment() {
+
+ atomic_inc(&reinterpret_cast<ATOMIC_COUNT*>(_value)->count);
+
+}
+
+bool AtomicCount::decrement() {
+
+ return atomic_dec_and_test(&reinterpret_cast<ATOMIC_COUNT*>(_value)->count);
+
+}
+
+};
+
+#endif // __ZTATOMICCOUNTIMPL_H__
diff --git a/dep/src/zthread/linux/AtomicFastLock.h b/dep/src/zthread/linux/AtomicFastLock.h
new file mode 100644
index 00000000000..b9aa1babcd6
--- /dev/null
+++ b/dep/src/zthread/linux/AtomicFastLock.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTFASTLOCK_H__
+#define __ZTFASTLOCK_H__
+
+#include "zthread/NonCopyable.h"
+#include "../ThreadOps.h"
+#include <assert.h>
+#include <asm/atomic.h>
+
+#if !defined(NDEBUG)
+# include <pthread.h>
+#endif
+
+namespace ZThread {
+
+/**
+ * @class FastLock
+ *
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T23:27:03-0400>
+ * @version 2.2.0
+ *
+ * This implementation of a FastLock uses the atomic operations that
+ * linux provides with its kernel sources. This demonstrates how to implement
+ * a spinlock with a decrement and test primative.
+ */
+class FastLock : private NonCopyable {
+
+ atomic_t _value;
+
+#if !defined(NDEBUG)
+ pthread_t _owner;
+#endif
+
+public:
+
+ inline FastLock() {
+
+ atomic_t tmp = ATOMIC_INIT(1);
+ _value = tmp;
+
+ }
+
+ inline ~FastLock() {
+
+ assert(atomic_read(&_value) == 1);
+ assert(_owner == 0);
+
+ }
+
+ inline void acquire() {
+
+ while(!atomic_dec_and_test(&_value)) {
+
+ atomic_inc(&_value);
+ ThreadOps::yield();
+
+ }
+
+#if !defined(NDEBUG)
+ _owner = pthread_self();
+#endif
+ }
+
+ inline void release() {
+
+#if !defined(NDEBUG)
+ assert(pthread_equal(_owner, pthread_self()) != 0);
+#endif
+
+ atomic_inc(&_value);
+ _owner = 0;
+
+ }
+
+ inline bool tryAcquire(unsigned long timeout=0) {
+
+ bool wasLocked = atomic_dec_and_test(&_value);
+ if(!wasLocked)
+ atomic_inc(&_value);
+
+#if !defined(NDEBUG)
+ if(wasLocked)
+ _owner = pthread_self();
+#endif
+
+ return wasLocked;
+
+ }
+
+}; /* FastLock */
+
+
+} // namespace ZThread
+
+#endif
diff --git a/dep/src/zthread/linux/FastRecursiveLock.h b/dep/src/zthread/linux/FastRecursiveLock.h
new file mode 100644
index 00000000000..d253652cb53
--- /dev/null
+++ b/dep/src/zthread/linux/FastRecursiveLock.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTFASTRECURSIVELOCK_H__
+#define __ZTFASTRECURSIVELOCK_H__
+
+#include "zthread/NonCopyable.h"
+#include <pthread.h>
+
+namespace ZThread {
+
+/**
+ * @class FastRecursiveLock
+ *
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T23:27:14-0400>
+ * @version 2.2.0
+ *
+ * This implementation of a FastRecursiveLock uses the recursive mutex
+ * that linux pthreads provides.
+ */
+class FastRecursiveLock : private NonCopyable {
+
+ pthread_mutex_t _mtx;
+
+public:
+
+ inline FastRecursiveLock() {
+
+ static const pthread_mutexattr_t attr = { PTHREAD_MUTEX_RECURSIVE_NP };
+ pthread_mutex_init(&_mtx, &attr);
+
+ }
+
+ inline ~FastRecursiveLock() {
+
+ pthread_mutex_destroy(&_mtx);
+
+ }
+
+ inline void acquire() {
+
+ pthread_mutex_lock(&_mtx);
+
+ }
+
+ inline void release() {
+
+ pthread_mutex_unlock(&_mtx);
+
+ }
+
+ inline bool tryAcquire(unsigned long timeout=0) {
+
+ return (pthread_mutex_trylock(&_mtx) == 0);
+
+ }
+
+}; /* FastRecursiveLock */
+
+
+} // namespace ZThread
+
+#endif
diff --git a/dep/src/zthread/macos/FastLock.h b/dep/src/zthread/macos/FastLock.h
new file mode 100644
index 00000000000..bae5c482903
--- /dev/null
+++ b/dep/src/zthread/macos/FastLock.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTFASTLOCK_H__
+#define __ZTFASTLOCK_H__
+
+#include "zthread/NonCopyable.h"
+#include "zthread/Exceptions.h"
+
+#include <assert.h>
+#include <CoreServices/CoreServices.h>
+//#include <Multiprocessing.h>
+
+namespace ZThread {
+
+/**
+ * @class FastLock
+ *
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T23:25:31-0400>
+ * @version 2.1.6
+ *
+ */
+class FastLock : private NonCopyable {
+
+ MPCriticalRegionID _mtx;
+
+ public:
+
+ /**
+ * Create a new FastLock. No safety or state checks are performed.
+ *
+ * @exception Initialization_Exception - not thrown
+ */
+ inline FastLock() {
+
+ // Apple TN1071
+ static bool init = MPLibraryIsLoaded();
+
+ if(!init || MPCreateCriticalRegion(&_mtx) != noErr) {
+ assert(0);
+ throw Initialization_Exception();
+ }
+
+ }
+
+ /**
+ * Destroy a FastLock. No safety or state checks are performed.
+ */
+ inline ~FastLock() throw () {
+
+ OSStatus status = MPDeleteCriticalRegion(_mtx);
+ if(status != noErr)
+ assert(false);
+
+ }
+
+ /**
+ * Acquire an exclusive lock. No safety or state checks are performed.
+ *
+ * @exception Synchronization_Exception - not thrown
+ */
+ inline void acquire() {
+
+ if(MPEnterCriticalRegion(_mtx, kDurationForever) != noErr)
+ throw Synchronization_Exception();
+
+ }
+
+ /**
+ * Try to acquire an exclusive lock. No safety or state checks are performed.
+ * This function returns immediately regardless of the value of the timeout
+ *
+ * @param timeout Unused
+ * @return bool
+ * @exception Synchronization_Exception - not thrown
+ */
+ inline bool tryAcquire(unsigned long timeout=0) {
+
+ OSStatus status =
+ MPEnterCriticalRegion(_mtx, kDurationMillisecond * timeout);
+
+ switch(status) {
+ case kMPTimeoutErr:
+ return false;
+
+ case noErr:
+ return true;
+
+ }
+
+ assert(0);
+ throw Synchronization_Exception();
+
+ }
+
+ /**
+ * Release an exclusive lock. No safety or state checks are performed.
+ * The caller should have already acquired the lock, and release it
+ * only once.
+ *
+ * @exception Synchronization_Exception - not thrown
+ */
+ inline void release() {
+
+ if(MPExitCriticalRegion(_mtx) != noErr)
+ throw Synchronization_Exception();
+
+ }
+
+
+}; /* FastLock */
+
+
+};
+
+#endif
+
+
+
diff --git a/dep/src/zthread/macos/Monitor.cxx b/dep/src/zthread/macos/Monitor.cxx
new file mode 100644
index 00000000000..ab7806b13df
--- /dev/null
+++ b/dep/src/zthread/macos/Monitor.cxx
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "Monitor.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+using namespace ZThread;
+
+Monitor::Monitor() : _owner(0), _waiting(false), _pending(false) {
+
+ if(MPCreateSemaphore(1, 0, &_sema) != noErr) {
+ assert(0);
+ throw Initialization_Exception();
+ }
+
+}
+
+Monitor::~Monitor() throw() {
+
+ assert(!_waiting);
+
+ OSStatus status = MPDeleteSemaphore(_sema);
+ if(status != noErr)
+ assert(false);
+
+}
+
+Monitor::STATE Monitor::wait(unsigned long timeout) {
+
+ // Calcuate the time, taking into account Intertask Signaling Time
+ // http://developer.apple.com/techpubs/macosx/Carbon/oss/MultiPServices/Multiprocessing_Services/index.html?http://developer.apple.com/techpubs/macosx/Carbon/oss/MultiPServices/Multiprocessing_Services/Functions/Creating_and_ssage_Queues.html
+
+ AbsoluteTime tTarget;
+ Duration waitDuration =
+ (timeout == 0) ? kDurationForever : (kDurationMillisecond * timeout);
+
+ if(waitDuration != kDurationForever)
+ tTarget = AddDurationToAbsolute(waitDuration, UpTime());
+
+ // Update the owner on first use. The owner will not change, each
+ // thread waits only on a single Monitor and a Monitor is never
+ // shared
+ if(_owner == 0)
+ _owner = MPCurrentTaskID();
+
+ STATE state(INVALID);
+
+ // Serialize access to the state of the Monitor
+ // and test the state to determine if a wait is needed.
+ _waitLock.acquire();
+
+ if(pending(ANYTHING)) {
+
+ // Return without waiting when possible
+ state = next();
+
+ _waitLock.release();
+ return state;
+
+ }
+ // Unlock the external lock if a wait() is probably needed.
+ // Access to the state is still serial.
+ _lock.release();
+
+ // Wait for a transition in the state that is of interest, this
+ // allows waits to exclude certain flags (e.g. INTERRUPTED)
+ // for a single wait() w/o actually discarding those flags -
+ // they will remain set until a wait interested in those flags
+ // occurs.
+
+ // Wait, ignoring signals
+ _waiting = true;
+
+ _waitLock.release();
+
+ // Update the wait time
+ if(waitDuration != kDurationForever)
+ waitDuration = AbsoluteDeltaToDuration(tTarget, UpTime());
+
+ // Sleep until a signal arrives or a timeout occurs
+ OSStatus status = MPWaitOnSemaphore(_sema, waitDuration);
+
+ // Reacquire serialized access to the state
+ _waitLock.acquire();
+
+ // Awaken only when the event is set or the timeout expired
+ assert(status == kMPTimeoutErr || status == noErr);
+
+ if(status == kMPTimeoutErr)
+ push(TIMEDOUT);
+
+ // Get the next available STATE
+ state = next();
+
+ _waiting = false;
+
+ // Its possible that a timeout will wake the thread before a signal is
+ // delivered. Absorb that leftover so the next wait isn't aborted right away
+ if(status == kMPTimeoutErr && _pending) {
+
+ status = MPWaitOnSemaphore(_sema, kDurationForever);
+ assert(status == noErr);
+
+ }
+
+ _pending = false;
+
+ // Acquire the internal lock & release the external lock
+ _waitLock.release();
+
+ // Reaquire the external lock, keep from deadlocking threads calling
+ // notify(), interrupt(), etc.
+ _lock.acquire();
+
+ return state;
+
+}
+
+
+bool Monitor::interrupt() {
+
+ // Serialize access to the state
+ _waitLock.acquire();
+
+ bool wasInterruptable = !pending(INTERRUPTED);
+ bool hasWaiter = false;
+
+ // Update the state & wake the waiter if there is one
+ if(wasInterruptable) {
+
+ push(INTERRUPTED);
+
+ wasInterruptable = false;
+
+ if(_waiting && !_pending) {
+
+ _pending = true;
+ hasWaiter = true;
+
+ } else
+ wasInterruptable = !(_owner == MPCurrentTaskID());
+
+ }
+
+ _waitLock.release();
+
+ if(hasWaiter && !masked(Monitor::INTERRUPTED))
+ MPSignalSemaphore(_sema);
+
+ return wasInterruptable;
+
+}
+
+bool Monitor::isInterrupted() {
+
+ // Serialize access to the state
+ _waitLock.acquire();
+
+ bool wasInterrupted = pending(INTERRUPTED);
+ clear(INTERRUPTED);
+
+ _waitLock.release();
+
+ return wasInterrupted;
+
+}
+
+
+bool Monitor::notify() {
+
+ // Serialize access to the state
+ _waitLock.acquire();
+
+ bool wasNotifyable = !pending(INTERRUPTED);
+ bool hasWaiter = false;
+
+ // Set the flag if theres a waiter
+ if(wasNotifyable) {
+
+ push(SIGNALED);
+
+ if(_waiting && !_pending) {
+
+ _pending = true;
+ hasWaiter = true;
+
+ }
+
+ }
+
+ _waitLock.release();
+
+ if(hasWaiter)
+ MPSignalSemaphore(_sema);
+
+ return wasNotifyable;
+
+}
+
+
+bool Monitor::cancel() {
+
+ // Serialize access to the state
+ _waitLock.acquire();
+
+ bool wasInterrupted = !pending(INTERRUPTED);
+ bool hasWaiter = false;
+
+ push(CANCELED);
+
+ // Update the state if theres a waiter
+ if(wasInterrupted) {
+
+ push(INTERRUPTED);
+
+ if(_waiting && !_pending) {
+
+ _pending = true;
+ hasWaiter = true;
+
+ }
+
+ }
+
+ _waitLock.release();
+
+ if(hasWaiter && !masked(Monitor::INTERRUPTED))
+ MPSignalSemaphore(_sema);
+
+ return wasInterrupted;
+
+}
+
+bool Monitor::isCanceled() {
+
+ // Serialize access to the state
+ _waitLock.acquire();
+
+ bool wasCanceled = Status::examine(CANCELED);
+
+ if(_owner == MPCurrentTaskID())
+ clear(INTERRUPTED);
+
+ _waitLock.release();
+
+ return wasCanceled;
+
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/dep/src/zthread/macos/Monitor.h b/dep/src/zthread/macos/Monitor.h
new file mode 100644
index 00000000000..f4312d7b7ee
--- /dev/null
+++ b/dep/src/zthread/macos/Monitor.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTMONITOR_H__
+#define __ZTMONITOR_H__
+
+#include "../Status.h"
+#include "../FastLock.h"
+
+namespace ZThread {
+
+/**
+ * @class Monitor
+ * @author Eric Crahen <http://www.code-foo.com/>
+ * @date <2003-07-29T11:24:58-0400>
+ * @version 2.2.1
+ */
+class Monitor : public Status, private NonCopyable {
+
+ //! Serialize access to external objects
+ FastLock _lock;
+
+ //! Serialize access to internal state
+ FastLock _waitLock;
+
+ //! Semaphore to control the owning thread
+ MPSemaphoreID _sema;
+
+ //! Owning thread
+ MPTaskID _owner;
+
+ //! Waiting flag, to avoid uneccessary signals
+ volatile bool _waiting;
+
+ //! Waiting flag, to avoid too many signals
+ volatile bool _pending;
+
+ //! State of the monitor
+ volatile int _state;
+
+ public:
+
+ //! Create a new monitor.
+ Monitor();
+
+ //! Destroy the monitor.
+ ~Monitor() throw();
+
+ //! Acquire the external lock for this monitor.
+ inline void acquire() {
+ _lock.acquire();
+ }
+
+ //! Try to acquire the external lock for this monitor.
+ inline bool tryAcquire() {
+ return _lock.tryAcquire();
+ }
+
+ //! Release the external lock for this monitor.
+ inline void release() {
+ _lock.release();
+ }
+
+ /**
+ * Wait for a state change and atomically unlock the external lock.
+ * Blocks for an indefinent amount of time.
+ *
+ * @return INTERRUPTED if the wait was ended by a interrupt()
+ * or SIGNALED if the wait was ended by a notify()
+ *
+ * @post the external lock is always acquired before this function returns
+ */
+ inline STATE wait() {
+ return wait(0);
+ }
+
+ /**
+ * Wait for a state change and atomically unlock the external lock.
+ * May blocks for an indefinent amount of time.
+ *
+ * @param timeout - maximum time to block (milliseconds) or 0 to
+ * block indefinently
+ *
+ * @return INTERRUPTED if the wait was ended by a interrupt()
+ * or TIMEDOUT if the maximum wait time expired.
+ * or SIGNALED if the wait was ended by a notify()
+ *
+ * @post the external lock is always acquired before this function returns
+ */
+ STATE wait(unsigned long timeout);
+
+ /**
+ * Interrupt this monitor. If there is a thread blocked on this monitor object
+ * it will be signaled and released. If there is no waiter, a flag is set and
+ * the next attempt to wait() will return INTERRUPTED w/o blocking.
+ *
+ * @return false if the thread was previously INTERRUPTED.
+ */
+ bool interrupt();
+
+ /**
+ * Notify this monitor. If there is a thread blocked on this monitor object
+ * it will be signaled and released. If there is no waiter, a flag is set and
+ * the next attempt to wait() will return SIGNALED w/o blocking, if no other
+ * flag is set.
+ *
+ * @return false if the thread was previously INTERRUPTED.
+ */
+ bool notify();
+
+ /**
+ * Check the state of this monitor, clearing the INTERRUPTED status if set.
+ *
+ * @return bool true if the monitor was INTERRUPTED.
+ * @post INTERRUPTED flag cleared if the calling thread owns the monitor.
+ */
+ bool isInterrupted();
+
+ /**
+ * Mark the Status CANCELED, and INTERRUPT the montor.
+ *
+ * @see interrupt()
+ */
+ bool cancel();
+
+ /**
+ * Test the CANCELED Status, clearing the INTERRUPTED status if set.
+ *
+ * @return bool
+ */
+ bool isCanceled();
+
+};
+
+};
+
+#endif
diff --git a/dep/src/zthread/macos/TSS.h b/dep/src/zthread/macos/TSS.h
new file mode 100644
index 00000000000..3f9805d0f7c
--- /dev/null
+++ b/dep/src/zthread/macos/TSS.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTTSS_H__
+#define __ZTTSS_H__
+
+#include "zthread/NonCopyable.h"
+#include "zthread/Exceptions.h"
+
+#include <assert.h>
+#include <CoreServices/CoreServices.h>
+//#include <Multiprocessing.h>
+
+namespace ZThread {
+
+ /**
+ * @class TSS
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-27T14:19:10-0400>
+ * @version 2.1.6
+ *
+ * An abstraction for dealing with POSIX thread specific storage (tss).
+ * Provides get/set and creation/destruction.
+ */
+ template <typename T>
+ class TSS : private NonCopyable {
+
+ TaskStorageIndex _key;
+
+ public:
+
+ /**
+ * Create a new object for accessing tss.
+ */
+ TSS() {
+
+ // Apple TN1071
+ static bool init = MPLibraryIsLoaded();
+
+ if(!init || MPAllocateTaskStorageIndex(&_key) != noErr) {
+ assert(0);
+ throw Initialization_Exception();
+ }
+
+ }
+
+ /**
+ * Destroy the underlying supoprt for accessing tss with this
+ * object.
+ */
+ ~TSS() {
+
+ OSStatus status = MPDeallocateTaskStorageIndex(_key);
+ if(status != noErr)
+ assert(0);
+
+ }
+
+ /**
+ * Get the value stored in tss.
+ *
+ * @return T
+ *
+ * @exception InvalidOp_exception thrown when the tss is not properly initialized
+ */
+ T get() const {
+ return reinterpret_cast<T>(MPGetTaskStorageValue(_key));
+ }
+
+
+ /**
+ * Store a value in tss.
+ *
+ * @param value T
+ * @return T old value
+ *
+ * @exception InvalidOp_exception thrown when the tss is not properly initialized
+ */
+ T set(T value) const {
+
+ T oldValue = get();
+
+ OSStatus status =
+ MPSetTaskStorageValue(_key, reinterpret_cast<TaskStorageValue>(value));
+
+ if(status != noErr) {
+ assert(0);
+ throw Synchronization_Exception();
+ }
+
+ return oldValue;
+
+ }
+
+ };
+
+}
+
+#endif
+
+
diff --git a/dep/src/zthread/macos/ThreadOps.cxx b/dep/src/zthread/macos/ThreadOps.cxx
new file mode 100644
index 00000000000..6a1a4106877
--- /dev/null
+++ b/dep/src/zthread/macos/ThreadOps.cxx
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+
+#include "ThreadOps.h"
+#include "zthread/Exceptions.h"
+#include "zthread/Runnable.h"
+
+namespace ZThread {
+
+const ThreadOps ThreadOps::INVALID(0);
+
+ThreadOps::ThreadOps() : _queue(0), _tid(0) {
+
+ if(MPCreateQueue(&_queue) != noErr)
+ throw Initialization_Exception();
+
+}
+
+ThreadOps::~ThreadOps() throw() {
+
+ if(_queue != 0) {
+
+ OSStatus status = MPDeleteQueue(_queue);
+ if(status != noErr)
+ assert(0);
+
+ }
+
+}
+
+bool ThreadOps::join(ThreadOps* ops) {
+
+ assert(ops);
+ assert(ops->_tid != 0);
+
+ OSStatus status = MPWaitOnQueue(ops->_queue, NULL, NULL, NULL, kDurationForever);
+
+ return status == noErr;
+
+}
+
+bool ThreadOps::yield() {
+
+ MPYield();
+ return true;
+
+}
+
+bool ThreadOps::setPriority(ThreadOps* impl, Priority p) {
+ return true;
+}
+
+bool ThreadOps::getPriority(ThreadOps* impl, Priority& p) {
+ return true;
+}
+
+
+bool ThreadOps::spawn(Runnable* task) {
+
+ OSStatus status =
+ MPCreateTask(&_dispatch, task, 0UL, _queue, NULL, NULL, 0UL, &_tid);
+
+ return status == noErr;
+
+}
+
+OSStatus ThreadOps::_dispatch(void *arg) {
+
+ Runnable* task = reinterpret_cast<Runnable*>(arg);
+ assert(task);
+
+ // Run the task from the correct context
+ task->run();
+
+ // Exit the thread
+ MPExit(noErr);
+ return noErr;
+
+}
+
+} // namespace ZThread
+
+
diff --git a/dep/src/zthread/macos/ThreadOps.h b/dep/src/zthread/macos/ThreadOps.h
new file mode 100644
index 00000000000..c100fcfefe5
--- /dev/null
+++ b/dep/src/zthread/macos/ThreadOps.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTTHREADOPS_H__
+#define __ZTTHREADOPS_H__
+
+#include "zthread/Priority.h"
+
+#include <assert.h>
+#include <CoreServices/CoreServices.h>
+//#include <Multiprocessing.h>
+//#include <MultiprocessingInfo.h>
+
+namespace ZThread {
+
+class Runnable;
+
+/**
+ * @class ThreadOps
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T23:26:01-0400>
+ * @version 2.2.0
+ *
+ * This class is an abstraction used to perform various operations on a
+ * native POSIX thread.
+ */
+class ThreadOps {
+
+ //! Keep track of the pthreads handle for the native thread
+ MPQueueID _queue;
+ MPTaskID _tid;
+
+ ThreadOps(MPTaskID tid) : _queue(0), _tid(tid) { }
+
+ static OSStatus _dispatch(void*);
+
+public:
+
+ const static ThreadOps INVALID;
+
+ /**
+ * Create a new ThreadOps to manipulate a native thread.
+ */
+ ThreadOps();
+
+ ThreadOps(const ThreadOps& ops) : _queue(0), _tid(ops._tid) {}
+
+ ~ThreadOps() throw();
+
+ inline bool operator==(const ThreadOps& ops) const {
+ return ops._tid == _tid;
+ }
+
+ const ThreadOps& operator=(const ThreadOps& ops) {
+
+ assert(_queue == 0);
+ _tid = ops._tid;
+
+ return *this;
+
+ }
+
+ static ThreadOps self() {
+ return ThreadOps(MPCurrentTaskID());
+ }
+
+ /**
+ * Activating an instance of ThreadOps will map it onto the currently
+ * executing thread.
+ */
+ static void activate(ThreadOps* ops) {
+
+ assert(ops);
+ assert(ops->_tid == 0);
+
+ ops->_tid = MPCurrentTaskID();
+
+ }
+
+ /**
+ * Test if this object represents the currently executing
+ * native thread.
+ *
+ * @return bool true if successful
+ */
+
+ static bool isCurrent(ThreadOps* ops) {
+
+ assert(ops);
+
+ return MPCurrentTaskID() == ops->_tid;
+
+ }
+
+ /**
+ * Join a native thread.
+ *
+ * @return bool true if successful
+ */
+ static bool join(ThreadOps*);
+
+ /**
+ * Force the current native thread to yield, letting the scheduler
+ * give the CPU time to another thread.
+ *
+ * @return bool true if successful, false if the operation can't
+ * be supported.
+ */
+ static bool yield();
+
+ /**
+ * Set the priority for the native thread if supported by the
+ * system.
+ *
+ * @param PRIORITY requested priority
+ * @return bool false if unsuccessful
+ */
+ static bool setPriority(ThreadOps*, Priority);
+
+ /**
+ * Set the priority for the native thread if supported by the
+ * system.
+ *
+ * @param Thread::PRIORITY& current priority
+ * @return bool false if unsuccessful
+ */
+ static bool getPriority(ThreadOps*, Priority&);
+
+protected:
+
+ /**
+ * Spawn a native thread.
+ *
+ * @param ThreadImpl* parent thread
+ * @param ThreadImpl* child thread being started.
+ * @param Runnable* task being executed.
+ *
+ * @return bool true if successful
+ */
+ bool spawn(Runnable*);
+
+};
+
+
+}
+
+#endif // __ZTTHREADOPS_H__
+
diff --git a/dep/src/zthread/macos/UpTimeStrategy.h b/dep/src/zthread/macos/UpTimeStrategy.h
new file mode 100644
index 00000000000..f2056e14ca2
--- /dev/null
+++ b/dep/src/zthread/macos/UpTimeStrategy.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTTIMESTRATEGY_H__
+#define __ZTTIMESTRATEGY_H__
+
+#include <CoreServices/CoreServices.h>
+//#include <DriverServices.h>
+
+namespace ZThread {
+
+
+/**
+ * @class TimeStrategy
+ *
+ * Implement a strategy for time operatons based on UpTime
+ */
+class TimeStrategy {
+
+ unsigned long _ms;
+ unsigned long _s;
+
+ public:
+
+ TimeStrategy() {
+
+ // Get the absolute time in milliseconds relative to the program startup
+ static AbsoluteTime sysUpTime(UpTime());
+ AbsoluteTime delta = AbsoluteDeltaToNanoseconds(UpTime(), sysUpTime);
+
+ uint64_t now = *reinterpret_cast<uint64_t*>(&delta) / 1000000;
+
+ _s = now / 1000;
+ _ms = now % 1000;
+
+ }
+
+ inline unsigned long seconds() const {
+ return _s;
+ }
+
+ inline unsigned long milliseconds() const {
+ return _ms;
+ }
+
+ unsigned long seconds(unsigned long s) {
+
+ unsigned long z = seconds();
+ _s = s;
+ return z;
+
+ }
+
+ unsigned long milliseconds(unsigned long ms) {
+
+ unsigned long z = milliseconds();
+ _ms = ms;
+
+ return z;
+
+ }
+
+};
+
+};
+
+#endif // __ZTTIMESTRATEGY_H__
diff --git a/dep/src/zthread/posix/ConditionRecursiveLock.h b/dep/src/zthread/posix/ConditionRecursiveLock.h
new file mode 100644
index 00000000000..a46ed35548c
--- /dev/null
+++ b/dep/src/zthread/posix/ConditionRecursiveLock.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTFASTRECURSIVELOCK_H__
+#define __ZTFASTRECURSIVELOCK_H__
+
+#include "zthread/NonCopyable.h"
+#include <pthread.h>
+#include <errno.h>
+#include <assert.h>
+
+namespace ZThread {
+
+/**
+ * @class FastRecursiveLock
+ *
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T23:28:37-0400>
+ * @version 2.2.0
+ *
+ * This is an implementation of a FastRecursiveLock for any vannila
+ * POSIX system. It is based on a condition variable and a mutex;
+ * because of this it is important to not that its waiting properties
+ * are not the same as other mutex implementations that generally
+ * based on spin locks. Under high contention, this implementation may
+ * be preferable to a spin lock, although refactoring the design of
+ * code that puts a mutex under alot of preasure may be worth investigating.
+ */
+class FastRecursiveLock : private NonCopyable {
+
+ //! Serialize state
+ pthread_mutex_t _mtx;
+
+ //! Wait for lock
+ pthread_cond_t _cond;
+
+ //! Owner
+ pthread_t _owner;
+
+ //! Count
+ volatile unsigned int _count;
+
+public:
+
+ inline FastRecursiveLock() : _owner(0), _count(0) {
+
+ pthread_mutex_init(&_mtx, 0);
+ if(pthread_cond_init(&_cond, 0) != 0) {
+ assert(0);
+ }
+
+ }
+
+ inline ~FastRecursiveLock() {
+
+ pthread_mutex_destroy(&_mtx);
+ if(pthread_cond_destroy(&_cond) != 0) {
+ assert(0);
+ }
+
+ }
+
+ inline void acquire() {
+
+ pthread_t self = pthread_self();
+ pthread_mutex_lock(&_mtx);
+
+ // If the caller does not own the lock, wait until there is no owner
+ if(_owner != 0 && !pthread_equal(_owner, self)) {
+
+ int status = 0;
+ do { // ignore signals
+ status = pthread_cond_wait(&_cond, &_mtx);
+ } while(status == EINTR && _owner == 0);
+
+ }
+
+ _owner = self;
+ _count++;
+
+ pthread_mutex_unlock(&_mtx);
+
+ }
+
+ inline bool tryAcquire(unsigned long timeout=0) {
+
+ pthread_t self = pthread_self();
+ pthread_mutex_lock(&_mtx);
+
+ // If the caller owns the lock, or there is no owner update the count
+ bool success = (_owner == 0 || pthread_equal(_owner, self));
+ if(success) {
+
+ _owner = self;
+ _count++;
+
+ }
+
+ pthread_mutex_unlock(&_mtx);
+
+ return success;
+
+ }
+
+ inline void release() {
+
+ assert(pthread_equal(_owner, pthread_self()));
+
+ pthread_mutex_lock(&_mtx);
+ if(--_count == 0) {
+
+ _owner = 0;
+ pthread_cond_signal(&_cond);
+
+ }
+
+ pthread_mutex_unlock(&_mtx);
+
+ }
+
+
+}; /* FastRecursiveLock */
+
+
+} // namespace ZThread
+
+#endif
diff --git a/dep/src/zthread/posix/FastLock.h b/dep/src/zthread/posix/FastLock.h
new file mode 100644
index 00000000000..87faf34d4ff
--- /dev/null
+++ b/dep/src/zthread/posix/FastLock.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTFASTLOCK_H__
+#define __ZTFASTLOCK_H__
+
+#include "zthread/Exceptions.h"
+#include "zthread/NonCopyable.h"
+#include <pthread.h>
+#include <assert.h>
+
+namespace ZThread {
+
+/**
+ * @class FastLock
+ *
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T23:28:07-0400>
+ * @version 2.2.8
+ *
+ * This is the smallest and fastest synchronization object in the library.
+ * It is an implementation of fast mutex, an all or nothing exclusive
+ * lock. It should be used only where you need speed and are willing
+ * to sacrifice all the state & safety checking provided by the framework
+ * for speed.
+ */
+class FastLock : private NonCopyable {
+
+ pthread_mutex_t _mtx;
+
+ public:
+
+ /**
+ * Create a new FastLock. No safety or state checks are performed.
+ *
+ * @exception Initialization_Exception - not thrown
+ */
+ inline FastLock() {
+
+ if(pthread_mutex_init(&_mtx, 0) != 0)
+ throw Initialization_Exception();
+
+ }
+
+ /**
+ * Destroy a FastLock. No safety or state checks are performed.
+ */
+ inline ~FastLock() {
+
+ if(pthread_mutex_destroy(&_mtx) != 0) {
+ assert(0);
+ }
+
+ }
+
+ /**
+ * Acquire an exclusive lock. No safety or state checks are performed.
+ *
+ * @exception Synchronization_Exception - not thrown
+ */
+ inline void acquire() {
+
+ if(pthread_mutex_lock(&_mtx) != 0)
+ throw Synchronization_Exception();
+
+ }
+
+ /**
+ * Try to acquire an exclusive lock. No safety or state checks are performed.
+ * This function returns immediately regardless of the value of the timeout
+ *
+ * @param timeout Unused
+ * @return bool
+ * @exception Synchronization_Exception - not thrown
+ */
+ inline bool tryAcquire(unsigned long /*timeout*/=0) {
+
+ return (pthread_mutex_trylock(&_mtx) == 0);
+
+ }
+
+ /**
+ * Release an exclusive lock. No safety or state checks are performed.
+ * The caller should have already acquired the lock, and release it
+ * only once.
+ *
+ * @exception Synchronization_Exception - not thrown
+ */
+ inline void release() {
+
+ if(pthread_mutex_unlock(&_mtx) != 0)
+ throw Synchronization_Exception();
+
+ }
+
+
+}; /* FastLock */
+
+
+};
+
+#endif
diff --git a/dep/src/zthread/posix/FtimeStrategy.h b/dep/src/zthread/posix/FtimeStrategy.h
new file mode 100644
index 00000000000..5e703970c5c
--- /dev/null
+++ b/dep/src/zthread/posix/FtimeStrategy.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTTIMESTRATEGY_H__
+#define __ZTTIMESTRATEGY_H__
+
+#include <sys/timeb.h>
+
+#if defined(_MSC_VER)
+
+# include <time.h>
+
+# define timeb _timeb
+# define ftime _ftime
+
+#endif
+
+namespace ZThread {
+
+/**
+ * @class TimeStrategy
+ *
+ * Implement a strategy for time operatons based on ftime
+ */
+class TimeStrategy {
+
+ struct timeb _value;
+
+public:
+
+ TimeStrategy() {
+ ftime(&_value);
+ }
+
+ inline unsigned long seconds() const {
+ return (unsigned long)_value.time;
+ }
+
+ inline unsigned long milliseconds() const {
+ return _value.millitm;
+ }
+
+ unsigned long seconds(unsigned long s) {
+
+ unsigned long z = seconds();
+ _value.time = s;
+
+ return z;
+
+ }
+
+ unsigned long milliseconds(unsigned long ms) {
+
+ unsigned long z = milliseconds();
+ _value.millitm = (unsigned short)ms;
+
+ return z;
+
+ }
+
+};
+
+};
+
+#endif // __ZTTIMESTRATEGY_H__
diff --git a/dep/src/zthread/posix/GetTimeOfDayStrategy.h b/dep/src/zthread/posix/GetTimeOfDayStrategy.h
new file mode 100644
index 00000000000..8588807f4f7
--- /dev/null
+++ b/dep/src/zthread/posix/GetTimeOfDayStrategy.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTTIMESTRATEGY_H__
+#define __ZTTIMESTRATEGY_H__
+
+#include <sys/time.h>
+
+namespace ZThread {
+
+/**
+ * @class TimeStrategy
+ *
+ * Implement a strategy for time operatons based on gettimeofday
+ */
+class TimeStrategy {
+
+ struct timeval _value;
+
+public:
+
+ TimeStrategy() {
+ gettimeofday(&_value, 0);
+ }
+
+ inline unsigned long seconds() const {
+ return _value.tv_sec;
+ }
+
+ inline unsigned long milliseconds() const {
+ return _value.tv_usec/1000;
+ }
+
+ unsigned long seconds(unsigned long s) {
+
+ unsigned long z = seconds();
+ _value.tv_sec = s;
+
+ return z;
+
+ }
+
+ unsigned long milliseconds(unsigned long ms) {
+
+ unsigned long z = milliseconds();
+ _value.tv_usec = ms*1000;
+
+ return z;
+
+ }
+
+};
+
+};
+
+#endif // __ZTTIMESTRATEGY_H__
diff --git a/dep/src/zthread/posix/Monitor.cxx b/dep/src/zthread/posix/Monitor.cxx
new file mode 100644
index 00000000000..bb157dae0dc
--- /dev/null
+++ b/dep/src/zthread/posix/Monitor.cxx
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "Monitor.h"
+#include "../Debug.h"
+#include "../TimeStrategy.h"
+
+#include <errno.h>
+#include <assert.h>
+#include <signal.h>
+
+namespace ZThread {
+
+Monitor::Monitor() : _owner(0), _waiting(false) {
+
+ pthread_cond_init(&_waitCond, 0);
+ pthread_mutex_init(&_waitLock, 0);
+
+}
+
+Monitor::~Monitor() {
+
+ assert(!_waiting);
+
+ pthread_cond_destroy(&_waitCond);
+ pthread_mutex_destroy(&_waitLock);
+
+}
+
+Monitor::STATE Monitor::wait(unsigned long ms) {
+
+ // Update the owner on first use. The owner will not change, each
+ // thread waits only on a single Monitor and a Monitor is never
+ // shared
+ if(_owner == 0)
+ _owner = pthread_self();
+
+ STATE state(INVALID);
+
+ // Serialize access to the state of the Monitor
+ // and test the state to determine if a wait is needed.
+
+ pthread_mutex_lock(&_waitLock);
+
+ if(pending(ANYTHING)) {
+
+ // Return without waiting when possible
+ state = next();
+
+ pthread_mutex_unlock(&_waitLock);
+ return state;
+
+ }
+
+ // Unlock the external lock if a wait() is probably needed.
+ // Access to the state is still serial.
+ _lock.release();
+
+ // Wait for a transition in the state that is of interest, this
+ // allows waits to exclude certain flags (e.g. INTERRUPTED)
+ // for a single wait() w/o actually discarding those flags -
+ // they will remain set until a wait interested in those flags
+ // occurs.
+ // if(!currentState(interest)) {
+
+ // Wait, ignoring signals
+ _waiting = true;
+ int status = 0;
+
+ if(ms == 0) { // Wait forever
+
+ do { // ignore signals unless the state is interesting
+ status = pthread_cond_wait(&_waitCond, &_waitLock);
+ } while(status == EINTR && !pending(ANYTHING));
+
+ // Akwaken only when a state is pending
+ assert(status == 0);
+
+ } else {
+
+ // Find the target time
+ TimeStrategy t;
+
+ ms += t.milliseconds();
+
+ unsigned long s = t.seconds() + (ms / 1000);
+ ms %= 1000;
+
+ // Convert to a timespec
+ struct ::timespec timeout;
+
+ timeout.tv_sec = s;
+ timeout.tv_nsec = ms*1000000;
+
+ // Wait ignoring signals until the state is interesting
+ do {
+
+ // When a timeout occurs, update the state to reflect that.
+ status = pthread_cond_timedwait(&_waitCond, &_waitLock, &timeout);
+
+ } while(status == EINTR && !pending(ANYTHING));
+
+ // Akwaken only when a state is pending or when the timeout expired
+ assert(status == 0 || status == ETIMEDOUT);
+
+ if(status == ETIMEDOUT)
+ push(TIMEDOUT);
+
+ }
+
+ // Get the next available STATE
+ state = next();
+ _waiting = false;
+
+ pthread_mutex_unlock(&_waitLock);
+
+ // Reaquire the external lock, keep from deadlocking threads calling
+ // notify(), interrupt(), etc.
+
+ _lock.acquire();
+
+ return state;
+
+}
+
+
+bool Monitor::interrupt() {
+
+ // Serialize access to the state
+ pthread_mutex_lock(&_waitLock);
+
+ bool wasInterruptable = !pending(INTERRUPTED);
+ bool hadWaiter = _waiting;
+
+ if(wasInterruptable) {
+
+ // Update the state & wake the waiter if there is one
+ push(INTERRUPTED);
+
+ wasInterruptable = false;
+
+ if(hadWaiter && !masked(Monitor::INTERRUPTED))
+ pthread_cond_signal(&_waitCond);
+ else
+ wasInterruptable = !pthread_equal(_owner, pthread_self());
+
+ }
+
+ pthread_mutex_unlock(&_waitLock);
+
+ // Only returns true when an interrupted thread is not currently blocked
+ return wasInterruptable;
+
+}
+
+bool Monitor::isInterrupted() {
+
+ // Serialize access to the state
+ pthread_mutex_lock(&_waitLock);
+
+ bool wasInterrupted = pending(INTERRUPTED);
+
+ clear(INTERRUPTED);
+
+ pthread_mutex_unlock(&_waitLock);
+
+ return wasInterrupted;
+
+}
+
+bool Monitor::isCanceled() {
+
+ // Serialize access to the state
+ pthread_mutex_lock(&_waitLock);
+
+ bool wasCanceled = examine(CANCELED);
+
+ if(pthread_equal(_owner, pthread_self()))
+ clear(INTERRUPTED);
+
+ pthread_mutex_unlock(&_waitLock);
+
+ return wasCanceled;
+
+}
+
+bool Monitor::cancel() {
+
+ // Serialize access to the state
+ pthread_mutex_lock(&_waitLock);
+
+ bool wasInterrupted = !pending(INTERRUPTED);
+ bool hadWaiter = _waiting;
+
+ push(CANCELED);
+
+ if(wasInterrupted) {
+
+ // Update the state & wake the waiter if there is one
+ push(INTERRUPTED);
+
+ if(hadWaiter && !masked(Monitor::INTERRUPTED))
+ pthread_cond_signal(&_waitCond);
+
+ }
+
+ pthread_mutex_unlock(&_waitLock);
+
+ return wasInterrupted;
+
+}
+
+bool Monitor::notify() {
+
+ // Serialize access to the state
+ pthread_mutex_lock(&_waitLock);
+
+ bool wasNotifyable = !pending(INTERRUPTED);
+
+ if(wasNotifyable) {
+
+ // Set the flag and wake the waiter if there
+ // is one
+ push(SIGNALED);
+
+ if(_waiting)
+ pthread_cond_signal(&_waitCond);
+
+ }
+
+ pthread_mutex_unlock(&_waitLock);
+
+ return wasNotifyable;
+
+}
+
+} // namespace ZThread
+
diff --git a/dep/src/zthread/posix/Monitor.h b/dep/src/zthread/posix/Monitor.h
new file mode 100644
index 00000000000..945c879f421
--- /dev/null
+++ b/dep/src/zthread/posix/Monitor.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTMONITOR_H__
+#define __ZTMONITOR_H__
+
+#include "../Status.h"
+#include "../FastLock.h"
+
+namespace ZThread {
+
+/**
+ * @class Monitor
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-18T08:16:09-0400>
+ * @version 2.2.8
+ */
+class Monitor : public Status, private NonCopyable {
+ private:
+
+ //! Serialize access to external objects
+ FastLock _lock;
+
+ //! Condition variable used to block a thread.
+ pthread_cond_t _waitCond;
+
+ //! Serialize access to the internal state of the monitor
+ pthread_mutex_t _waitLock;
+
+ //! Owning thread
+ pthread_t _owner;
+
+ //! Waiting flag, to avoid uneccessary signals
+ volatile bool _waiting;
+
+ public:
+
+ typedef Status::STATE STATE;
+
+ //! Create a new monitor.
+ Monitor();
+
+ //! Destroy the monitor.
+ ~Monitor();
+
+ //! Acquire the lock for this monitor.
+ inline void acquire() {
+ _lock.acquire();
+ }
+
+ //! Acquire the lock for this monitor.
+ inline bool tryAcquire() {
+ return _lock.tryAcquire();
+ }
+
+ //! Release the lock for this monitor
+ inline void release() {
+ _lock.release();
+ }
+
+ /**
+ * Wait for a state change and atomically unlock the external lock.
+ * Blocks for an indefinent amount of time.
+ *
+ * @return INTERRUPTED if the wait was ended by a interrupt()
+ * or SIGNALED if the wait was ended by a notify()
+ *
+ * @post the external lock is always acquired before this function returns
+ */
+ inline STATE wait() {
+ return wait(0);
+ }
+
+ /**
+ * Wait for a state change and atomically unlock the external lock.
+ * May blocks for an indefinent amount of time.
+ *
+ * @param timeout - maximum time to block (milliseconds) or 0 to
+ * block indefinently
+ *
+ * @return INTERRUPTED if the wait was ended by a interrupt()
+ * or TIMEDOUT if the maximum wait time expired.
+ * or SIGNALED if the wait was ended by a notify()
+ *
+ * @post the external lock is always acquired before this function returns
+ */
+ STATE wait(unsigned long timeout);
+
+ /**
+ * Interrupt this monitor. If there is a thread blocked on this monitor object
+ * it will be signaled and released. If there is no waiter, a flag is set and
+ * the next attempt to wait() will return INTERRUPTED w/o blocking.
+ *
+ * @return false if the thread was previously INTERRUPTED.
+ */
+ bool interrupt();
+
+ /**
+ * Notify this monitor. If there is a thread blocked on this monitor object
+ * it will be signaled and released. If there is no waiter, a flag is set and
+ * the next attempt to wait() will return SIGNALED w/o blocking, if no other
+ * flag is set.
+ *
+ * @return false if the thread was previously INTERRUPTED.
+ */
+ bool notify();
+
+ /**
+ * Check the state of this monitor, clearing the INTERRUPTED status if set.
+ *
+ * @return bool true if the monitor was INTERRUPTED.
+ * @post INTERRUPTED flag cleared if the calling thread owns the monitor.
+ */
+ bool isInterrupted();
+
+ /**
+ * Mark the Status CANCELED, and INTERRUPT the montor.
+ *
+ * @see interrupt()
+ */
+ bool cancel();
+
+ /**
+ * Test the CANCELED Status, clearing the INTERRUPTED status if set.
+ *
+ * @return bool
+ */
+ bool isCanceled();
+
+};
+
+};
+
+#endif
diff --git a/dep/src/zthread/posix/PriorityOps.h b/dep/src/zthread/posix/PriorityOps.h
new file mode 100644
index 00000000000..92da66a9cff
--- /dev/null
+++ b/dep/src/zthread/posix/PriorityOps.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTPRIORITYOPS_H__
+#define __ZTPRIORITYOPS_H__
+
+#include "zthread/Priority.h"
+#include "../ThreadOps.h"
+
+namespace ZThread {
+
+/**
+ * @class PriorityOps
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T23:30:00-0400>
+ * @version 2.2.0
+ *
+ * This class is an abstraction used to perform various operations on a
+ * native POSIX thread.
+ */
+class PriorityOps {
+
+
+public:
+
+
+};
+
+
+} // namespace ZThread
+
+#endif // __ZTPRIORITYOPS_H__
diff --git a/dep/src/zthread/posix/TSS.h b/dep/src/zthread/posix/TSS.h
new file mode 100644
index 00000000000..931ff348b3d
--- /dev/null
+++ b/dep/src/zthread/posix/TSS.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTTSS_H__
+#define __ZTTSS_H__
+
+#include "zthread/NonCopyable.h"
+#include <pthread.h>
+#include <assert.h>
+
+namespace ZThread {
+
+ /**
+ * @class TSS
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-27T14:18:37-0400>
+ * @version 2.3.0
+ *
+ * An abstraction for dealing with POSIX thread specific storage (tss).
+ * Provides get/set and creation/destruction.
+ */
+ template <typename T>
+ class TSS : private NonCopyable {
+
+ pthread_key_t _key;
+
+ public:
+
+ /**
+ * Create a new object for accessing tss.
+ */
+ TSS() {
+
+ if(pthread_key_create(&_key, 0) != 0) {
+ assert(0); // Key creation failed
+ }
+
+ }
+
+ /**
+ * Destroy the underlying supoprt for accessing tss with this
+ * object.
+ */
+ ~TSS() {
+
+ pthread_key_delete(_key);
+
+ }
+
+ /**
+ * Get the value stored in tss.
+ *
+ * @return T
+ *
+ * @exception InvalidOp_exception thrown when the tss is not properly initialized
+ */
+ T get() const {
+ return reinterpret_cast<T>(pthread_getspecific(_key));
+ }
+
+
+ /**
+ * Store a value in tss.
+ *
+ * @param value T
+ * @return T old value
+ *
+ * @exception InvalidOp_exception thrown when the tss is not properly initialized
+ */
+ T set(T value) const {
+
+ T oldValue = get();
+ pthread_setspecific(_key, value);
+
+ return oldValue;
+
+ }
+
+ };
+
+}
+
+#endif
+
+
diff --git a/dep/src/zthread/posix/ThreadOps.cxx b/dep/src/zthread/posix/ThreadOps.cxx
new file mode 100644
index 00000000000..e72ef78ada3
--- /dev/null
+++ b/dep/src/zthread/posix/ThreadOps.cxx
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "ThreadOps.h"
+#include "zthread/Guard.h"
+#include "zthread/Runnable.h"
+#include <errno.h>
+
+#if defined(HAVE_SCHED_YIELD)
+# include <sched.h>
+#endif
+
+namespace ZThread {
+
+const ThreadOps ThreadOps::INVALID(0);
+
+bool ThreadOps::join(ThreadOps* ops) {
+
+ assert(ops);
+ assert(ops->_tid != 0);
+
+ int err = 0;
+
+ do {
+
+ err = pthread_join(ops->_tid, NULL);
+
+ } while(err == EINTR);
+
+ return err == 0;
+
+}
+
+bool ThreadOps::yield() {
+
+ bool result = false;
+
+#if defined(HAVE_SCHED_YIELD)
+ result = sched_yield() == 0;
+#endif
+
+ return result;
+
+}
+
+bool ThreadOps::setPriority(ThreadOps* impl, Priority p) {
+
+ assert(impl);
+
+ bool result = true;
+
+#if !defined(ZTHREAD_DISABLE_PRIORITY)
+
+ struct sched_param param;
+
+ switch(p) {
+ case Low:
+ param.sched_priority = 0;
+ break;
+ case High:
+ param.sched_priority = 10;
+ break;
+ case Medium:
+ default:
+ param.sched_priority = 5;
+ }
+
+ result = pthread_setschedparam(impl->_tid, SCHED_OTHER, &param) == 0;
+
+#endif
+
+ return result;
+
+}
+
+bool ThreadOps::getPriority(ThreadOps* impl, Priority& p) {
+
+ assert(impl);
+
+ bool result = true;
+
+#if !defined(ZTHREAD_DISABLE_PRIORITY)
+
+ struct sched_param param;
+ int policy = SCHED_OTHER;
+
+ if(result = (pthread_getschedparam(impl->_tid, &policy, &param) == 0)) {
+
+ // Convert to one of the PRIORITY values
+ if(param.sched_priority < 10)
+ p = Low;
+ else if(param.sched_priority == 10)
+ p = Medium;
+ else
+ p = High;
+
+ }
+
+#endif
+
+ return result;
+
+}
+
+
+bool ThreadOps::spawn(Runnable* task) {
+ return pthread_create(&_tid, 0, _dispatch, task) == 0;
+}
+
+
+
+extern "C" void *_dispatch(void *arg) {
+
+ Runnable* task = reinterpret_cast<Runnable*>(arg);
+ assert(task);
+
+ // Run the task from the correct context
+ task->run();
+
+ // Exit the thread
+ pthread_exit((void**)0);
+ return (void*)0;
+
+}
+
+} // namespace ZThread
+
+
diff --git a/dep/src/zthread/posix/ThreadOps.h b/dep/src/zthread/posix/ThreadOps.h
new file mode 100644
index 00000000000..be754c2d659
--- /dev/null
+++ b/dep/src/zthread/posix/ThreadOps.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTTHREADOPS_H__
+#define __ZTTHREADOPS_H__
+
+
+#include "zthread/Priority.h"
+#include <pthread.h>
+#include <assert.h>
+
+namespace ZThread {
+
+class Runnable;
+
+//! Dispatch function for native pthreads required extern C
+//! linkage.
+extern "C" void* _dispatch(void*);
+
+/**
+ * @class ThreadOps
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T23:30:25-0400>
+ * @version 2.2.8
+ *
+ * This class is an abstraction used to perform various operations on a
+ * native POSIX thread.
+ */
+class ThreadOps {
+
+ //! Keep track of the pthreads handle for the native thread
+ pthread_t _tid;
+
+ ThreadOps(pthread_t tid) : _tid(tid) { }
+
+public:
+
+ const static ThreadOps INVALID;
+
+ /**
+ * Create a new ThreadOps to manipulate a native thread.
+ */
+ ThreadOps() : _tid(0) { }
+
+
+ inline bool operator==(const ThreadOps& ops) const {
+ return pthread_equal(_tid, ops._tid);
+ }
+
+
+ static ThreadOps self() {
+ return ThreadOps(pthread_self());
+ }
+
+ /**
+ * Activating an instance of ThreadOps will map it onto the currently
+ * executing thread.
+ */
+ static void activate(ThreadOps* ops) {
+
+ assert(ops);
+ assert(ops->_tid == 0);
+
+ ops->_tid = pthread_self();
+
+ }
+
+ /**
+ * Test if this object represents the currently executing
+ * native thread.
+ *
+ * @return bool true if successful
+ */
+
+ static bool isCurrent(ThreadOps* ops) {
+
+ assert(ops);
+
+ return pthread_equal(pthread_self(), ops->_tid);
+
+ }
+
+ /**
+ * Join a native thread.
+ *
+ * @return bool true if successful
+ */
+ static bool join(ThreadOps*);
+
+ /**
+ * Force the current native thread to yield, letting the scheduler
+ * give the CPU time to another thread.
+ *
+ * @return bool true if successful, false if the operation can't
+ * be supported.
+ */
+ static bool yield();
+
+ /**
+ * Set the priority for the native thread if supported by the
+ * system.
+ *
+ * @param PRIORITY requested priority
+ * @return bool false if unsuccessful
+ */
+ static bool setPriority(ThreadOps*, Priority);
+
+ /**
+ * Set the priority for the native thread if supported by the
+ * system.
+ *
+ * @param Thread::PRIORITY& current priority
+ * @return bool false if unsuccessful
+ */
+ static bool getPriority(ThreadOps*, Priority&);
+
+protected:
+
+ /**
+ * Spawn a native thread.
+ *
+ * @param ThreadImpl* parent thread
+ * @param ThreadImpl* child thread being started.
+ * @param Runnable* task being executed.
+ *
+ * @return bool true if successful
+ */
+ bool spawn(Runnable*);
+
+};
+
+
+}
+
+#endif // __ZTTHREADOPS_H__
diff --git a/dep/src/zthread/solaris/FastRecursiveLock.h b/dep/src/zthread/solaris/FastRecursiveLock.h
new file mode 100644
index 00000000000..956e1dbd3ad
--- /dev/null
+++ b/dep/src/zthread/solaris/FastRecursiveLock.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTFASTRECURSIVELOCK_H__
+#define __ZTFASTRECURSIVELOCK_H__
+
+#include "zthread/NonCopyable.h"
+#include <pthread.h>
+
+namespace ZThread {
+
+/**
+ * @class FastRecursiveLock
+ *
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T23:31:23-0400>
+ * @version 2.2.0
+ *
+ * This FastRecursiveLock implementation uses pthreads mutex attribute
+ * functions to create a recursive lock. This implementation is not
+ * specific to solaris and will work on any system that supports
+ * pthread_mutexattr_settype().
+ */
+class FastRecursiveLock : private NonCopyable {
+
+ pthread_mutex_t _mtx;
+
+ /**
+ * @class Attribute
+ *
+ * Utility class to maintain the attribute as long as it is needed.
+ */
+ class Attribute {
+
+ pthread_mutexattr_t _attr;
+
+ public:
+
+ Attribute() {
+
+ if(pthread_mutexattr_init(&_attr) != 0) {
+ assert(0);
+ }
+
+ if(pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_RECURSIVE) != 0) {
+ assert(0);
+ }
+
+ }
+
+ ~Attribute() {
+
+ if(pthread_mutexattr_destroy(&_attr) != 0) {
+ assert(0);
+ }
+
+ }
+
+ operator pthread_mutexattr_t*() {
+ return &_attr;
+ }
+
+ };
+
+public:
+
+ inline FastRecursiveLock() {
+
+ static Attribute attr;
+ pthread_mutex_init(&_mtx, (pthread_mutexattr_t*)attr);
+
+ }
+
+ inline ~FastRecursiveLock() {
+
+ pthread_mutex_destroy(&_mtx);
+
+ }
+
+ inline void acquire() {
+
+ pthread_mutex_lock(&_mtx);
+
+ }
+
+ inline void release() {
+
+ pthread_mutex_unlock(&_mtx);
+
+ }
+
+ inline bool tryAcquire(unsigned long timeout=0) {
+
+ return (pthread_mutex_trylock(&_mtx) == 0);
+
+ }
+
+}; /* FastRecursiveLock */
+
+
+} // namespace ZThread
+
+#endif
diff --git a/dep/src/zthread/vanilla/DualMutexRecursiveLock.h b/dep/src/zthread/vanilla/DualMutexRecursiveLock.h
new file mode 100644
index 00000000000..ddce7a3cd27
--- /dev/null
+++ b/dep/src/zthread/vanilla/DualMutexRecursiveLock.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTFASTRECURSIVELOCK_H__
+#define __ZTFASTRECURSIVELOCK_H__
+
+#include "../FastLock.h"
+#include "../ThreadOps.h"
+#include <assert.h>
+
+namespace ZThread {
+
+/**
+ * @class FastRecursiveLock
+ *
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T23:31:09-0400>
+ * @version 2.2.8
+ *
+ * This is a vanilla FastRecursiveLock implementation for a
+ * system that doesn't provide recurisve locks. This implementation
+ * is based on using a pair of mutexes, because of this, it performs
+ * roughly the same as a spin lock would.
+ */
+class FastRecursiveLock : private NonCopyable {
+
+ //! Lock for blocking
+ FastLock _blockingLock;
+
+ //! Serialize state
+ FastLock _stateLock;
+
+ //! Owner
+ ThreadOps _owner;
+
+ //! Count
+ volatile unsigned int _count;
+
+ public:
+
+ inline FastRecursiveLock() : _owner(ThreadOps::INVALID), _count(0) { }
+
+ inline ~FastRecursiveLock() {
+
+ assert(_owner == ThreadOps::INVALID);
+ assert(_count == 0);
+
+ }
+
+ void acquire() {
+
+ ThreadOps self(ThreadOps::self());
+
+ // Try to lock the blocking mutex first
+ bool wasLocked = _blockingLock.tryAcquire();
+ if(!wasLocked) {
+
+ // Otherwise, grab the lock for the state
+ _stateLock.acquire();
+
+ wasLocked = (_owner == self);
+ if(wasLocked)
+ _count++;
+
+ _stateLock.release();
+
+ if(wasLocked)
+ return;
+
+ // Try to be cooperative
+ ThreadOps::yield();
+ _blockingLock.acquire();
+
+ }
+
+ // Serialze access to the state
+ _stateLock.acquire();
+
+ // Take ownership
+ assert(_owner == ThreadOps::INVALID || _owner == self);
+
+ _owner = self;
+ _count++;
+
+ _stateLock.release();
+
+ }
+
+
+ bool tryAcquire(unsigned long timeout = 0) {
+
+ ThreadOps self(ThreadOps::self());
+
+ // Try to lock the blocking mutex first
+ bool wasLocked = _blockingLock.tryAcquire();
+ if(!wasLocked) {
+
+ // Otherwise, grab the lock for the state
+ _stateLock.acquire();
+
+ wasLocked = (_owner == self);
+ if(wasLocked)
+ _count++;
+
+ _stateLock.release();
+
+ return wasLocked;
+
+ }
+
+ // Serialze access to the state
+ _stateLock.acquire();
+
+ // Take ownership
+ assert(_owner == ThreadOps::INVALID || _owner == self);
+
+ _owner = self;
+ _count++;
+
+ _stateLock.release();
+
+ return true;
+
+ }
+
+
+ void release() {
+
+ // Assume that release is only used by the owning thread, as it
+ // should be.
+ assert(_count != 0);
+ assert(_owner == ThreadOps::self());
+
+ _stateLock.acquire();
+
+ // If the lock was owned and the count has reached 0, give up
+ // ownership and release the blocking lock
+ if(--_count == 0) {
+
+ _owner = ThreadOps::INVALID;
+ _blockingLock.release();
+
+ }
+
+ _stateLock.release();
+
+ }
+
+
+}; /* FastRecursiveLock */
+
+} // namespace ZThread
+
+#endif
diff --git a/dep/src/zthread/vanilla/SimpleAtomicCount.cxx b/dep/src/zthread/vanilla/SimpleAtomicCount.cxx
new file mode 100644
index 00000000000..fc63d141d6a
--- /dev/null
+++ b/dep/src/zthread/vanilla/SimpleAtomicCount.cxx
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTATOMICCOUNTIMPL_H__
+#define __ZTATOMICCOUNTIMPL_H__
+
+#include "zthread/Guard.h"
+#include "../FastLock.h"
+
+#include <assert.h>
+
+namespace ZThread {
+
+typedef struct atomic_count_t {
+
+ FastLock lock;
+ unsigned long count;
+
+ atomic_count_t() : count(0) {}
+
+} ATOMIC_COUNT;
+
+AtomicCount::AtomicCount() {
+
+ ATOMIC_COUNT* c = new ATOMIC_COUNT;
+ _value = reinterpret_cast<void*>(c);
+
+}
+
+AtomicCount::~AtomicCount() {
+
+ ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
+ assert(c->count == 0);
+
+ delete c;
+
+}
+
+//! Postfix decrement and return the current value
+size_t AtomicCount::operator--(int) {
+
+ ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
+
+ Guard<FastLock> g(c->lock);
+ return c->count--;
+
+}
+
+//! Postfix increment and return the current value
+size_t AtomicCount::operator++(int) {
+
+ ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
+
+ Guard<FastLock> g(c->lock);
+ return c->count++;
+
+}
+
+//! Prefix decrement and return the current value
+size_t AtomicCount::operator--() {
+
+ ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
+
+ Guard<FastLock> g(c->lock);
+ return --c->count;
+
+}
+
+//! Prefix increment and return the current value
+size_t AtomicCount::operator++() {
+
+ ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
+
+ Guard<FastLock> g(c->lock);
+ return ++c->count;
+
+}
+
+};
+
+#endif // __ZTATOMICCOUNTIMPL_H__
diff --git a/dep/src/zthread/vanilla/SimpleRecursiveLock.h b/dep/src/zthread/vanilla/SimpleRecursiveLock.h
new file mode 100644
index 00000000000..f4f309218b6
--- /dev/null
+++ b/dep/src/zthread/vanilla/SimpleRecursiveLock.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTFASTRECURSIVELOCK_H__
+#define __ZTFASTRECURSIVELOCK_H__
+
+#include "../FastLock.h"
+#include "../ThreadOps.h"
+#include <assert.h>
+
+namespace ZThread {
+
+/**
+ * @class FastRecursiveLock
+ *
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T23:30:59-0400>
+ * @version 2.2.8
+ *
+ * This implementation of a FastRecursiveLock uses the which ever FastLock
+ * that is selected to create a recursive spin lock.
+ */
+class FastRecursiveLock : private NonCopyable {
+
+ FastLock _lock;
+
+ ThreadOps _owner;
+
+ volatile unsigned int _count;
+
+public:
+
+ inline FastRecursiveLock() : _owner(ThreadOps::INVALID), _count(0) {}
+
+ inline ~FastRecursiveLock() {
+
+ assert(_owner == ThreadOps::INVALID);
+ assert(_count == 0);
+
+ }
+
+ inline void acquire() {
+
+ ThreadOps self(ThreadOps::self());
+ bool wasLocked = false;
+
+ do {
+
+ _lock.acquire();
+
+ // If there is no owner, or the owner is the caller
+ // update the count
+ if(_owner == ThreadOps::INVALID || _owner == self) {
+
+ _owner = self;
+ _count++;
+
+ wasLocked = true;
+
+ }
+
+ _lock.release();
+
+ } while(!wasLocked);
+
+ assert(_owner == ThreadOps::self());
+
+ }
+
+ inline void release() {
+
+ assert(_owner == ThreadOps::self());
+
+ _lock.acquire();
+
+ if(--_count == 0)
+ _owner = ThreadOps::INVALID;
+
+ _lock.release();
+
+ }
+
+ inline bool tryAcquire(unsigned long timeout=0) {
+
+ ThreadOps self(ThreadOps::self());
+ bool wasLocked = false;
+
+ _lock.acquire();
+
+ if(_owner == ThreadOps::INVALID || _owner == self) {
+
+ _owner = self;
+ _count++;
+
+ wasLocked = true;
+
+ }
+
+ _lock.release();
+
+ assert(!wasLocked || _owner == ThreadOps::self());
+ return wasLocked;
+
+ }
+
+}; /* FastRecursiveLock */
+
+
+} // namespace ZThread
+
+#endif
diff --git a/dep/src/zthread/win32/AtomicCount.cxx b/dep/src/zthread/win32/AtomicCount.cxx
new file mode 100644
index 00000000000..84cbf8c3ddc
--- /dev/null
+++ b/dep/src/zthread/win32/AtomicCount.cxx
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTATOMICCOUNTIMPL_H__
+#define __ZTATOMICCOUNTIMPL_H__
+
+#include <windows.h>
+#include <assert.h>
+
+namespace ZThread {
+
+
+AtomicCount::AtomicCount() {
+
+ _value = reinterpret_cast<void*>(new LONG(0));
+
+}
+
+AtomicCount::~AtomicCount() {
+
+ assert(*reinterpret_cast<LPLONG>(_value) == 0);
+ delete reinterpret_cast<LPLONG>(_value);
+
+}
+
+void AtomicCount::increment() {
+
+ ::InterlockedIncrement(reinterpret_cast<LPLONG>(_value));
+
+}
+
+bool AtomicCount::decrement() {
+
+ LONG v = ::InterlockedDecrement(reinterpret_cast<LPLONG>(_value));
+ return static_cast<unsigned long>(v) == 0;
+
+}
+
+};
+
+#endif // __ZTATOMICCOUNTIMPL_H__
diff --git a/dep/src/zthread/win32/AtomicFastLock.h b/dep/src/zthread/win32/AtomicFastLock.h
new file mode 100644
index 00000000000..a714c03789f
--- /dev/null
+++ b/dep/src/zthread/win32/AtomicFastLock.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTFASTLOCK_H__
+#define __ZTFASTLOCK_H__
+
+#include "zthread/NonCopyable.h"
+#include <windows.h>
+#include <assert.h>
+
+namespace ZThread {
+
+
+/**
+ * @class FastLock
+ *
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T23:32:20-0400>
+ * @version 2.1.6
+ *
+ * This is the smallest and fastest synchronization object in the library.
+ * It is an implementation of fast mutex, an all or nothing exclusive
+ * lock. It should be used only where you need speed and are willing
+ * to sacrifice all the state & safety checking provided by the framework
+ * for speed.
+ *
+ * The current Platform SDK defines:
+ *
+ * LONG InterlockedExchange(LPLONG, LONG)
+ * LONG InterlockedCompareExchange(LPLONG, LONG, LONG, LONG)
+ *
+ * If your compiler complains about LPLONG not being implicitly casted to
+ * a PVOID, then you should get the SDK update from microsoft or use the
+ * WIN9X implementation of this class.
+ *
+ * ----
+ * Because Windows 95 and earlier can run on processors prior to the 486, they
+ * don't all support the CMPXCHG function, and so Windows 95 an earlier dont support
+ * InterlockedCompareExchange. For this, you should use the win9x implementation
+ * of this class
+ */
+class FastLock : private NonCopyable {
+
+#pragma pack(push, 8)
+ LONG volatile _lock;
+#pragma pack(pop)
+
+ public:
+
+ /**
+ * Create a new FastLock
+ */
+ inline FastLock() : _lock(0) { }
+
+
+ /**
+ * Destroy FastLock
+ */
+ inline ~FastLock() { assert(_lock == 0); }
+
+ /**
+ * Lock the fast Lock, no error check.
+ *
+ * @exception None
+ */
+ inline void acquire() {
+
+ while (::InterlockedCompareExchange(const_cast<LPLONG>(&_lock), 1, 0) != 0)
+ ::Sleep(0);
+
+ }
+
+
+ /**
+ * Release the fast Lock, no error check.
+ *
+ * @exception None
+ */
+ inline void release() {
+
+ ::InterlockedExchange(const_cast<LPLONG>(&_lock), (LONG)0);
+
+ }
+
+ /**
+ * Try to acquire an exclusive lock. No safety or state checks are performed.
+ * This function returns immediately regardless of the value of the timeout
+ *
+ * @param timeout Unused
+ * @return bool
+ * @exception Synchronization_Exception - not thrown
+ */
+ inline bool tryAcquire(unsigned long timeout=0) {
+
+ return ::InterlockedCompareExchange(const_cast<LPLONG>(&_lock), 1, 0) == 0;
+
+ }
+
+}; /* FastLock */
+
+
+};
+#endif
diff --git a/dep/src/zthread/win32/AtomicFastRecursiveLock.h b/dep/src/zthread/win32/AtomicFastRecursiveLock.h
new file mode 100644
index 00000000000..c6a61b03b5d
--- /dev/null
+++ b/dep/src/zthread/win32/AtomicFastRecursiveLock.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTFASTRECURSIVELOCK_H__
+#define __ZTFASTRECURSIVELOCK_H__
+
+#include "zthread/NonCopyable.h"
+#include <windows.h>
+#include <assert.h>
+
+namespace ZThread {
+
+
+/**
+ * @class FastRecursiveLock
+ *
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T23:32:34-0400>
+ * @version 2.1.6
+ *
+ * This is the smaller and faster implementation of a RecursiveLock.
+ * A single thread can acquire the mutex any number of times, but it
+ * must perform a release for each acquire(). Other threads are blocked
+ * until a thread has released all of its locks on the mutex.
+ *
+ * This particular implementation performs fewer safety checks. Like
+ * the FastLock implementation, any waiting caused by an acquire() request
+ * is not interruptable. This is so that the mutex can have the fastest
+ * response time for a time critical application while still having a good
+ * degree of reliability.
+ *
+ * TryEnterCriticalSection() does not work at all on some systems, so its
+ * not used.
+ *
+ *
+ * The current Platform SDK defines:
+ *
+ * LONG InterlockedExchange(LPLONG, LONG)
+ * LONG InterlockedCompareExchange(LPLONG, LONG, LONG, LONG)
+ *
+ * If your compiler complains about LPLONG not being implicitly casted to
+ * a PVOID, then you should get the SDK update from microsoft or use the
+ * WIN9X implementation of this class.
+ *
+ * ----
+ * Because Windows 95 and earlier can run on processors prior to the 486, they
+ * don't all support the CMPXCHG function, and so Windows 95 an earlier dont support
+ * InterlockedCompareExchange. If you define ZT_WIN9X, you'll get a version of the
+ * FastLock that uses the XCHG instruction
+ */
+class FastRecursiveLock : private NonCopyable {
+
+// Add def for mingw32 or other non-ms compiler to align on 64-bit
+// boundary
+#pragma pack(push, 8)
+ LONG volatile _lock;
+#pragma pack(pop)
+ LONG _count;
+
+ public:
+
+ /**
+ * Create a new FastRecursiveLock
+ */
+ inline FastRecursiveLock() : _lock(0), _count(0) { }
+
+
+ /**
+ * Destroy FastLock
+ */
+ inline ~FastRecursiveLock() {
+ assert(_lock == 0);
+ }
+
+ /**
+ * Lock the fast Lock, no error check.
+ *
+ * @exception None
+ */
+ inline void acquire() {
+
+ DWORD id = ::GetCurrentThreadId();
+
+ // Take ownership if the lock is free or owned by the calling thread
+ do {
+
+ DWORD owner = (DWORD)::InterlockedCompareExchange(const_cast<LPLONG>(&_lock), id, 0);
+ if(owner == 0 || owner == id)
+ break;
+
+ ::Sleep(0);
+
+ } while(1);
+
+ _count++;
+
+ }
+
+
+ /**
+ * Release the fast Lock, no error check.
+ *
+ * @exception None
+ */
+ inline void release() {
+
+ if(--_count == 0)
+ ::InterlockedExchange(const_cast<LPLONG>(&_lock), 0);
+
+ }
+
+ /**
+ * Try to acquire an exclusive lock. No safety or state checks are performed.
+ * This function returns immediately regardless of the value of the timeout
+ *
+ * @param timeout Unused
+ * @return bool
+ * @exception Synchronization_Exception - not thrown
+ */
+ inline bool tryAcquire(unsigned long timeout=0) {
+
+ DWORD id = ::GetCurrentThreadId();
+ DWORD owner = (DWORD)::InterlockedCompareExchange(const_cast<LPLONG>(&_lock), id, 0);
+
+ if(owner == 0 || owner == id) {
+ _count++;
+ return true;
+ }
+
+ return false;
+
+ }
+
+
+}; /* FastRecursiveLock */
+
+
+};
+#endif
diff --git a/dep/src/zthread/win32/FastLock.h b/dep/src/zthread/win32/FastLock.h
new file mode 100644
index 00000000000..2e9fe829af6
--- /dev/null
+++ b/dep/src/zthread/win32/FastLock.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTFASTLOCK_H__
+#define __ZTFASTLOCK_H__
+
+#include "zthread/Exceptions.h"
+#include "zthread/NonCopyable.h"
+#include "../ThreadOps.h"
+#include <windows.h>
+#include <assert.h>
+
+namespace ZThread {
+
+ /**
+ * @class FastLock
+ *
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T23:32:44-0400>
+ * @version 2.2.11
+ *
+ * This FastLock implementation is based on a Win32 Mutex
+ * object. This will perform better under high contention,
+ * but will not be as fast as the spin lock under reasonable
+ * circumstances.
+ */
+ class FastLock : private NonCopyable {
+
+ HANDLE _hMutex;
+#ifndef NDEBUG
+ volatile bool _locked;
+#endif
+
+ public:
+
+ /**
+ * Create a new FastLock
+ */
+ FastLock() {
+
+#ifndef NDEBUG
+ _locked = false;
+#endif
+
+ _hMutex = ::CreateMutex(0, 0, 0);
+ assert(_hMutex != NULL);
+ if(_hMutex == NULL)
+ throw Initialization_Exception();
+
+ }
+
+
+ ~FastLock() {
+ ::CloseHandle(_hMutex);
+ }
+
+ void acquire() {
+
+ if(::WaitForSingleObject(_hMutex, INFINITE) != WAIT_OBJECT_0) {
+ assert(0);
+ throw Synchronization_Exception();
+ }
+
+#ifndef NDEBUG
+
+ // Simulate deadlock to provide consistent behavior. This
+ // will help avoid errors when porting. Avoiding situations
+ // where a FastMutex mistakenly behaves as a recursive lock.
+
+ while(_locked)
+ ThreadOps::yield();
+
+ _locked = true;
+
+#endif
+
+ }
+
+ void release() {
+
+#ifndef NDEBUG
+ _locked = false;
+#endif
+
+ if(::ReleaseMutex(_hMutex) == 0) {
+ assert(0);
+ throw Synchronization_Exception();
+ }
+
+ }
+
+
+ bool tryAcquire(unsigned long timeout = 0) {
+
+ switch(::WaitForSingleObject(_hMutex, timeout)) {
+ case WAIT_OBJECT_0:
+
+#ifndef NDEBUG
+
+ // Simulate deadlock to provide consistent behavior. This
+ // will help avoid errors when porting. Avoiding situations
+ // where a FastMutex mistakenly behaves as a recursive lock.
+
+ while(_locked)
+ ThreadOps::yield();
+
+ _locked = true;
+
+#endif
+
+ return true;
+ case WAIT_TIMEOUT:
+ return false;
+ default:
+ break;
+ }
+
+ assert(0);
+ throw Synchronization_Exception();
+
+ }
+
+ };
+
+} // namespace ZThread
+
+#endif
diff --git a/dep/src/zthread/win32/FastRecursiveLock.h b/dep/src/zthread/win32/FastRecursiveLock.h
new file mode 100644
index 00000000000..e1a6e7cd692
--- /dev/null
+++ b/dep/src/zthread/win32/FastRecursiveLock.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTFASTRECURSIVELOCK_H__
+#define __ZTFASTRECURSIVELOCK_H__
+
+#include "zthread/Exceptions.h"
+#include "zthread/NonCopyable.h"
+#include <windows.h>
+#include <assert.h>
+
+namespace ZThread {
+
+
+/**
+ * @class FastRecursiveLock
+ *
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T23:32:56-0400>
+ * @version 2.2.11
+ *
+ * This FastRecursiveLock implementation is based on a Win32 Mutex
+ * object. This will perform better under high contention,
+ * but will not be as fast as the spin lock under reasonable
+ * circumstances.
+ */
+class FastRecursiveLock : private NonCopyable {
+
+ HANDLE _hMutex;
+ volatile unsigned int _count;
+
+ public:
+
+ /**
+ * Create a new FastRecursiveLock
+ */
+ FastRecursiveLock() : _count(0) {
+
+ _hMutex = ::CreateMutex(0, 0, 0);
+ assert(_hMutex != NULL);
+ if(_hMutex == NULL)
+ throw Initialization_Exception();
+
+ }
+
+
+ ~FastRecursiveLock() {
+ ::CloseHandle(_hMutex);
+ }
+
+
+ void acquire() {
+
+ if(::WaitForSingleObject(_hMutex, INFINITE) != WAIT_OBJECT_0) {
+ assert(0);
+ throw Synchronization_Exception();
+ }
+
+ }
+
+ void release() {
+
+ if(::ReleaseMutex(_hMutex) == 0) {
+ assert(0);
+ throw Synchronization_Exception();
+ }
+
+ }
+
+ bool tryAcquire(unsigned long) {
+
+ switch(::WaitForSingleObject(_hMutex, 0)) {
+ case WAIT_OBJECT_0:
+ return true;
+ case WAIT_TIMEOUT:
+ return false;
+ default:
+ break;
+ }
+
+ assert(0);
+ throw Synchronization_Exception();
+
+ }
+
+}; /* FastRecursiveLock */
+
+} // namespace ZThread
+
+#endif
diff --git a/dep/src/zthread/win32/Monitor.cxx b/dep/src/zthread/win32/Monitor.cxx
new file mode 100644
index 00000000000..6e69487c054
--- /dev/null
+++ b/dep/src/zthread/win32/Monitor.cxx
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "Monitor.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+using namespace ZThread;
+
+Monitor::Monitor() : _owner(0), _waiting(false) {
+
+ _handle = ::CreateEvent(0, TRUE, FALSE, 0);
+ if(_handle == NULL) {
+ assert(0);
+ }
+
+}
+
+Monitor::~Monitor() {
+
+ assert(!_waiting);
+
+ ::CloseHandle(_handle);
+
+}
+
+Monitor::STATE Monitor::wait(unsigned long ms) {
+
+ // Update the owner on first use. The owner will not change, each
+ // thread waits only on a single Monitor and a Monitor is never
+ // shared
+ if(_owner == 0)
+ _owner = ::GetCurrentThreadId();
+
+ STATE state; //(INVALID);
+
+ // Serialize access to the state of the Monitor
+ // and test the state to determine if a wait is needed.
+ _waitLock.acquire();
+
+ if(pending(ANYTHING)) {
+
+ // Return without waiting when possible
+ state = next();
+
+ _waitLock.release();
+ return state;
+
+ }
+ // Unlock the external lock if a wait() is probably needed.
+ // Access to the state is still serial.
+ _lock.release();
+
+ // Wait for a transition in the state that is of interest, this
+ // allows waits to exclude certain flags (e.g. INTERRUPTED)
+ // for a single wait() w/o actually discarding those flags -
+ // they will remain set until a wait interested in those flags
+ // occurs.
+ // if(!currentState(interest)) {
+
+ // Wait, ignoring signals
+ _waiting = true;
+
+ // Block until the event is set.
+ _waitLock.release();
+
+ // The event is manual reset so this lack of atmoicity will not
+ // be an issue
+
+ DWORD dwResult =
+ ::WaitForSingleObject(_handle, ((ms == 0) ? INFINITE : (DWORD)ms));
+
+ // Reacquire serialized access to the state
+ _waitLock.acquire();
+
+ // Awaken only when the event is set or the timeout expired
+ assert(dwResult == WAIT_OBJECT_0 || dwResult == WAIT_TIMEOUT);
+
+ if(dwResult == WAIT_TIMEOUT)
+ push(TIMEDOUT);
+
+ // Get the next available STATE
+ state = next();
+ _waiting = false;
+
+ ::ResetEvent(_handle);
+
+ // Acquire the internal lock & release the external lock
+ _waitLock.release();
+
+ // Reaquire the external lock, keep from deadlocking threads calling
+ // notify(), interrupt(), etc.
+ _lock.acquire();
+
+ return state;
+
+}
+
+
+bool Monitor::interrupt() {
+
+ // Serialize access to the state
+ _waitLock.acquire();
+
+ bool wasInterruptable = !pending(INTERRUPTED);
+ bool hadWaiter = _waiting;
+
+ if(wasInterruptable) {
+
+ // Update the state & wake the waiter if there is one
+ push(INTERRUPTED);
+
+ wasInterruptable = false;
+
+ if(hadWaiter && !masked(Monitor::INTERRUPTED)) {
+
+ // Blocked on a synchronization object
+ if(::SetEvent(_handle) == FALSE) {
+ assert(0);
+ }
+
+ } else
+ wasInterruptable = !(_owner == ::GetCurrentThreadId());
+
+ }
+
+ _waitLock.release();
+
+ // Only returns true when an interrupted thread is not currently blocked
+ return wasInterruptable;
+
+}
+
+bool Monitor::isInterrupted() {
+
+ // Serialize access to the state
+ _waitLock.acquire();
+
+ bool wasInterrupted = pending(INTERRUPTED);
+ clear(INTERRUPTED);
+
+ _waitLock.release();
+
+ return wasInterrupted;
+
+}
+
+
+bool Monitor::notify() {
+
+ // Serialize access to the state
+ _waitLock.acquire();
+
+ bool wasNotifyable = !pending(INTERRUPTED);
+
+ if(wasNotifyable) {
+
+ // Set the flag and wake the waiter if there
+ // is one
+ push(SIGNALED);
+
+ // If there is a waiter then send the signal.
+ if(_waiting)
+ if(::SetEvent(_handle) == FALSE) {
+ assert(0);
+ }
+
+ }
+
+ _waitLock.release();
+
+ return wasNotifyable;
+
+}
+
+
+bool Monitor::cancel() {
+
+ // Serialize access to the state
+ _waitLock.acquire();
+
+ bool wasInterrupted = !pending(INTERRUPTED);
+ bool hadWaiter = _waiting;
+
+ push(CANCELED);
+
+ if(wasInterrupted) {
+
+ // Update the state & wake the waiter if there is one
+ push(INTERRUPTED);
+
+ // If there is a waiter then send the signal.
+ if(hadWaiter && !masked(Monitor::INTERRUPTED))
+ if(::SetEvent(_handle) == FALSE) {
+ assert(0);
+ }
+
+ }
+
+ _waitLock.release();
+
+ return wasInterrupted;
+
+}
+
+bool Monitor::isCanceled() {
+
+ // Serialize access to the state
+ _waitLock.acquire();
+
+ bool wasCanceled = examine(CANCELED);
+
+ if(_owner == ::GetCurrentThreadId())
+ clear(INTERRUPTED);
+
+ _waitLock.release();
+
+ return wasCanceled;
+
+}
+
diff --git a/dep/src/zthread/win32/Monitor.h b/dep/src/zthread/win32/Monitor.h
new file mode 100644
index 00000000000..7073343b7f8
--- /dev/null
+++ b/dep/src/zthread/win32/Monitor.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTMONITOR_H__
+#define __ZTMONITOR_H__
+
+#include "../Status.h"
+#include "../FastLock.h"
+
+namespace ZThread {
+
+/**
+ * @class Monitor
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T23:33:10-0400>
+ * @version 2.2.11
+ */
+class Monitor : public Status, private NonCopyable {
+
+ //! Serialize access to external objects
+ FastLock _lock;
+
+ //! Event used to block thread
+ HANDLE _handle;
+
+ //! Serialize access to the internal state of the monitor
+ FastLock _waitLock;
+
+ //! Owning thread
+ DWORD _owner;
+
+ //! Waiting flag, to avoid uneccessary signals
+ volatile bool _waiting;
+
+ //! State of the monitor
+ volatile int _state;
+
+ public:
+
+ //! Create a new monitor.
+ Monitor();
+
+ //! Destroy the monitor.
+ ~Monitor();
+
+ //! Acquire the external lock for this monitor.
+ inline void acquire() {
+ _lock.acquire();
+ }
+
+ //! Try to acquire the external lock for this monitor.
+ inline bool tryAcquire() {
+ return _lock.tryAcquire();
+ }
+
+ //! Release the external lock for this monitor.
+ inline void release() {
+ _lock.release();
+ }
+
+ /**
+ * Wait for a state change and atomically unlock the external lock.
+ * Blocks for an indefinent amount of time.
+ *
+ * @return INTERRUPTED if the wait was ended by a interrupt()
+ * or SIGNALED if the wait was ended by a notify()
+ *
+ * @post the external lock is always acquired before this function returns
+ */
+ inline STATE wait() {
+ return wait(0);
+ }
+
+ /**
+ * Wait for a state change and atomically unlock the external lock.
+ * May blocks for an indefinent amount of time.
+ *
+ * @param timeout - maximum time to block (milliseconds) or 0 to
+ * block indefinently
+ *
+ * @return INTERRUPTED if the wait was ended by a interrupt()
+ * or TIMEDOUT if the maximum wait time expired.
+ * or SIGNALED if the wait was ended by a notify()
+ *
+ * @post the external lock is always acquired before this function returns
+ */
+ STATE wait(unsigned long timeout);
+
+ /**
+ * Interrupt this monitor. If there is a thread blocked on this monitor object
+ * it will be signaled and released. If there is no waiter, a flag is set and
+ * the next attempt to wait() will return INTERRUPTED w/o blocking.
+ *
+ * @return false if the thread was previously INTERRUPTED.
+ */
+ bool interrupt();
+
+ /**
+ * Notify this monitor. If there is a thread blocked on this monitor object
+ * it will be signaled and released. If there is no waiter, a flag is set and
+ * the next attempt to wait() will return SIGNALED w/o blocking, if no other
+ * flag is set.
+ *
+ * @return false if the thread was previously INTERRUPTED.
+ */
+ bool notify();
+
+ /**
+ * Check the state of this monitor, clearing the INTERRUPTED status if set.
+ *
+ * @return bool true if the monitor was INTERRUPTED.
+ * @post INTERRUPTED flag cleared if the calling thread owns the monitor.
+ */
+ bool isInterrupted();
+
+ /**
+ * Mark the Status CANCELED, and INTERRUPT the montor.
+ *
+ * @see interrupt()
+ */
+ bool cancel();
+
+ /**
+ * Test the CANCELED Status, clearing the INTERRUPTED status if set.
+ *
+ * @return bool
+ */
+ bool isCanceled();
+
+};
+
+};
+
+#endif
diff --git a/dep/src/zthread/win32/PerformanceCounterStrategy.h b/dep/src/zthread/win32/PerformanceCounterStrategy.h
new file mode 100644
index 00000000000..95b526830b3
--- /dev/null
+++ b/dep/src/zthread/win32/PerformanceCounterStrategy.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTTIMESTRATEGY_H__
+#define __ZTTIMESTRATEGY_H__
+
+#include <assert.h>
+#include <windows.h>
+
+namespace ZThread {
+
+/**
+ * @class PerformanceCounterStrategy
+ *
+ * Implement a strategy for time operatons based on
+ * Windows QueryPerformanceXXX() functions.
+ * This only (erroneously) considers the lower 32 bits.
+ */
+class TimeStrategy {
+
+ unsigned long _secs;
+ unsigned long _millis;
+
+public:
+
+ TimeStrategy() {
+
+ // Keep track of the relative time the program started
+ static LARGE_INTEGER i;
+ static BOOL valid(::QueryPerformanceCounter(&i));
+
+ assert(valid == TRUE);
+
+ LARGE_INTEGER j;
+ ::QueryPerformanceCounter(&j);
+
+ j.LowPart -= i.LowPart;
+ j.LowPart /= frequency();
+
+ // Mask off the high bits
+ _millis = (unsigned long)j.LowPart / 1000;
+ _secs = (unsigned long)j.LowPart - _millis;
+
+ }
+
+ unsigned long seconds() const {
+ return _secs;
+ }
+
+ unsigned long milliseconds() const {
+ return _millis;
+ }
+
+ unsigned long seconds(unsigned long s) {
+
+ unsigned long z = seconds();
+
+ _secs = s;
+ return z;
+
+ }
+
+ unsigned long milliseconds(unsigned long ms) {
+
+ unsigned long z = milliseconds();
+
+ _millis = ms;
+ return z;
+
+ }
+
+private:
+
+ // Get the frequency
+ static DWORD frequency() {
+
+ static LARGE_INTEGER i;
+ static BOOL valid(::QueryPerformanceFrequency(&i));
+
+ assert(valid == TRUE);
+ return i.LowPart;
+
+ }
+
+};
+
+};
+
+#endif // __ZTTIMESTRATEGY_H__
diff --git a/dep/src/zthread/win32/TSS.h b/dep/src/zthread/win32/TSS.h
new file mode 100644
index 00000000000..2400830f06a
--- /dev/null
+++ b/dep/src/zthread/win32/TSS.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTTSS_H__
+#define __ZTTSS_H__
+
+#include <windows.h>
+
+namespace ZThread {
+
+ /**
+ * @class TSS
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-27T14:18:43-0400>
+ * @version 2.3.0
+ *
+ * An abstraction for dealing with WIN32 thread specific storage (tss).
+ * Provides get/set and creation/destruction.
+ */
+ template <typename T>
+ class TSS {
+
+ DWORD _key;
+ bool _valid;
+
+ public:
+
+ /**
+ * Create a new object for accessing tss. The def
+ */
+ TSS() {
+
+ _key = ::TlsAlloc();
+ _valid = (_key != 0xFFFFFFFF);
+
+ }
+
+ /**
+ * Destroy the underlying supoprt for accessing tss with this
+ * object.
+ */
+ virtual ~TSS() {
+
+ if(_valid)
+ ::TlsFree(_key);
+
+ }
+
+ /**
+ * Get the value stored in tss.
+ *
+ * @return T
+ *
+ * @exception InvalidOp_exception thrown when the tss is not properly initialized
+ */
+ inline T get() const {
+
+ if(!_valid)
+ throw InvalidOp_Exception();
+
+ return static_cast<T>(::TlsGetValue(_key));
+
+ }
+
+ /**
+ * Store a value in tss.
+ *
+ * @param value T
+ * @return T old value
+ *
+ * @exception InvalidOp_exception thrown when the tss is not properly initialized
+ */
+ inline T set(T value) const {
+
+ T oldValue = get();
+ ::TlsSetValue(_key, value);
+
+ return oldValue;
+
+ }
+
+
+ };
+
+}
+
+#endif
+
+
diff --git a/dep/src/zthread/win32/ThreadOps.cxx b/dep/src/zthread/win32/ThreadOps.cxx
new file mode 100644
index 00000000000..6e8fb8d3b71
--- /dev/null
+++ b/dep/src/zthread/win32/ThreadOps.cxx
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "ThreadOps.h"
+#include "zthread/Runnable.h"
+#include <process.h>
+
+namespace ZThread {
+
+const ThreadOps ThreadOps::INVALID(0);
+
+/**
+ * Detect OS at runtime and attempt to locate the SwitchToThread
+ * function, which will assist in making the spin lock implementation
+ * which use ThreadOps::yield() a bit fairer.
+ */
+class YieldOps {
+
+ typedef BOOL (*Yield)(void);
+ Yield _fnYield;
+
+public:
+
+ YieldOps() : _fnYield(NULL) {
+
+ OSVERSIONINFO v;
+ v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+ if(::GetVersionEx(&v) && (v.dwPlatformId == VER_PLATFORM_WIN32_NT)) {
+
+ // Uses GetModuleHandle() so the reference count on the dll is
+ // not affected. There is a warning about race conditions involving
+ // this function being called as FreeLibrary() completes; however
+ // nearly all win32 applications load this particular and will keep it
+ // in memory until the process exits.
+ HINSTANCE hInst = ::GetModuleHandle("Kernel32.dll");
+ if(hInst != NULL)
+ _fnYield = (Yield)::GetProcAddress(hInst, "SwitchToThread");
+
+ // REMIND: possibly need to use _T() macro for these strings
+ }
+
+ }
+
+ bool operator()() {
+
+ // Attempt to yield using the best function available
+ if(!_fnYield || !_fnYield())
+ ::Sleep(0);
+
+ return true;
+
+ }
+
+};
+
+bool ThreadOps::join(ThreadOps* ops) {
+
+ assert(ops);
+ assert(ops->_tid != 0);
+ assert(ops->_hThread != NULL);
+
+ if(::WaitForSingleObjectEx(ops->_hThread, INFINITE, FALSE) != WAIT_OBJECT_0)
+ return false;
+
+ ::CloseHandle(ops->_hThread);
+ ops->_hThread = NULL;
+
+ return true;
+
+}
+
+bool ThreadOps::yield() {
+
+ static YieldOps yielder;
+
+ yielder();
+
+ return true;
+
+}
+
+bool ThreadOps::setPriority(ThreadOps* impl, Priority p) {
+
+ assert(impl);
+
+#if !defined(ZTHREAD_DISABLE_PRIORITY)
+
+ bool result;
+
+ // Convert
+ int n;
+ switch(p) {
+ case Low:
+ n = THREAD_PRIORITY_BELOW_NORMAL;
+ break;
+ case High:
+ n = THREAD_PRIORITY_ABOVE_NORMAL;
+ break;
+ case Medium:
+ default:
+ n = THREAD_PRIORITY_NORMAL;
+ }
+
+
+ result = (::SetThreadPriority(impl->_hThread, n) != THREAD_PRIORITY_ERROR_RETURN);
+ return result;
+
+#else
+
+ return true;
+
+#endif
+
+}
+
+bool ThreadOps::getPriority(ThreadOps* impl, Priority& p) {
+
+ assert(impl);
+ bool result = true;
+
+#if !defined(ZTHREAD_DISABLE_PRIORITY)
+
+ // Convert to one of the PRIORITY values
+ switch(::GetThreadPriority(impl->_hThread)) {
+ case THREAD_PRIORITY_ERROR_RETURN:
+ result = false;
+ case THREAD_PRIORITY_BELOW_NORMAL:
+ p = Low;
+ break;
+ case THREAD_PRIORITY_ABOVE_NORMAL:
+ p = High;
+ break;
+ case THREAD_PRIORITY_NORMAL:
+ default:
+ p = Medium;
+ }
+
+#endif
+
+ return result;
+
+}
+
+
+bool ThreadOps::spawn(Runnable* task) {
+
+// Start the thread.
+#if defined(HAVE_BEGINTHREADEX)
+ _hThread = (HANDLE)::_beginthreadex(0, 0, &_dispatch, task, 0, (unsigned int*)&_tid);
+#else
+ _hThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&_dispatch, task, 0, (DWORD*)&_tid);
+#endif
+
+ return _hThread != NULL;
+
+}
+
+unsigned int __stdcall ThreadOps::_dispatch(void *arg) {
+
+ Runnable* task = reinterpret_cast<Runnable*>(arg);
+ assert(task);
+
+ // Run the task from the correct context
+ task->run();
+
+ // Exit the thread
+#if defined(HAVE_BEGINTHREADEX)
+ ::_endthreadex(0);
+#else
+ ExitThread(0);
+#endif
+
+ return 0;
+
+}
+
+}
diff --git a/dep/src/zthread/win32/ThreadOps.h b/dep/src/zthread/win32/ThreadOps.h
new file mode 100644
index 00000000000..4a3eeac2ed9
--- /dev/null
+++ b/dep/src/zthread/win32/ThreadOps.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTTHREADOPS_H__
+#define __ZTTHREADOPS_H__
+
+#include "zthread/Priority.h"
+#include <windows.h>
+#include <assert.h>
+
+namespace ZThread {
+
+class Runnable;
+
+/**
+ * @class ThreadOps
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T23:33:59-0400>
+ * @version 2.2.8
+ *
+ * This class is an abstraction used to perform various operations on a
+ * native WIN32 thread.
+ */
+class ThreadOps {
+
+ //! Dispatch function for native thread
+ static unsigned int __stdcall _dispatch(void*);
+
+ //! TID while the thread is executing.
+ HANDLE _hThread;
+ DWORD _tid;
+
+ ThreadOps(DWORD tid) : _tid(tid) { }
+
+ public:
+
+ const static ThreadOps INVALID;
+
+ /**
+ * Create a new ThreadOps to represent a native thread.
+ */
+ ThreadOps() : _tid(0), _hThread(NULL) {}
+
+
+ inline bool operator==(const ThreadOps& ops) const {
+ return _tid == ops._tid;
+ }
+
+
+ static ThreadOps self() {
+ return ThreadOps(::GetCurrentThreadId());
+ }
+
+ /**
+ * Update the native tid for this thread so it matches the current
+ * thread.
+ */
+ static void activate(ThreadOps* ops) {
+
+ assert(ops);
+ assert(ops->_tid == 0);
+
+ ops->_tid = ::GetCurrentThreadId();
+
+ }
+
+ /**
+ * Test if this object representative of the currently executing
+ * native thread.
+ *
+ * @return bool true if successful
+ */
+ static bool isCurrent(ThreadOps* ops) {
+
+ assert(ops);
+
+ return ops->_tid == ::GetCurrentThreadId();
+
+ }
+
+ /**
+ * Join a native thread.
+ *
+ * @return bool true if successful
+ */
+ static bool join(ThreadOps*);
+
+ /**
+ * Force the current native thread to yield, letting the scheduler
+ * give the CPU time to another thread.
+ *
+ * @return bool true if successful
+ */
+ static bool yield();
+
+ /**
+ * Set the priority for the native thread if supported by the
+ * system.
+ *
+ * @param PRIORITY requested priority
+ * @return bool false if unsuccessful
+ */
+ static bool setPriority(ThreadOps*, Priority);
+
+ /**
+ * Set the priority for the native thread if supported by the
+ * system.
+ *
+ * @param Thread::PRIORITY& current priority
+ * @return bool false if unsuccessful
+ */
+ static bool getPriority(ThreadOps*, Priority&);
+
+protected:
+
+ /**
+ * Spawn a native thread.
+ *
+ * @param ThreadImpl* parent thread
+ * @param ThreadImpl* child thread being started.
+ * @param Runnable* task being executed.
+ *
+ * @return bool true if successful
+ */
+ bool spawn(Runnable*);
+
+
+};
+
+
+}
+
+#endif
diff --git a/dep/src/zthread/win9x/AtomicCount.cxx b/dep/src/zthread/win9x/AtomicCount.cxx
new file mode 100644
index 00000000000..2bf07dcd2e7
--- /dev/null
+++ b/dep/src/zthread/win9x/AtomicCount.cxx
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTATOMICCOUNTIMPL_H__
+#define __ZTATOMICCOUNTIMPL_H__
+
+#include <windows.h>
+#include <assert.h>
+
+namespace ZThread {
+
+typedef struct atomic_count_t {
+
+ CRITICAL_SECTION cs;
+ size_t count;
+
+ atomic_count_t() : count(0) {}
+
+} ATOMIC_COUNT;
+
+AtomicCount::AtomicCount() {
+
+ ATOMIC_COUNT* c = new ATOMIC_COUNT;
+ _value = reinterpret_cast<void*>(c);
+ ::InitializeCriticalSection(&c->cs);
+
+}
+
+AtomicCount::~AtomicCount() {
+
+ ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
+ assert(c->count == 0);
+ ::DeleteCriticalSection(&c->cs);
+ delete c;
+
+}
+
+//! Postfix decrement and return the current value
+size_t AtomicCount::operator--(int) {
+
+ ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
+ size_t value;
+
+ ::EnterCriticalSection(&c->cs);
+ value = c->count--;
+ ::LeaveCriticalSection(&c->cs);
+
+ return value;
+
+}
+
+//! Postfix increment and return the current value
+size_t AtomicCount::operator++(int) {
+
+ ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
+ size_t value;
+
+ ::EnterCriticalSection(&c->cs);
+ value = c->count++;
+ ::LeaveCriticalSection(&c->cs);
+
+ return value;
+
+}
+
+//! Prefix decrement and return the current value
+size_t AtomicCount::operator--() {
+
+ ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
+ size_t value;
+
+ ::EnterCriticalSection(&c->cs);
+ value = --c->count;
+ ::LeaveCriticalSection(&c->cs);
+
+ return value;
+
+}
+
+//! Prefix increment and return the current value
+size_t AtomicCount::operator++() {
+
+ ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
+ size_t value;
+
+ ::EnterCriticalSection(&c->cs);
+ value = ++c->count;
+ ::LeaveCriticalSection(&c->cs);
+
+ return value;
+
+}
+
+};
+
+#endif // __ZTATOMICCOUNTIMPL_H__
diff --git a/dep/src/zthread/win9x/AtomicFastLock.h b/dep/src/zthread/win9x/AtomicFastLock.h
new file mode 100644
index 00000000000..5b50a9c7337
--- /dev/null
+++ b/dep/src/zthread/win9x/AtomicFastLock.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2005, Eric Crahen
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifndef __ZTFASTLOCK_H__
+#define __ZTFASTLOCK_H__
+
+#include "zthread/NonCopyable.h"
+#include <windows.h>
+#include <assert.h>
+
+namespace ZThread {
+
+
+/**
+ * @class FastLock
+ *
+ * @author Eric Crahen <http://www.code-foo.com>
+ * @date <2003-07-16T23:31:51-0400>
+ * @version 2.2.0
+ *
+ * This uses a custom spin lock based on the older swap & compare approach
+ * using the XCHG instruction. You should only use this is you *absolutely* need
+ * to use an older system, like Windows 95. If you can, use the Win32 version.
+ *
+ * Because Windows 95 and earlier can run on processors prior to the 486, they
+ * don't all support the CMPXCHG function, and so Windows 95 an earlier dont support
+ * InterlockedCompareExchange.
+ *
+ * This is asm inlined for microsoft visual c, it needs to be changed in order to
+ * compile with gcc, or another win32 compiler - but more likely than not you'll
+ * be using the Win32 version on those compilers and this won't be a problem.
+ */
+class FastLock : private NonCopyable {
+
+// Add def for mingw32 or other non-ms compiler to align on 32-bit boundary
+#pragma pack(push, 4)
+ unsigned char volatile _lock;
+#pragma pack(pop)
+
+ public:
+
+ /**
+ * Create a new FastLock
+ */
+ inline FastLock() : _lock(0) { }
+
+
+ inline ~FastLock() {
+ assert(_lock == 0);
+ }
+
+ inline void acquire() {
+
+ DWORD dw = (DWORD)&_lock;
+
+ _asm { // swap & compare
+ spin_lock:
+
+ mov al, 1
+ mov esi, dw
+ xchg [esi], al
+ and al,al
+ jz spin_locked
+ }
+
+ ::Sleep(0);
+
+ _asm {
+ jmp spin_lock
+ spin_locked:
+ }
+
+ }
+
+ inline void release() {
+
+ DWORD dw = (DWORD)&_lock;
+
+ _asm {
+ mov al, 0
+ mov esi, dw
+ xchg [esi], al
+ }
+
+
+ }
+
+ inline bool tryAcquire(unsigned long timeout=0) {
+
+ volatile DWORD dw = (DWORD)&_lock;
+ volatile DWORD result;
+
+ _asm {
+
+ mov al, 1
+ mov esi, dw
+ xchg [esi], al
+ and al,al
+ mov esi, result
+ xchg [esi], al
+ }
+
+ return result == 0;
+
+ }
+
+}; /* Fast Lock */
+
+} // namespace ZThread
+
+#endif