diff options
Diffstat (limited to 'dep/include/zthread')
45 files changed, 7663 insertions, 0 deletions
diff --git a/dep/include/zthread/AtomicCount.h b/dep/include/zthread/AtomicCount.h new file mode 100644 index 00000000000..ea042a7feb2 --- /dev/null +++ b/dep/include/zthread/AtomicCount.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 __ZTATOMICCOUNT_H__ +#define __ZTATOMICCOUNT_H__ + +#include <cstdlib> + +#include "zthread/Config.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + /** + * @class AtomicCount + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T09:41:55-0400> + * @version 2.3.0 + * + * This class provides an interface to a small integer whose value can be + * incremented or decremented atomically. It's designed to be as simple and + * lightweight as possible so that it can be used cheaply to create reference + * counts. + */ + class ZTHREAD_API AtomicCount : public NonCopyable { + + void* _value; + + public: + + //! Create a new AtomicCount, initialized to a value of 1 + AtomicCount(); + + //! Destroy a new AtomicCount + ~AtomicCount(); + + //! Postfix decrement and return the current value + size_t operator--(int); + + //! Postfix increment and return the current value + size_t operator++(int); + + //! Prefix decrement and return the current value + size_t operator--(); + + //! Prefix increment and return the current value + size_t operator++(); + + + }; /* AtomicCount */ + + +} // namespace ZThread + +#endif // __ZTATOMICCOUNT_H__ diff --git a/dep/include/zthread/Barrier.h b/dep/include/zthread/Barrier.h new file mode 100644 index 00000000000..6aaafa93678 --- /dev/null +++ b/dep/include/zthread/Barrier.h @@ -0,0 +1,328 @@ +/* + * 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 __ZTBARRIER_H__ +#define __ZTBARRIER_H__ + +#include "zthread/Condition.h" +#include "zthread/Guard.h" +#include "zthread/Waitable.h" +#include "zthread/Runnable.h" + +namespace ZThread { + + /** + * @class Barrier + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T09:54:01-0400> + * @version 2.2.1 + * + * A Barrier is a Waitable object that serves as synchronization points for + * a set of threads. A Barrier is constructed for a fixed number (<i>N</i>) of threads. + * Threads attempting to wait() on a Barrier (<i> 1 - N</i>) will block until the <i>N</i>th + * thread arrives. The <i>N</i>th thread will awaken all the the others. + * + * An optional Runnable command may be associated with the Barrier. This will be run() + * when the <i>N</i>th thread arrives and Barrier is not broken. + * + * <b>Error Checking</b> + * + * A Barrier uses an all-or-nothing. All threads involved must successfully + * meet at Barrier. If any one of those threads leaves before all the threads + * have (as the result of an error or exception) then all threads present at + * the Barrier will throw BrokenBarrier_Exception. + * + * A broken Barrier will cause all threads attempting to wait() on it to + * throw a BrokenBarrier_Exception. + * + * A Barrier will remain 'broken', until it is manually reset(). + */ + template <unsigned int Count, class LockType> + class Barrier : public Waitable, private NonCopyable { + + //! Broken flag + bool _broken; + //! Task flag + bool _haveTask; + //! Thread count + unsigned int _count; + //! Wait generation + unsigned int _generation; + //! Serialize access + LockType _lock; + //! Signaled when all thread arrive + Condition _arrived; + //! Command to run when all the thread arrive + Task _task; + + public: + + //! Create a Barrier + Barrier() + : _broken(false), _haveTask(false), _count(Count), _generation(0), _arrived(_lock), _task(0) { } + + /** + * Create a Barrier that executes the given task when all threads arrive + * without error + * + * @param task Task to associate with this Barrier + */ + Barrier(const Task& task) + : _broken(false), _haveTask(true), _count(Count), _generation(0), _arrived(_lock), + _task(task) { } + + //! Destroy this Barrier + virtual ~Barrier() {} + + /** + * Enter barrier and wait for the other threads to arrive. This can block for an indefinite + * amount of time. + * + * @exception BrokenBarrier_Exception thrown when any thread has left a wait on this + * Barrier as a result of an error. + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending a wait + * for one thread and breaking the barrier for all threads + * + * @see Waitable::wait() + * + * @post If no exception was thrown, all threads have successfully arrived + * @post If an exception was thrown, the barrier is broken + */ + virtual void wait() { + + Guard<LockType> g(_lock); + + if(_broken) + throw BrokenBarrier_Exception(); + + // Break the barrier if an arriving thread is interrupted + if(Thread::interrupted()) { + + // Release the other waiter, propagate the exception + _arrived.broadcast(); + _broken = true; + + throw Interrupted_Exception(); + + } + + if(--_count == 0) { + + // Wake the other threads if this was the last + // arriving thread + _arrived.broadcast(); + + // Try to run the associated task, if it throws then + // break the barrier and propagate the exception + try { + + if(_task) + _task->run(); + + _generation++; + + } catch(Synchronization_Exception&) { + + _broken = true; + throw; + + } catch(...) { assert(0); } + + } else { + + int myGeneration = _generation; + + try { + + // Wait for the other threads to arrive + _arrived.wait(); + + } catch(Interrupted_Exception&) { + + // Its possible for a thread to be interrupted before the + // last thread arrives. If the interrupted thread hasn't + // resumed, then just propagate the interruption + + if(myGeneration != _generation) + Thread().interrupt(); + + else _broken = true; + + } catch(Synchronization_Exception&) { + + // Break the barrier and propagate the exception + _broken = true; + throw; + + } + + // If the thread woke because it was notified by the thread + // that broke the barrier, throw. + if(_broken) + throw BrokenBarrier_Exception(); + + } + + } + + /** + * Enter barrier and wait for the other threads to arrive. This can block up to the + * amount of time specified with the timeout parameter. The barrier will not break + * if a thread leaves this function due to a timeout. + * + * @param timeout maximum amount of time, in milliseconds, to wait before + * + * @return + * - <em>true</em> if the set of tasks being wait for complete before + * <i>timeout</i> milliseconds elapse. + * - <em>false</em> otherwise. + * + * @exception BrokenBarrier_Exception thrown when any thread has left a wait on this + * Barrier as a result of an error. + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending a wait + * for one thread and breaking the barrier for all threads + * + * @see Waitable::wait(unsigned long timeout) + * + * @post If no exception was thrown, all threads have successfully arrived + * @post If an exception was thrown, the barrier is broken + */ + virtual bool wait(unsigned long timeout) { + + Guard<LockType> g(_lock); + + if(_broken) + throw BrokenBarrier_Exception(); + + // Break the barrier if an arriving thread is interrupted + if(Thread::interrupted()) { + + // Release the other waiter, propagate the exception + _arrived.broadcast(); + _broken = true; + + throw Interrupted_Exception(); + + } + + + if(--_count == 0) { + + // Wake the other threads if this was the last + // arriving thread + _arrived.broadcast(); + + // Try to run the associated task, if it throws then + // break the barrier and propagate the exception + try { + + if(_task) + _task->run(); + + _generation++; + + } catch(Synchronization_Exception&) { + + _broken = true; + throw; + + } catch(...) { assert(0); } + + } else { + + int myGeneration = _generation; + + try { + + // Wait for the other threads to arrive + if(!_arrived.wait(timeout)) + _broken = true; + + } catch(Interrupted_Exception&) { + + // Its possible for a thread to be interrupted before the + // last thread arrives. If the interrupted thread hasn't + // resumed, then just propagate the interruption + + if(myGeneration != _generation) + Thread().interrupt(); + + else _broken = true; + + } catch(Synchronization_Exception&) { + + // Break the barrier and propagate the exception + _broken = true; + throw; + + } + + // If the thread woke because it was notified by the thread + // that broke the barrier, throw. + if(_broken) + throw BrokenBarrier_Exception(); + + } + + return true; + + } + + /** + * Break the Barrier ending the wait for any threads that were waiting on + * the barrier. + * + * @post the Barrier is broken, all waiting threads will throw the + * BrokenBarrier_Exception + */ + void shatter() { + + Guard<LockType> g(_lock); + + _broken = true; + _arrived.broadcast(); + + } + + /** + * Reset the Barrier. + * + * @post the Barrier is no longer Broken and can be used again. + */ + void reset() { + + Guard<LockType> g(_lock); + + _broken = false; + _generation++; + _count = Count; + + } + + }; + + +} // namespace ZThread + +#endif // __ZTBARRIER_H__ diff --git a/dep/include/zthread/BiasedReadWriteLock.h b/dep/include/zthread/BiasedReadWriteLock.h new file mode 100644 index 00000000000..b1de74292cf --- /dev/null +++ b/dep/include/zthread/BiasedReadWriteLock.h @@ -0,0 +1,319 @@ +/* + * 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 __ZTBIASEDREADWRITELOCK_H__ +#define __ZTBIASEDREADWRITELOCK_H__ + +#include "zthread/ReadWriteLock.h" +#include "zthread/Condition.h" +#include "zthread/Guard.h" +#include "zthread/FastMutex.h" + +namespace ZThread { + + /** + * @class BiasedReadWriteLock + * + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T10:22:34-0400> + * @version 2.2.7 + * + * A BiasedReadWriteLock has a bias toward writers. It will prefer read-write access over + * read-only access when many threads are contending for access to either Lockable this + * ReadWriteLock provides. + * + * @see ReadWriteLock + */ + class BiasedReadWriteLock : public ReadWriteLock { + + FastMutex _lock; + Condition _condRead; + Condition _condWrite; + + volatile int _activeWriters; + volatile int _activeReaders; + + volatile int _waitingReaders; + volatile int _waitingWriters; + + //! @class ReadLock + class ReadLock : public Lockable { + + BiasedReadWriteLock& _rwlock; + + public: + + ReadLock(BiasedReadWriteLock& rwlock) : _rwlock(rwlock) {} + + virtual ~ReadLock() {} + + virtual void acquire() { + _rwlock.beforeRead(); + } + + virtual bool tryAcquire(unsigned long timeout) { + return _rwlock.beforeReadAttempt(timeout); + } + + virtual void release() { + _rwlock.afterRead(); + } + + }; + + //! @class WriteLock + class WriteLock : public Lockable { + + BiasedReadWriteLock& _rwlock; + + public: + + WriteLock(BiasedReadWriteLock& rwlock) : _rwlock(rwlock) {} + + virtual ~WriteLock() {} + + + virtual void acquire() { + _rwlock.beforeWrite(); + } + + virtual bool tryAcquire(unsigned long timeout) { + return _rwlock.beforeWriteAttempt(timeout); + } + + virtual void release() { + _rwlock.afterWrite(); + } + + }; + + friend class ReadLock; + friend class WriteLock; + + ReadLock _rlock; + WriteLock _wlock; + + public: + + /** + * Create a BiasedReadWriteLock + * + * @exception Initialization_Exception thrown if resources could not be + * allocated for this object. + */ + BiasedReadWriteLock() : _condRead(_lock), _condWrite(_lock), _rlock(*this), _wlock(*this) { + + _activeWriters = 0; + _activeReaders = 0; + + _waitingReaders = 0; + _waitingWriters = 0; + + } + + //! Destroy this ReadWriteLock + virtual ~BiasedReadWriteLock() {} + + /** + * @see ReadWriteLock::getReadLock() + */ + virtual Lockable& getReadLock() { return _rlock; } + + /** + * @see ReadWriteLock::getWriteLock() + */ + virtual Lockable& getWriteLock() { return _wlock; } + + + protected: + + void beforeRead() { + + Guard<FastMutex> guard(_lock); + + ++_waitingReaders; + + while(!allowReader()) { + + try { + + // wait + _condRead.wait(); + + } catch(...) { + + --_waitingReaders; + throw; + + } + + } + + --_waitingReaders; + ++_activeReaders; + + } + + bool beforeReadAttempt(unsigned long timeout) { + + Guard<FastMutex> guard(_lock); + bool result = false; + + ++_waitingReaders; + + while(!allowReader()) { + + try { + + result = _condRead.wait(timeout); + + } catch(...) { + + --_waitingReaders; + throw; + + } + + } + + --_waitingReaders; + ++_activeReaders; + + return result; + } + + + void afterRead() { + + bool wakeReader = false; + bool wakeWriter = false; + + { + + Guard<FastMutex> guard(_lock); + + --_activeReaders; + + wakeReader = (_waitingReaders > 0); + wakeWriter = (_waitingWriters > 0); + + } + + if(wakeWriter) + _condWrite.signal(); + + else if(wakeReader) + _condRead.signal(); + + } + + void beforeWrite() { + + Guard<FastMutex> guard(_lock); + + ++_waitingWriters; + + while(!allowWriter()) { + + try { + + _condWrite.wait(); + + } catch(...) { + + --_waitingWriters; + throw; + + } + + } + + --_waitingWriters; + ++_activeWriters; + + } + + bool beforeWriteAttempt(unsigned long timeout) { + + Guard<FastMutex> guard(_lock); + bool result = false; + + ++_waitingWriters; + + while(!allowWriter()) { + + try { + + result = _condWrite.wait(timeout); + + } catch(...) { + + --_waitingWriters; + throw; + } + + } + + --_waitingWriters; + ++_activeWriters; + + return result; + + } + + void afterWrite() { + + bool wakeReader = false; + bool wakeWriter = false; + + { + + Guard<FastMutex> guard(_lock); + + --_activeWriters; + + wakeReader = (_waitingReaders > 0); + wakeWriter = (_waitingWriters > 0); + + } + + if(wakeWriter) + _condWrite.signal(); + + else if(wakeReader) + _condRead.signal(); + + } + + bool allowReader() { + return (_activeWriters == 0); + } + + bool allowWriter() { + return (_activeWriters == 0 && _activeReaders == 0); + } + + }; + +}; // __ZTBIASEDREADWRITELOCK_H__ + +#endif diff --git a/dep/include/zthread/BlockingQueue.h b/dep/include/zthread/BlockingQueue.h new file mode 100644 index 00000000000..ac17347d1cc --- /dev/null +++ b/dep/include/zthread/BlockingQueue.h @@ -0,0 +1,245 @@ +/* + * 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 __ZTBLOCKINGQUEUE_H__ +#define __ZTBLOCKINGQUEUE_H__ + +#include "zthread/Guard.h" +#include "zthread/Condition.h" +#include "zthread/Queue.h" + +#include <deque> + +namespace ZThread { + + /** + * @class BlockingQueue + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T12:01:43-0400> + * @version 2.3.0 + * + * Like a LockedQueue, a BlockingQueue is a Queue implementation that provides + * serialized access to the items added to it. It differs by causing threads + * accessing the next() methods to block until a value becomes available. + */ + template <class T, class LockType, typename StorageType = std::deque<T> > + class BlockingQueue : public Queue<T>, public Lockable { + + //! Serialize access + LockType _lock; + + //! Signaled when empty + Condition _notEmpty; + + //! Storage backing the queue + StorageType _queue; + + //! Cancellation flag + volatile bool _canceled; + + public: + + //! Create a new BlockingQueue + BlockingQueue() : _notEmpty(_lock), _canceled(false) {} + + //! Destroy this BlockingQueue + virtual ~BlockingQueue() { } + + /** + * @see Queue::add(const T& item) + */ + virtual void add(const T& item) { + + Guard<LockType> g(_lock); + + if(_canceled) + throw Cancellation_Exception(); + + _queue.push_back(item); + + _notEmpty.signal(); + + } + + /** + * @see Queue::add(const T& item, unsigned long timeout) + */ + virtual bool add(T item, unsigned long timeout) { + + try { + + Guard<LockType> g(_lock, timeout); + + if(_canceled) + throw Cancellation_Exception(); + + _queue.push_back(item); + + _notEmpty.signal(); + + } catch(Timeout_Exception&) { return false; } + + return true; + + } + + /** + * Get a value from this Queue. The calling thread may block indefinitely. + * + * @return <em>T</em> next available value + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * + * @exception Interrupted_Exception thrown if the calling thread is interrupted + * before a value becomes available. + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post The value returned will have been removed from the Queue. + * + * @see Queue::next() + */ + virtual T next() { + + Guard<LockType> g(_lock); + + while(_queue.empty() && !_canceled) + _notEmpty.wait(); + + if( _queue.empty() ) + throw Cancellation_Exception(); + + T item = _queue.front(); + _queue.pop_front(); + + return item; + + } + + + /** + * Get a value from this Queue. The calling thread may block indefinitely. + * + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return <em>T</em> next available value + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Timeout_Exception thrown if the timeout expires before a value + * can be retrieved. + * @exception Interrupted_Exception thrown if the calling thread is interrupted + * before a value becomes available. + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post The value returned will have been removed from the Queue. + * + * @see Queue::next(unsigned long timeout) + */ + virtual T next(unsigned long timeout) { + + Guard<LockType> g(_lock, timeout); + + while(_queue.empty() && !_canceled) { + if(!_notEmpty.wait(timeout)) + throw Timeout_Exception(); + } + + if(_queue.empty() ) + throw Cancellation_Exception(); + + T item = _queue.front(); + _queue.pop_front(); + + return item; + + } + + + /** + * @see Queue::cancel() + * + * @post If threads are blocked on one of the next() functions then + * they will be awakened with a Cancellation_Exception. + */ + virtual void cancel() { + + Guard<LockType> g(_lock); + + _notEmpty.broadcast(); + _canceled = true; + + } + + /** + * @see Queue::isCanceled() + */ + virtual bool isCanceled() { + + // Faster check since the queue will not become un-canceled + if(_canceled) + return true; + + Guard<LockType> g(_lock); + + return _canceled; + + } + + /** + * @see Queue::size() + */ + virtual size_t size() { + + Guard<LockType> g(_lock); + return _queue.size(); + + } + + /** + * @see Queue::size(unsigned long timeout) + */ + virtual size_t size(unsigned long timeout) { + + Guard<LockType> g(_lock, timeout); + return _queue.size(); + + } + + public: + + virtual void acquire() { + _lock.acquire(); + } + + virtual bool tryAcquire(unsigned long timeout) { + return _lock.tryAcquire(timeout); + } + + virtual void release() { + _lock.release(); + } + + }; /* BlockingQueue */ + +} // namespace ZThread + +#endif // __ZTBLOCKINGQUEUE_H__ diff --git a/dep/include/zthread/BoundedQueue.h b/dep/include/zthread/BoundedQueue.h new file mode 100644 index 00000000000..2b3a616f1fb --- /dev/null +++ b/dep/include/zthread/BoundedQueue.h @@ -0,0 +1,387 @@ +/* + * 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 __ZTBOUNDEDQUEUE_H__ +#define __ZTBOUNDEDQUEUE_H__ + +#include "zthread/Condition.h" +#include "zthread/Guard.h" +#include "zthread/Queue.h" + +#include <deque> + +namespace ZThread { + + /** + * @class BoundedQueue + * + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T13:54:04-0400> + * @version 2.3.0 + * + * A BoundedQueue provides serialized access to a set of values. It differs from other + * Queues by adding a maximum capacity, giving it the following properties: + * + * - Threads calling the empty() methods will be blocked until the BoundedQueue becomes empty. + * - Threads calling the next() methods will be blocked until the BoundedQueue has a value to + * return. + * - Threads calling the add() methods will be blocked until the number of values in the + * Queue drops below the maximum capacity. + * + * @see Queue + */ + template <class T, class LockType, typename StorageType=std::deque<T> > + class BoundedQueue : public Queue<T>, public Lockable { + + //! Maximum capacity for the Queue + size_t _capacity; + + //! Serialize access + LockType _lock; + + //! Signaled if not full + Condition _notFull; + + //! Signaled if not empty + Condition _notEmpty; + + //! Signaled if empty + Condition _isEmpty; + + //! Storage backing the queue + StorageType _queue; + + //! Cancellation flag + volatile bool _canceled; + + public: + + /** + * Create a BoundedQueue with the given capacity. + * + * @param capacity maximum number of values to allow in the Queue at + * at any time + */ + BoundedQueue(size_t capacity) + : _notFull(_lock), _notEmpty(_lock), _isEmpty(_lock), + _capacity(capacity), _canceled(false) {} + + //! Destroy this Queue + virtual ~BoundedQueue() { } + + /** + * Get the maximum capacity of this Queue. + * + * @return <i>size_t</i> maximum capacity + */ + size_t capacity() { + return _capacity; + } + + /** + * Add a value to this Queue. + * + * If the number of values in the queue matches the value returned by <i>capacity</i>() + * then the calling thread will be blocked until at least one value is removed from + * the Queue. + * + * @param item value to be added to the Queue + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Interrupted_Exception thrown if the thread was interrupted while waiting + * to add a value + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post If no exception is thrown, a copy of <i>item</i> will have been added to the Queue. + * + * @see Queue::add(const T& item) + */ + virtual void add(const T& item) { + + Guard<LockType> g(_lock); + + // Wait for the capacity of the Queue to drop + while ((_queue.size() == _capacity) && !_canceled) + _notFull.wait(); + + if(_canceled) + throw Cancellation_Exception(); + + _queue.push_back(item); + _notEmpty.signal(); // Wake any waiters + + + } + + /** + * Add a value to this Queue. + * + * If the number of values in the queue matches the value returned by <i>capacity</i>() + * then the calling thread will be blocked until at least one value is removed from + * the Queue. + * + * @param item value to be added to the Queue + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return + * - <em>true</em> if a copy of <i>item</i> can be added before <i>timeout</i> + * milliseconds elapse. + * - <em>false</em> otherwise. + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Interrupted_Exception thrown if the thread was interrupted while waiting + * to add a value + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post If no exception is thrown, a copy of <i>item</i> will have been added to the Queue. + * + * @see Queue::add(const T& item, unsigned long timeout) + */ + virtual bool add(const T& item, unsigned long timeout) { + + try { + + Guard<LockType> g(_lock, timeout); + + // Wait for the capacity of the Queue to drop + while ((_queue.size() == _capacity) && !_canceled) + if(!_notFull.wait(timeout)) + return false; + + if(_canceled) + throw Cancellation_Exception(); + + _queue.push_back(item); + _notEmpty.signal(); // Wake any waiters + + } catch(Timeout_Exception&) { return false; } + + return true; + + } + + /** + * Retrieve and remove a value from this Queue. + * + * If invoked when there are no values present to return then the calling thread + * will be blocked until a value arrives in the Queue. + * + * @return <em>T</em> next available value + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Interrupted_Exception thrown if the thread was interrupted while waiting + * to retrieve a value + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post The value returned will have been removed from the Queue. + */ + virtual T next() { + + Guard<LockType> g(_lock); + + while ( _queue.empty() && !_canceled) + _notEmpty.wait(); + + if( _queue.empty()) // Queue canceled + throw Cancellation_Exception(); + + T item = _queue.front(); + _queue.pop_front(); + + _notFull.signal(); // Wake any thread trying to add + + if(_queue.empty()) // Wake empty waiters + _isEmpty.broadcast(); + + return item; + + } + + /** + * Retrieve and remove a value from this Queue. + * + * If invoked when there are no values present to return then the calling thread + * will be blocked until a value arrives in the Queue. + * + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return <em>T</em> next available value + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Timeout_Exception thrown if the timeout expires before a value + * can be retrieved. + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post The value returned will have been removed from the Queue. + */ + virtual T next(unsigned long timeout) { + + Guard<LockType> g(_lock, timeout); + + // Wait for items to be added + while (_queue.empty() && !_canceled) { + if(!_notEmpty.wait(timeout)) + throw Timeout_Exception(); + } + + if(_queue.empty()) // Queue canceled + throw Cancellation_Exception(); + + T item = _queue.front(); + _queue.pop_front(); + + _notFull.signal(); // Wake add() waiters + + if(_queue.empty()) // Wake empty() waiters + _isEmpty.broadcast(); + + return item; + + } + + /** + * Cancel this queue. + * + * @post Any threads blocked by an add() function will throw a Cancellation_Exception. + * @post Any threads blocked by a next() function will throw a Cancellation_Exception. + * + * @see Queue::cancel() + */ + virtual void cancel() { + + Guard<LockType> g(_lock); + + _canceled = true; + _notEmpty.broadcast(); // Wake next() waiters + + } + + /** + * @see Queue::isCanceled() + */ + virtual bool isCanceled() { + + // Faster check since the Queue will not become un-canceled + if(_canceled) + return true; + + Guard<LockType> g(_lock); + + return _canceled; + + } + + /** + * @see Queue::size() + */ + virtual size_t size() { + + Guard<LockType> g(_lock); + return _queue.size(); + + } + + /** + * @see Queue::size(unsigned long timeout) + */ + virtual size_t size(unsigned long timeout) { + + Guard<LockType> g(_lock, timeout); + return _queue.size(); + + } + + /** + * Test whether any values are available in this Queue. + * + * The calling thread is blocked until there are no values present + * in the Queue. + * + * @return + * - <em>true</em> if there are no values available. + * - <em>false</em> if there <i>are</i> values available. + * + * @see Queue::empty() + */ + virtual bool empty() { + + Guard<LockType> g(_lock); + + while(!_queue.empty()) // Wait for an empty signal + _isEmpty.wait(); + + return true; + + + } + + + /** + * Test whether any values are available in this Queue. + * + * The calling thread is blocked until there are no values present + * in the Queue. + * + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return + * - <em>true</em> if there are no values available. + * - <em>false</em> if there <i>are</i> values available. + * + * @exception Timeout_Exception thrown if <i>timeout</i> milliseconds + * expire before a value becomes available + * + * @see Queue::empty() + */ + virtual bool empty(unsigned long timeout) { + + Guard<LockType> g(_lock, timeout); + + while(!_queue.empty()) // Wait for an empty signal + _isEmpty.wait(timeout); + + return true; + + } + + public: + + virtual void acquire() { + _lock.acquire(); + } + + virtual bool tryAcquire(unsigned long timeout) { + return _lock.tryAcquire(timeout); + } + + virtual void release() { + _lock.release(); + } + + }; /* BoundedQueue */ + +} // namespace ZThread + +#endif // __ZTBOUNDEDQUEUE_H__ diff --git a/dep/include/zthread/Cancelable.h b/dep/include/zthread/Cancelable.h new file mode 100644 index 00000000000..9151ec8dd03 --- /dev/null +++ b/dep/include/zthread/Cancelable.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 __ZTCANCELABLE_H__ +#define __ZTCANCELABLE_H__ + +#include "zthread/Exceptions.h" + +namespace ZThread { + + /** + * @class Cancelable + * + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T09:28:46-0400> + * @version 2.3.0 + * + * The Cancelable interface defines a common method of adding general <i>disable-and-exit</i> + * semantics to some object. By cancel()ing a Cancelable object, a request is + * made to disable that object. + * + * <b>Disabling</b> + * + * A cancel()ed object may not necessarily abort it work immediately. Often, it much more + * elegant for a cancel()ed object to complete handling whatever responsibilities have + * been assigned to it, but it will <i>not</i> take on any new responsibility. + * + * <b>Exiting</b> + * + * A cancel()ed should complete its responsibilities as soon as possible. + * Canceling is not only a request to stop taking on new responsibility, and to + * complete its current responsibility. Its also a request to complete dealing with its + * current responsibilities, quickly when possible. + */ + class Cancelable { + public: + + //! Destroy a Cancelable object. + virtual ~Cancelable() {} + + /** + * Canceling a Cancelable object makes a request to disable that object. + * This entails refusing to take on any new responsibility, and completing + * its current responsibilities quickly. + * + * Canceling an object more than once has no effect. + * + * @post The Cancelable object will have permanently transitioned to a + * disabled state; it will now refuse to accept new responsibility. + */ + virtual void cancel() = 0; + + /** + * Determine if a Cancelable object has been canceled. + * + * @return + * - <em>true</em> if cancel() was called prior to this function. + * - <em>false</em> otherwise. + */ + virtual bool isCanceled() = 0; + + }; /* Cancelable */ + + +} // namespace ZThread + +#endif // __ZTCANCELABLE_H__ diff --git a/dep/include/zthread/ClassLockable.h b/dep/include/zthread/ClassLockable.h new file mode 100644 index 00000000000..a10fb4932a2 --- /dev/null +++ b/dep/include/zthread/ClassLockable.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 __ZTCLASSLOCKABLE_H__ +#define __ZTCLASSLOCKABLE_H__ + +#include "zthread/CountedPtr.h" +#include "zthread/Mutex.h" + +namespace ZThread { + + /** + * @class ClassLockable + * + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T23:37:38-0400> + * @version 2.3.0 + * + * + */ + template <typename ClassType, class LockType = Mutex> + class ClassLockable : public Lockable { + + static CountedPtr<LockType> _instance; + CountedPtr<LockType> _lock; + + public: + + //! Create a ClassLockable + ClassLockable() + : _lock(_instance) {} + + //! acquire() the ClassLockable + virtual void acquire() { + _lock->acquire(); + } + + //! tryAcquire() the ClassLockable + virtual bool tryAcquire(unsigned long timeout) { + return _lock->tryAcquire(timeout); + } + + //! release() the ClassLockable + virtual void release() { + _lock->release(); + } + + }; + + template <typename ClassType, class LockType> + CountedPtr<LockType> ClassLockable<ClassType, LockType>::_instance(new LockType); + +} // namespace ZThread + +#endif // __ZTCLASSLOCKABLE_H__ diff --git a/dep/include/zthread/ConcurrentExecutor.h b/dep/include/zthread/ConcurrentExecutor.h new file mode 100644 index 00000000000..199fe306e08 --- /dev/null +++ b/dep/include/zthread/ConcurrentExecutor.h @@ -0,0 +1,124 @@ +/* + * 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 __ZTCONCURRENTEXECUTOR_H__ +#define __ZTCONCURRENTEXECUTOR_H__ + +#include "zthread/PoolExecutor.h" + +namespace ZThread { + + /** + * @class ConcurrentExecutor + * + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T22:36:11-0400> + * @version 2.3.0 + * + * A ConcurrentExecutor spawns a single thread to service a series of Tasks. + * + * @see PoolExecutor. + */ + class ConcurrentExecutor : public Executor { + + PoolExecutor _executor; + + public: + + //! Create a ConcurrentExecutor + ConcurrentExecutor(); + + /** + * Interrupting a ConcurrentExecutor will cause the thread running the tasks to be + * be interrupted once during the execution of each task that has been submitted + * at the time this function is called. + * + * Tasks that are submitted after this function is called will + * not be interrupt()ed; unless this function is invoked again(). + * + * @code + * + * void aFunction() { + * + * ConcurrentExecutor executor; + * + * // Submit p Tasks + * for(size_t n = 0; n < p; n++) + * executor.execute(new aRunnable); + * + * // Tasks [m, p) may be interrupted, where m is the first task that has + * // not completed at the time the interrupt() is invoked. + * executor.interrupt(); + * + * // Submit (q - p) Tasks + * for(size_t n = p; n < q; n++) + * executor.execute(new Chore); + * + * // Tasks [p, q) are not interrupted + * + * } + * + * @endcode + */ + virtual void interrupt(); + + /** + * Submit a Task to this Executor. This will not block the current thread + * for very long. The task will be enqueued internally and eventually run + * in the context of the single thread driving all the Tasks submitted to this + * Executor. + * + * @exception Cancellation_Exception thrown if this Executor has been canceled. + * The Task being submitted will not be executed by this Executor. + * + * @exception Synchronization_Exception thrown only in the event of an error + * in the implementation of the library. + * + * @see Executor::execute(const Task&) + */ + virtual void execute(const Task&); + + /** + * @see Cancelable::cancel() + */ + virtual void cancel(); + + /** + * @see Cancelable::isCanceled() + */ + virtual bool isCanceled(); + + /** + * @see PoolExecutor::wait() + */ + virtual void wait(); + + /** + * @see PoolExecutor::wait(unsigned long timeout) + */ + virtual bool wait(unsigned long timeout); + + }; /* ConcurrentExecutor */ + +} // namespace ZThread + +#endif // __ZTCONCURRENTEXECUTOR_H__ diff --git a/dep/include/zthread/Condition.h b/dep/include/zthread/Condition.h new file mode 100644 index 00000000000..eba93619bfe --- /dev/null +++ b/dep/include/zthread/Condition.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 __ZTCONDITION_H__ +#define __ZTCONDITION_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" +#include "zthread/Waitable.h" + +namespace ZThread { + + class FifoConditionImpl; + + /** + * @class Condition + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T14:38:59-0400> + * @version 2.2.1 + * + * A Condition is a Waitable object used to block a thread until a particular + * condition is met. A Condition object is always used in conjunction with Lockable + * object. This object should be a FastMutex, Mutex, PriorityMutex or PriorityInheritanceMutex. + * + * Condition objects are reminiscent of POSIX condition variables in several ways but + * are slightly different. + * + * A Condition is <i>not</i> subject to spurious wakeup. + * + * Like all Waitable objects, Conditions are sensitive to Thread::interupt() which can + * be used to prematurely end a wait(). + * + * @see Thread::interupt() + * + * Before a wait() is performed on a Condition, the associated Lockable object should + * have been acquire()ed. When the wait() begins, that Lockable object is release()d + * (wait() will atomically begin the wait and unlock the Lockable). + * + * A thread blocked by wait() will remain so until an exception occurs, or until + * the thread awakened by a signal() or broadcast(). When the thread resumes execution, + * the associated Lockable is acquire()d before wait() returns. + * + * <b>Scheduling</b> + * + * Threads blocked on a Condition are resumed in FIFO order. + */ + class ZTHREAD_API Condition : public Waitable, private NonCopyable { + + FifoConditionImpl* _impl; + + public: + + /** + * Create a Condition associated with the given Lockable object. + * + * @param l Lockable object to associate with this Condition object. + */ + Condition(Lockable& l); + + //! Destroy Condition object + virtual ~Condition(); + + /** + * Wake <em>one</em> thread waiting on this Condition. + * + * The associated Lockable need not have been acquire when this function is + * invoked. + * + * @post a waiting thread, if any exists, will be awakened. + */ + void signal(); + + /** + * Wake <em>all</em> threads wait()ing on this Condition. + * + * The associated Lockable need not have been acquire when this function is + * invoked. + * + * @post all wait()ing threads, if any exist, will be awakened. + */ + void broadcast(); + + /** + * Wait for this Condition, blocking the calling thread until a signal or broadcast + * is received. + * + * This operation atomically releases the associated Lockable and blocks the calling thread. + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * + * @pre The thread calling this method must have first acquired the associated + * Lockable object. + * + * @post A thread that has resumed execution without exception (because of a signal(), + * broadcast() or exception) will have acquire()d the associated Lockable object + * before returning from a wait(). + * + * @see Waitable::wait() + */ + virtual void wait(); + + /** + * Wait for this Condition, blocking the calling thread until a signal or broadcast + * is received. + * + * This operation atomically releases the associated Lockable and blocks the calling thread. + * + * @param timeout maximum amount of time (milliseconds) this method could block + * + * @return + * - <em>true</em> if the Condition receives a signal or broadcast before + * <i>timeout</i> milliseconds elapse. + * - <em>false</em> otherwise. + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * + * @pre The thread calling this method must have first acquired the associated + * Lockable object. + * + * @post A thread that has resumed execution without exception (because of a signal(), + * broadcast() or exception) will have acquire()d the associated Lockable object + * before returning from a wait(). + * + * @see Waitable::wait(unsigned long timeout) + */ + virtual bool wait(unsigned long timeout); + + + }; + +} // namespace ZThread + +#endif // __ZTCONDITION_H__ diff --git a/dep/include/zthread/Config.h b/dep/include/zthread/Config.h new file mode 100644 index 00000000000..21e08bf8461 --- /dev/null +++ b/dep/include/zthread/Config.h @@ -0,0 +1,218 @@ +/* + * 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 __ZTCONFIG_H__ +#define __ZTCONFIG_H__ + +// ===================================================================================== +// The following section describes the symbols the configure program will define. +// If you are not using configure (autoconf), then you make want to set these by +// uncommenting them here, or whatever other means you'd like. +// ===================================================================================== + +// (configure) +// Uncomment to disable actually changing the operating systems real thread priority +// #define ZTHREAD_DISABLE_PRIORITY 1 + +// (configure) +// Uncomment to disable compiling the interrupt() hook mechanisms. +// #define ZTHREAD_DISABLE_INTERRUPT 1 + +// (configure) +// Uncomment to select a Win32 ThreadOps implementation that uses _beginthreadex() +// otherwise, CreateThread() will be used for a Windows compilation +// #define HAVE_BEGINTHREADEX 1 + +// (configure) +// Uncomment to select a pthreads based implementation +// #define ZT_POSIX 1 + +// (configure) +// Uncomment to select a Windows based implementation that uses features not +// supported by windows 98 and 95 +// #define ZT_WIN32 1 + +// (configure) +// Uncomment to select a Windows based implementation that does not use features not +// supported by windows 98 and 95, but may not be compatible with 64 bit or alpha systems +// #define ZT_WIN9X 1 + +// (configure) +// Uncomment to select a MacOS based implementation +// #define ZT_MACOS 1 + +// (configure) +// Uncomment to prefer vanilla implementations of primatives when possible +// #define ZT_VANILLA 1 + +// ===================================================================================== +// The following section can be customized to select the implementation that is compiled +// Eventually, the configure program will be updated to define these symbols as well. +// ===================================================================================== + +// Uncomment to select very simple spinlock based implementations +// #define ZTHREAD_USE_SPIN_LOCKS 1 + +// Uncomment to select the vannila dual mutex implementation of FastRecursiveLock +// #define ZTHREAD_DUAL_LOCKS 1 + +// Uncomment to select a POSIX implementation of FastRecursiveLock that does not +// spin, but instead sleeps on a condition variable. +// #define ZTHREAD_CONDITION_LOCKS 1 + +// Uncomment if you want to eliminate inlined code used as a part of some template classes +// #define ZTHREAD_NOINLINE + +// Uncomment if you want to compile a DLL version of the library. (Win32) +// #define ZTHREAD_EXPORTS 1 + +// Uncomment if you want to compile a client using the DLL version of the library. (Win32) +// #define ZTHREAD_IMPORTS 1 + +// =================================================================================== +// The following section will attempt to guess the best configuration for your system +// =================================================================================== + +// Select an implementation by checking out the environment, first looking for +// compilers, then by looking for other definitions that could be present + +#if !defined(ZT_POSIX) && !defined(ZT_WIN9X) && !defined(ZT_WIN32) && !defined(ZT_MACOS) + +// Check for well known compilers +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__BCPLUSPLUS__) || defined(__MINGW32__) + +# define ZT_WIN32 + +#elif defined(__CYGWIN__) + +# define ZT_POSIX + +// Check for well known platforms +#elif defined(__linux__) || \ + defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ + defined(__hpux) || \ + defined(__sgi) || \ + defined(__sun) + +# define ZT_POSIX + +// Check for definitions from well known headers +#elif defined(_POSIX_SOURCE) || defined(_XOPEN_SOURCE) + +# define ZT_POSIX + +#elif defined(WIN32_LEAN_AND_MEAN) + +# define ZT_WIN32 + +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) + +# define ZT_MACOS + +#else +# error "Could not select implementation, define ZT_WIN9X, ZT_WIN32, ZT_POSIX or ZT_MACOS" +#endif + +#endif + +// Once an implementation has been selected, configure the API decorator +// for shared libraries if its needed. + +#if defined(ZTHREAD_SHARED) // Compatibility w/ past releases + +# define ZTHREAD_IMPORTS + +#elif defined(ZTHREAD_STATIC) + +# undef ZTHREAD_EXPORTS +# undef ZTHREAD_IMPORTS + +#endif + +// Windows users will get a static build by default, unless they +// define either ZTHREAD_IMPORTS or ZTHREAD_EXPORTS. Client code +// of a dll version of this library should define the first flag; +// To build the dll version of this library, define the second. + +#if defined(ZTHREAD_IMPORTS) && defined(ZTHREAD_EXPORTS) +# error "Import and export declarations are not valid" +#else + +# if defined(ZTHREAD_IMPORTS) +# define ZTHREAD_API __declspec(dllimport) +# elif defined(ZTHREAD_EXPORTS) +# define ZTHREAD_API __declspec(dllexport) +# else +# define ZTHREAD_API +# endif + +#endif + +// Once the API decorator is configured, create a macro for +// explicit template instantiation (whose need can hopefully +// be removed from the library) + +#if defined(ZTHREAD_EXPORTS) +# define EXPLICIT_TEMPLATE(X) template class __declspec( dllexport ) X; +#elif defined(ZTHREAD_IMPORTS) +# define EXPLICIT_TEMPLATE(X) template class __declspec( dllimport ) X; +#else +# define EXPLICIT_TEMPLATE(X) +#endif + +// Give libc a hint, should be defined by the user - but people tend +// to forget. + +#if !defined(REENTRANT) +# define REENTRANT +#endif + +#if !defined(_REENTRANT) +# define _REENTRANT +#endif + +#if defined(_MSC_VER) +# pragma warning(disable:4275) +# pragma warning(disable:4290) +# pragma warning(disable:4786) +# pragma warning(disable:4251) +# pragma warning(disable:4355) +#endif + +// Ensure that only one implementation is selected +#if \ +(defined(ZT_POSIX) && defined(ZT_WIN32)) \ + || (defined(ZT_POSIX) && defined(ZT_WIN9X)) \ + || (defined(ZT_WIN32) && defined(ZT_WIN9X)) + +# error "Only one implementation should be selected!" + +#endif + +#if defined(ZTHREAD_NOINLINE) +# define ZTHREAD_INLINE +#else +# define ZTHREAD_INLINE inline +#endif + +#endif // __ZTCONFIG_H__ + diff --git a/dep/include/zthread/CountedPtr.h b/dep/include/zthread/CountedPtr.h new file mode 100644 index 00000000000..a4dcc6ef248 --- /dev/null +++ b/dep/include/zthread/CountedPtr.h @@ -0,0 +1,289 @@ +/* + * 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 __ZTCOUNTEDPTR_H__ +#define __ZTCOUNTEDPTR_H__ + +#include <algorithm> +#include <cassert> + +#include "zthread/AtomicCount.h" + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable:4786) // warning: long template symbol name +# pragma warning(push) +# pragma warning(disable:4284) // warning: odd return type for operator-> +#endif + +namespace ZThread { + + /** + * @class CountedPtr + * + * @author Eric Crahen <http://www.code-foo.com/> + * @date <2003-07-29T06:43:48-0400> + * @version 2.3.0 + * + */ + template <typename T, typename CountT = AtomicCount> + class CountedPtr { + +#if !defined(__MWERKS__) +#if !defined(_MSC_VER) || (_MSC_VER > 1200) + template <typename U, typename V> friend class CountedPtr; +#endif +#endif + + CountT* _count; + T* _instance; + + public: + + CountedPtr() : _count(0), _instance(0) { } + +#if !defined(__MWERKS__) +#if !defined(_MSC_VER) || (_MSC_VER > 1200) + + explicit CountedPtr(T* raw) : _count(new CountT()), _instance(raw) { + (*_count)++; + } + +#endif +#endif + + template <typename U> + explicit CountedPtr(U* raw) : _count(new CountT()), _instance(raw) { + (*_count)++; + } + +#if !defined(__MWERKS__) +#if !defined(_MSC_VER) || (_MSC_VER > 1200) + + CountedPtr(const CountedPtr& ptr) : _count(ptr._count), _instance(ptr._instance) { + + if(_count) + (*_count)++; + + } + +#endif +#endif + + template <typename U, typename V> + CountedPtr(const CountedPtr<U, V>& ptr) : _count(ptr._count), _instance(ptr._instance) { + + if(_count) + (*_count)++; + + } + + ~CountedPtr() { + + if(_count && --(*_count) == 0) { + + if(_instance) + delete _instance; + + delete _count; + + } + + } + + +#if !defined(__MWERKS__) +#if !defined(_MSC_VER) || (_MSC_VER > 1200) + + const CountedPtr& operator=(const CountedPtr& ptr) { + + typedef CountedPtr<T, CountT> ThisT; + + ThisT(ptr).swap(*this); + return *this; + + } + +#endif +#endif + + template <typename U, typename V> + const CountedPtr& operator=(const CountedPtr<U, V>& ptr) { + + typedef CountedPtr<T, CountT> ThisT; + + ThisT(ptr).swap(*this); + return *this; + + } + + void reset() { + + typedef CountedPtr<T, CountT> ThisT; + ThisT().swap(*this); + + } + +#if !defined(__MWERKS__) +#if !defined(_MSC_VER) || (_MSC_VER > 1200) + + void swap(CountedPtr& ptr) { + + std::swap(_count, ptr._count); + std::swap(_instance, ptr._instance); + + } + +#endif +#endif + + template <typename U, typename V> + void swap(CountedPtr<U, V>& ptr) { + + std::swap(_count, ptr._count); + std::swap(_instance, ptr._instance); + + } + + // Convience operators + +#if !defined(__MWERKS__) +#if !defined(_MSC_VER) || (_MSC_VER > 1200) + + bool less(const CountedPtr& ptr) const { + return _instance < ptr._instance; + } + +#endif +#endif + + template <typename U, typename V> + bool less(const CountedPtr<U, V>& ptr) const { + return _instance < ptr._instance; + } + + +#if !defined(__MWERKS__) +#if !defined(_MSC_VER) || (_MSC_VER > 1200) + + bool equal(const CountedPtr& ptr) const { + return _count == ptr._count; + } + +#endif +#endif + + template <typename U, typename V> + bool equal(const CountedPtr<U, V>& ptr) const { + return _count == ptr._count; + } + + + friend inline bool operator==(const CountedPtr& lhs, const CountedPtr& rhs) { + return lhs.equal(rhs); + } + + friend inline bool operator<(const CountedPtr& lhs, const CountedPtr& rhs) { + return lhs.less(rhs); + } + + + T& operator*() { + assert(_instance != 0); + return *_instance; + } + + T* operator->() { + assert(_instance != 0); + return _instance; + } + + const T* operator->() const { + assert(_instance != 0); + return _instance; + } + + bool operator!() const { + return _instance == 0; + } + + operator bool() const { + return _instance != 0; + } + + }; /* CountedPtr */ + + template<typename U, typename V, typename X, typename Y> + inline bool operator<(CountedPtr<U, V> const &lhs, CountedPtr<X, Y> const &rhs) { + return lhs.less(rhs); + } + + template<typename U, typename V, typename X, typename Y> + inline bool operator==(CountedPtr<U, V> const &lhs, CountedPtr<X, Y> const &rhs) { + return lhs.equal(rhs.get); + } + + template<typename U, typename V, typename X, typename Y> + inline bool operator!=(CountedPtr<U, V> const &lhs, CountedPtr<X, Y> const &rhs) { + return !(lhs.equal(rhs.get)); + } + + template<typename U, typename V, typename X, typename Y> + inline void swap(CountedPtr<U, V> const &lhs, CountedPtr<X, Y> const &rhs) { + lhs.swap(rhs); + } + +#if !defined(__MWERKS__) +#if !defined(_MSC_VER) || (_MSC_VER > 1200) + + template<typename U, typename V> + inline bool operator<(CountedPtr<U, V> const &lhs, CountedPtr<U, V> const &rhs) { + return lhs.less(rhs); + } + + template<typename U, typename V> + inline bool operator==(CountedPtr<U, V> const &lhs, CountedPtr<U, V> const &rhs) { + return lhs.equal(rhs.get); + } + + template<typename U, typename V> + inline bool operator!=(CountedPtr<U, V> const &lhs, CountedPtr<U, V> const &rhs) { + return !(lhs.equal(rhs.get)); + } + + template<typename U, typename V> + inline void swap(CountedPtr<U, V> const &lhs, CountedPtr<U, V> const &rhs) { + lhs.swap(rhs); + } + +#endif +#endif + +} // namespace ZThread + +#ifdef _MSC_VER +# pragma warning(pop) +# pragma warning(pop) +#endif + + +#endif // __ZTCOUNTEDPTR_H__ diff --git a/dep/include/zthread/CountingSemaphore.h b/dep/include/zthread/CountingSemaphore.h new file mode 100644 index 00000000000..f580a65f726 --- /dev/null +++ b/dep/include/zthread/CountingSemaphore.h @@ -0,0 +1,138 @@ +/* + * 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 __ZTCOUNTINGSEMAPHORE_H__ +#define __ZTCOUNTINGSEMAPHORE_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + class FifoSemaphoreImpl; + + /** + * @class CountingSemaphore + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T15:26:18-0400> + * @version 2.2.1 + * + * A CountingSemaphore is an owner-less Lockable object. + * + * It differs from a normal Semaphore in that there is no upper bound on the count + * and it will not throw an exception because a maximum value has been exceeded. + * + * @see Semaphore + * + * Threads blocked on a CountingSemaphore are resumed in FIFO order. + */ + class ZTHREAD_API CountingSemaphore : public Lockable, private NonCopyable { + + FifoSemaphoreImpl* _impl; + + public: + + /** + * Create a new CountingSemaphore. + * + * @param count - initial count + */ + CountingSemaphore(int initialCount = 0); + + //! Destroy the CountingSemaphore + virtual ~CountingSemaphore(); + + /** + * <i>Provided to reflect the traditional Semaphore semantics</i> + * + * @see acquire() + */ + void wait(); + + + /** + * <i>Provided to reflect the traditional Semaphore semantics</i> + * + * @see tryAcquire(unsigned long timeout) + */ + bool tryWait(unsigned long timeout); + + /** + * <i>Provided to reflect the traditional Semaphore semantics</i> + * + * @see release() + */ + void post(); + + + /** + * Get the current count of the semaphore. + * + * This value may change immediately after this function returns to the calling thread. + * + * @return <em>int</em> count + */ + virtual int count(); + + /** + * Decrement the count, blocking that calling thread if the count becomes 0 or + * less than 0. The calling thread will remain blocked until the count is + * raised above 0, an exception is thrown or the given amount of time expires. + * + * @param timeout maximum amount of time (milliseconds) this method could block + * + * @return + * - <em>true</em> if the Semaphore was acquired before <i>timeout</i> milliseconds elapse. + * - <em>false</em> otherwise. + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * + * @see Lockable::tryAcquire(unsigned long timeout) + */ + virtual bool tryAcquire(unsigned long timeout); + + /** + * Decrement the count, blocking that calling thread if the count becomes 0 or + * less than 0. The calling thread will remain blocked until the count is + * raised above 0 or if an exception is thrown. + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * + * @see Lockable::acquire() + */ + virtual void acquire(); + + /** + * Increment the count, unblocking one thread if count is positive. + * + * @see Lockable::release() + */ + virtual void release(); + + }; + + +} // namespace ZThread + +#endif // __ZTCOUNTINGSEMAPHORE_H__ diff --git a/dep/include/zthread/Exceptions.h b/dep/include/zthread/Exceptions.h new file mode 100644 index 00000000000..b7207932af4 --- /dev/null +++ b/dep/include/zthread/Exceptions.h @@ -0,0 +1,244 @@ +/* + * 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 __ZTEXCEPTIONS_H__ +#define __ZTEXCEPTIONS_H__ + + +#include "zthread/Config.h" +#include <string> + +namespace ZThread { + +/** + * @class Synchronization_Exception + * + * Serves as a general base class for the Exception hierarchy used within + * this package. + * + */ +class Synchronization_Exception { + + // Restrict heap allocation + static void * operator new(size_t size); + static void * operator new[](size_t size); + + std::string _msg; + +public: + + /** + * Create a new exception with a default error message 'Synchronization + * Exception' + */ + Synchronization_Exception() : _msg("Synchronization exception") { } + + /** + * Create a new exception with a given error message + * + * @param const char* - error message + */ + Synchronization_Exception(const char* msg) : _msg(msg) { } + + /** + * Get additional info about the exception + * + * @return const char* for the error message + */ + const char* what() const { + return _msg.c_str(); + } + +}; + + +/** + * @class Interrupted_Exception + * + * Used to describe an interrupted operation that would have normally + * blocked the calling thread + */ +class Interrupted_Exception : public Synchronization_Exception { + + public: + + //! Create a new exception + Interrupted_Exception() : Synchronization_Exception("Thread interrupted") { } + + //! Create a new exception + Interrupted_Exception(const char* msg) : Synchronization_Exception(msg) { } + +}; + + + +/** + * @class Deadlock_Exception + * + * Thrown when deadlock has been detected + */ +class Deadlock_Exception : public Synchronization_Exception { + public: + + //! Create a new exception + Deadlock_Exception() : Synchronization_Exception("Deadlock detected") { } + + //! Create a new exception + Deadlock_Exception(const char* msg) : Synchronization_Exception(msg) { } + +}; + + +/** + * @class InvalidOp_Exception + * + * Thrown when performing an illegal operation this object + */ +class InvalidOp_Exception : public Synchronization_Exception { + public: + + //! Create a new exception + InvalidOp_Exception() : Synchronization_Exception("Invalid operation") { } + //! Create a new exception + InvalidOp_Exception(const char* msg) : Synchronization_Exception(msg) { } + +}; + + + +/** + * @class Initialization_Exception + * + * Thrown when the system has no more resources to create new + * synchronization controls + */ +class Initialization_Exception : public Synchronization_Exception { + + public: + + //! Create a new exception + Initialization_Exception() : Synchronization_Exception("Initialization error") { } + //! Create a new exception + Initialization_Exception(const char*msg) : Synchronization_Exception(msg) { } + +}; + +/** + * @class Cancellation_Exception + * + * Cancellation_Exceptions are thrown by 'Canceled' objects. + * @see Cancelable + */ +class Cancellation_Exception : public Synchronization_Exception { + + public: + + //! Create a new Cancelltion_Exception + Cancellation_Exception() : Synchronization_Exception("Canceled") { } + //! Create a new Cancelltion_Exception + Cancellation_Exception(const char*msg) : Synchronization_Exception(msg) { } + +}; + + +/** + * @class Timeout_Exception + * + * There is no need for error messaged simply indicates the last + * operation timed out + */ +class Timeout_Exception : public Synchronization_Exception { + public: + + //! Create a new Timeout_Exception + Timeout_Exception() : Synchronization_Exception("Timeout") { } + //! Create a new + Timeout_Exception(const char*msg) : Synchronization_Exception(msg) { } + +}; + +/** + * @class NoSuchElement_Exception + * + * The last operation that was attempted on a Queue could not find + * the item that was indicated (during that last Queue method invocation) + */ +class NoSuchElement_Exception { + public: + + //! Create a new exception + NoSuchElement_Exception() {} + +}; + +/** + * @class InvalidTask_Exception + * + * Thrown when a task is not valid (e.g. null or start()ing a thread with + * no overriden run() method) + */ +class InvalidTask_Exception : public InvalidOp_Exception { + public: + + //! Create a new exception + InvalidTask_Exception() : InvalidOp_Exception("Invalid task") {} + +}; + +/** + * @class BrokenBarrier_Exception + * + * Thrown when a Barrier is broken because one of the participating threads + * has been interrupted. + */ +class BrokenBarrier_Exception : public Synchronization_Exception { + + public: + + //! Create a new exception + BrokenBarrier_Exception() : Synchronization_Exception("Barrier broken") { } + + //! Create a new exception + BrokenBarrier_Exception(const char* msg) : Synchronization_Exception(msg) { } + +}; + +/** + * @class Future_Exception + * + * Thrown when there is an error using a Future. + */ +class Future_Exception : public Synchronization_Exception { + + public: + + //! Create a new exception + Future_Exception() : Synchronization_Exception() { } + + //! Create a new exception + Future_Exception(const char* msg) : Synchronization_Exception(msg) { } + +}; + +}; + +#endif // __ZTEXCEPTIONS_H__ diff --git a/dep/include/zthread/Executor.h b/dep/include/zthread/Executor.h new file mode 100644 index 00000000000..833d0d4c3d1 --- /dev/null +++ b/dep/include/zthread/Executor.h @@ -0,0 +1,94 @@ +/* + * 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 __ZTEXECUTOR_H__ +#define __ZTEXECUTOR_H__ + +#include "zthread/Thread.h" +#include "zthread/Waitable.h" + +namespace ZThread { + + + /** + * @class Executor + * + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T22:39:39-0400> + * @version 2.3.0 + * + * Execeutors are an implementation of the Executor pattern. This is + * a more versatile construct than a thread pool. A paper describing can + * be found in the proceedings of the 2002 VikingPLOP conference. + * + * <b>Executing</b> + * + * - <em>execute</em>()ing task with an Executor will submit the task, scheduling + * it for execution at some future time depending on the Executor being used. + * + * <b>Disabling</b> + * + * - <em>cancel</em>()ing an Executor will cause it to stop accepting + * new tasks. + * + * <b>Interrupting</b> + * + * - <em>interrupt</em>()ing an Executor will cause the any thread running + * a task which was submitted prior to the invocation of this function to + * be interrupted during the execution of that task. + * + * <b>Waiting</b> + * + * - <em>wait</em>()ing on a PoolExecutor will block the calling thread + * until all tasks that were submitted prior to the invocation of this function + * have completed. + * + * @see Cancelable + * @see Waitable + */ + class Executor : public Cancelable, public Waitable, private NonCopyable { + public: + + /** + * If supported by the Executor, interrupt all tasks submitted prior to + * the invocation of this function. + */ + virtual void interrupt() = 0; + + /** + * Submit a task to this Executor. + * + * @param task Task to be run by a thread managed by this executor + * + * @pre The Executor should have been canceled prior to this invocation. + * @post The submitted task will be run at some point in the future by this Executor. + * + * @exception Cancellation_Exception thrown if the Executor was canceled prior to + * the invocation of this function. + */ + virtual void execute(const Task& task) = 0; + + }; + +} // namespace ZThread + +#endif // __ZTEXECUTOR_H__ diff --git a/dep/include/zthread/FairReadWriteLock.h b/dep/include/zthread/FairReadWriteLock.h new file mode 100644 index 00000000000..8f183b62839 --- /dev/null +++ b/dep/include/zthread/FairReadWriteLock.h @@ -0,0 +1,183 @@ +/* + * 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 __ZTFAIRREADWRITELOCK_H__ +#define __ZTFAIRREADWRITELOCK_H__ + +#include "zthread/ReadWriteLock.h" +#include "zthread/Condition.h" +#include "zthread/Guard.h" +#include "zthread/Mutex.h" + +namespace ZThread { + + /** + * @class FairReadWriteLock + * + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T10:26:25-0400> + * @version 2.2.7 + * + * A FairReadWriteLock maintains a balance between the order read-only access + * and read-write access is allowed. Threads contending for the pair of Lockable + * objects this ReadWriteLock provides will gain access to the locks in FIFO order. + * + * @see ReadWriteLock + */ + class FairReadWriteLock : public ReadWriteLock { + + Mutex _lock; + Condition _cond; + + volatile int _readers; + + //! @class ReadLock + class ReadLock : public Lockable { + + FairReadWriteLock& _rwlock; + + public: + + ReadLock(FairReadWriteLock& rwlock) : _rwlock(rwlock) {} + + virtual ~ReadLock() {} + + virtual void acquire() { + + Guard<Mutex> g(_rwlock._lock); + ++_rwlock._readers; + + } + + virtual bool tryAcquire(unsigned long timeout) { + + if(!_rwlock._lock.tryAcquire(timeout)) + return false; + + ++_rwlock._readers; + _rwlock._lock.release(); + + return true; + } + + virtual void release() { + + Guard<Mutex> g(_rwlock._lock); + --_rwlock._readers; + + if(_rwlock._readers == 0) + _rwlock._cond.signal(); + + } + + }; + + //! @class WriteLock + class WriteLock : public Lockable { + + FairReadWriteLock& _rwlock; + + public: + + WriteLock(FairReadWriteLock& rwlock) : _rwlock(rwlock) {} + + virtual ~WriteLock() {} + + virtual void acquire() { + + _rwlock._lock.acquire(); + + try { + + while(_rwlock._readers > 0) + _rwlock._cond.wait(); + + } catch(...) { + + _rwlock._lock.release(); + throw; + + } + + } + + virtual bool tryAcquire(unsigned long timeout) { + + if(!_rwlock._lock.tryAcquire(timeout)) + return false; + + try { + + while(_rwlock._readers > 0) + _rwlock._cond.wait(timeout); + + } catch(...) { + + _rwlock._lock.release(); + throw; + + } + + return true; + + } + + virtual void release() { + _rwlock._lock.release(); + } + + }; + + friend class ReadLock; + friend class WriteLock; + + ReadLock _rlock; + WriteLock _wlock; + + public: + + /** + * Create a BiasedReadWriteLock + * + * @exception Initialization_Exception thrown if resources could not be + * allocated for this object. + */ + FairReadWriteLock() : _cond(_lock), _readers(0), _rlock(*this), _wlock(*this) {} + + //! Destroy this ReadWriteLock + virtual ~FairReadWriteLock() {} + + /** + * @see ReadWriteLock::getReadLock() + */ + virtual Lockable& getReadLock() { return _rlock; } + + /** + * @see ReadWriteLock::getWriteLock() + */ + virtual Lockable& getWriteLock() { return _wlock; } + + }; + +}; // __ZTFAIRREADWRITELOCK_H__ + +#endif diff --git a/dep/include/zthread/FastMutex.h b/dep/include/zthread/FastMutex.h new file mode 100644 index 00000000000..1812c3e55a5 --- /dev/null +++ b/dep/include/zthread/FastMutex.h @@ -0,0 +1,111 @@ +/* + * 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 __ZTFASTMUTEX_H__ +#define __ZTFASTMUTEX_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + class FastLock; + + /** + * @class FastMutex + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-19T18:45:39-0400> + * @version 2.2.0 + * + * A FastMutex is a small fast implementation of a non-recursive, mutually exclusive + * Lockable object. This implementation is a bit faster than the other Mutex classes + * as it involved the least overhead. However, this slight increase in speed is + * gained by sacrificing the robustness provided by the other classes. + * + * A FastMutex has the useful property of not being interruptable; that is to say + * that acquire() and tryAcquire() will not throw Interrupted_Exceptions. + * + * @see Mutex + * + * <b>Scheduling</b> + * + * Scheduling is left to the operating systems and may vary. + * + * <b>Error Checking</b> + * + * No error checking is performed, this means there is the potential for deadlock. + */ + class ZTHREAD_API FastMutex : public Lockable, private NonCopyable { + + FastLock* _lock; + + public: + + //! Create a FastMutex + FastMutex(); + + //! Destroy a FastMutex + virtual ~FastMutex(); + + /** + * Acquire exclusive access to the mutex. The calling thread will block until the + * lock can be acquired. No safety or state checks are performed. + * + * @pre The calling thread should <i>not</i> have previously acquired this lock. + * Deadlock will result if the same thread attempts to acquire the mutex more + * than once. + * + * @post The calling thread obtains the lock successfully if no exception is thrown. + * @exception Interrupted_Exception never thrown + */ + virtual void acquire(); + + /** + * Release exclusive access. No safety or state checks are performed. + * + * @pre the caller should have previously acquired this lock + */ + virtual void release(); + + /** + * Try to acquire exclusive access to the mutex. The calling thread will block until the + * lock can be acquired. No safety or state checks are performed. + * + * @pre The calling thread should <i>not</i> have previously acquired this lock. + * Deadlock will result if the same thread attempts to acquire the mutex more + * than once. + * + * @param timeout unused + * @return + * - <em>true</em> if the lock was acquired + * - <em>false</em> if the lock was acquired + * + * @post The calling thread obtains the lock successfully if no exception is thrown. + * @exception Interrupted_Exception never thrown + */ + virtual bool tryAcquire(unsigned long timeout); + + }; /* FastMutex */ + +}; + +#endif // __ZTFASTMUTEX_H__ diff --git a/dep/include/zthread/FastRecursiveMutex.h b/dep/include/zthread/FastRecursiveMutex.h new file mode 100644 index 00000000000..a30f4b53aa7 --- /dev/null +++ b/dep/include/zthread/FastRecursiveMutex.h @@ -0,0 +1,106 @@ +/* + * 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 __ZTFASTRECURSIVEMUTEX_H__ +#define __ZTFASTRECURSIVEMUTEX_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + class FastRecursiveLock; + + /** + * @class FastRecursiveMutex + * + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-19T19:00:25-0400> + * @version 2.2.0 + * + * A FastRecursiveMutex is a small fast implementation of a recursive, mutally exclusive + * Lockable object. This implementation is a bit faster than the other Mutex classes + * as it involved the least overhead. However, this slight increase in speed is + * gained by sacrificing the robustness provided by the other classes. + * + * A FastRecursiveMutex has the useful property of not being interruptable; that is to say + * that acquire() and tryAcquire() will not throw Interrupted_Exceptions. + * + * @see RecursiveMutex + * + * <b>Scheduling</b> + * + * Scheduling is left to the operating systems and may vary. + * + * <b>Error Checking</b> + * + * No error checking is performed, this means there is the potential for deadlock. + */ + class ZTHREAD_API FastRecursiveMutex : public Lockable, private NonCopyable { + + FastRecursiveLock* _lock; + + public: + + //! Create a new FastRecursiveMutex + FastRecursiveMutex(); + + //! Destroy this FastRecursiveMutex + virtual ~FastRecursiveMutex(); + + /** + * Acquire exclusive access to the mutex. The calling thread will block until the + * lock can be acquired. No safety or state checks are performed. The calling thread + * may acquire the mutex nore than once. + * + * @post The calling thread obtains the lock successfully if no exception is thrown. + * @exception Interrupted_Exception never thrown + */ + virtual void acquire(); + + /** + * Release access. No safety or state checks are performed. + * + * @pre the caller should have previously acquired this lock at least once. + */ + virtual void release(); + + /** + * Try to acquire exclusive access to the mutex. The calling thread will block until the + * lock can be acquired. No safety or state checks are performed. The calling thread + * may acquire the mutex more than once. + * + * @param timeout unused + * @return + * - <em>true</em> if the lock was acquired + * - <em>false</em> if the lock was acquired + * + * @post The calling thread obtains the lock successfully if no exception is thrown. + * @exception Interrupted_Exception never thrown + */ + virtual bool tryAcquire(unsigned long timeout); + + }; + +} // namespace ZThread + +#endif // __ZTFASTRECURSIVEMUTEX_H__ diff --git a/dep/include/zthread/Guard.h b/dep/include/zthread/Guard.h new file mode 100644 index 00000000000..988c3cfa3c2 --- /dev/null +++ b/dep/include/zthread/Guard.h @@ -0,0 +1,511 @@ +/* + * 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 __ZTGUARD_H__ +#define __ZTGUARD_H__ + +#include "zthread/NonCopyable.h" +#include "zthread/Exceptions.h" + +namespace ZThread { + +// +// GuardLockingPolicyContract { +// +// createScope(lock_type&) +// bool createScope(lock_type&, unsigned long) +// destroyScope(lock_type&) +// +// } +// + +/** + * @class LockHolder + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T17:55:42-0400> + * @version 2.2.0 + * + * This is a simple base class for Guards class. It allows Guards + * that have compatible targets to refer to each others targets + * allowing for the construction of Guards that share the same lock + * but have different locking policies. + */ +template <class LockType> +class LockHolder { + + LockType &_lock; + bool _enabled; + + public: + + template <class T> + LockHolder(T& t) : _lock(extract(t)._lock), _enabled(true) { } + + LockHolder(LockHolder& holder) : _lock(holder._lock), _enabled(true) { } + + LockHolder(LockType& lock) : _lock(lock), _enabled(true) { } + + void disable() { + _enabled = false; + } + + bool isDisabled() { + return !_enabled; + } + + LockType& getLock() { + return _lock; + } + + protected: + + template <class T> + static LockHolder& extract(T& t) { + // Design and Evolution of C++, page 328 + return (LockHolder&)(t); + } + +}; + +/** + * @class CompoundScope + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T17:55:42-0400> + * @version 2.2.0 + * + * Locking policy that aggregates two policies that share a target. + * It is not appropriate to use with any type of OverlappedScope + */ +template <class Scope1, class Scope2> +class CompoundScope { + public: + + template <class LockType> + static void createScope(LockHolder<LockType>& l) { + + Scope1::createScope(l); + Scope2::createScope(l); + + } + + template <class LockType> + static void createScope(LockHolder<LockType>& l, unsigned long ms) { + + if(Scope1::createScope(l, ms)) + if(!Scope2::createScope(l, ms)) { + + Scope1::destroyScope(l); + return false; + + } + + return true; + + } + + template <class LockType> + static void destroyScope(LockHolder<LockType>& l) { + + Scope1::destroyScope(l); + Scope2::destroyScope(l); + + } + +}; + + +/** + * @class LockedScope + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T17:55:42-0400> + * @version 2.2.0 + * + * Locking policy for Lockable objects. This policy acquire()s a Lockable + * when the protection scope is created, and it release()s a Lockable + * when the scope is destroyed. + */ +class LockedScope { + public: + + /** + * A new protection scope is being created by l2, using an existing scope + * created by l1. + * + * @param lock1 LockType1& is the LockHolder that holds the desired lock + * @param lock2 LockType1& is the LockHolder that wants to share + template <class LockType1, class LockType2> + static void shareScope(LockHolder<LockType1>& l1, LockHolder<LockType2>& l2) { + + l2.getLock().acquire(); + + } + */ + + /** + * A new protection scope is being created. + * + * @param lock LockType& is a type of LockHolder. + */ + template <class LockType> + static bool createScope(LockHolder<LockType>& l, unsigned long ms) { + + return l.getLock().tryAcquire(ms); + + } + + /** + * A new protection scope is being created. + * + * @param lock LockType& is a type of LockHolder. + */ + template <class LockType> + static void createScope(LockHolder<LockType>& l) { + + l.getLock().acquire(); + + } + + /** + * A protection scope is being destroyed. + * + * @param lock LockType& is a type of LockHolder. + */ + template <class LockType> + static void destroyScope(LockHolder<LockType>& l) { + + l.getLock().release(); + + } + +}; + + +/** + * @class UnlockedScope + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T17:55:42-0400> + * @version 2.2.0 + * + * Locking policy for Lockable objects. This policy release()s a Lockable + * when the protection scope is created, and it acquire()s a Lockable + * when the scope is destroyed. + */ +class UnlockedScope { + public: + + /** + * A new protection scope is being created by l2, using an existing scope + * created by l1. + * + * @param lock1 LockType1& is the LockHolder that holds the desired lock + * @param lock2 LockType1& is the LockHolder that wants to share + */ + template <class LockType1, class LockType2> + static void shareScope(LockHolder<LockType1>& /*l1*/, LockHolder<LockType2>& l2) { + + l2.getLock().release(); + + } + + /** + * A new protection scope is being created. + * + * @param lock LockType& is a type of LockHolder. + template <class LockType> + static void createScope(LockHolder<LockType>& l) { + + l.getLock().release(); + + } + */ + + /** + * A protection scope is being destroyed. + * + * @param lock LockType& is a type of LockHolder. + */ + template <class LockType> + static void destroyScope(LockHolder<LockType>& l) { + + l.getLock().acquire(); + + } + +}; + + + +/** + * @class TimedLockedScope + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T17:55:42-0400> + * @version 2.2.0 + * + * Locking policy that attempts to enterScope some resource + * in a certain amount of time using an tryEnterScope-relase protocol. + */ +template <int TimeOut> +class TimedLockedScope { + public: + + /** + * Try to enterScope the given LockHolder. + * + * @param lock LockType& is a type of LockHolder. + */ + template <class LockType1, class LockType2> + static void shareScope(LockHolder<LockType1>& l1, LockHolder<LockType2>& l2) { + + if(!l2.getLock().tryAcquire(TimeOut)) + throw Timeout_Exception(); + + } + + template <class LockType> + static void createScope(LockHolder<LockType>& l) { + + if(!l.getLock().tryAcquire(TimeOut)) + throw Timeout_Exception(); + + } + + template <class LockType> + static void destroyScope(LockHolder<LockType>& l) { + + l.getLock().release(); + + } + +}; + + +/** + * @class OverlappedScope + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T17:55:42-0400> + * @version 2.2.0 + * + * Locking policy allows the effective scope of two locks to overlap + * by releasing and disabling one lock before its Guard does so. + */ +class OverlappedScope { + public: + + template <class LockType1, class LockType2> + static void transferScope(LockHolder<LockType1>& l1, LockHolder<LockType2>& l2) { + + l1.getLock().acquire(); + + l2.getLock().release(); + l2.disable(); + + } + + template <class LockType> + static void destroyScope(LockHolder<LockType>& l) { + + l.getLock().release(); + + } + +}; + + + +/** + * @class Guard + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T17:55:42-0400> + * @version 2.2.0 + * + * Scoped locking utility. This template class can be given a Lockable + * synchronization object and can 'Guard' or serialize access to + * that method. + * + * For instance, consider a case in which a class or program have a + * Mutex object associated with it. Access can be serialized with a + * Guard as shown below. + * + * @code + * + * Mutex _mtx; + * void guarded() { + * + * Guard<Mutex> g(_mtx); + * + * } + * + * @endcode + * + * The Guard will lock the synchronization object when it is created and + * automatically unlock it when it goes out of scope. This eliminates + * common mistakes like forgetting to unlock your mutex. + * + * An alternative to the above example would be + * + * @code + * + * void guarded() { + * + * (Guard<Mutex>)(_mtx); + * + * } + * + * @endcode + * + * HOWEVER; using a Guard in this method is dangerous. Depending on your + * compiler an anonymous variable like this can go out of scope immediately + * which can result in unexpected behavior. - This is the case with MSVC + * and was the reason for introducing assertions into the Win32_MutexImpl + * to track this problem down + * + */ +template <class LockType, class LockingPolicy = LockedScope> +class Guard : private LockHolder<LockType>, private NonCopyable { + + friend class LockHolder<LockType>; + +public: + + /** + * Create a Guard that enforces a the effective protection scope + * throughout the lifetime of the Guard object or until the protection + * scope is modified by another Guard. + * + * @param lock LockType the lock this Guard will use to enforce its + * protection scope. + * @post the protection scope may be ended prematurely + */ + Guard(LockType& lock) : LockHolder<LockType>(lock) { + + LockingPolicy::createScope(*this); + + }; + + /** + * Create a Guard that enforces a the effective protection scope + * throughout the lifetime of the Guard object or until the protection + * scope is modified by another Guard. + * + * @param lock LockType the lock this Guard will use to enforce its + * protection scope. + * @post the protection scope may be ended prematurely + */ + Guard(LockType& lock, unsigned long timeout) : LockHolder<LockType>(lock) { + + if(!LockingPolicy::createScope(*this, timeout)) + throw Timeout_Exception(); + + }; + + /** + * Create a Guard that shares the effective protection scope + * from the given Guard to this Guard. + * + * @param g Guard<U, V> guard that is currently enabled + * @param lock LockType the lock this Guard will use to enforce its + * protection scope. + */ + template <class U, class V> + Guard(Guard<U, V>& g) : LockHolder<LockType>(g) { + + LockingPolicy::shareScope(*this, extract(g)); + + } + + /** + * Create a Guard that shares the effective protection scope + * from the given Guard to this Guard. + * + * @param g Guard guard that is currently enabled + * @param lock LockType the lock this Guard will use to enforce its + * protection scope. + */ + Guard(Guard& g) : LockHolder<LockType>(g) { + + LockingPolicy::shareScope(*this, g); + + } + + + /** + * Create a Guard that transfers the effective protection scope + * from the given Guard to this Guard. + * + * @param g Guard<U, V> guard that is currently enabled + * @param lock LockType the lock this Guard will use to enforce its + * protection scope. + */ + template <class U, class V> + Guard(Guard<U, V>& g, LockType& lock) : LockHolder<LockType>(lock) { + + LockingPolicy::transferScope(*this, extract(g)); + + } + + + /** + * Create a Guard that transfers the effective protection scope + * from the given Guard to this Guard. + * + * @param g Guard guard that is currently enabled + * @param lock LockType the lock this Guard will use to enforce its + * protection scope. + */ + Guard(Guard& g, LockType& lock) : LockHolder<LockType>(lock) { + + LockingPolicy::transferScope(*this, g); + + } + + + /** + * Unlock a given Lockable object with the destruction of this Guard + */ + ~Guard() throw(); + +}; /* Guard */ + + +template <class LockType, class LockingPolicy> +Guard<LockType, LockingPolicy>::~Guard() throw() { + + try { + + if(!this->isDisabled()) + LockingPolicy::destroyScope(*this); + + } catch (...) { /* ignore */ } + +} + + +}; + +#endif // __ZTGUARD_H__ + + + + + + + diff --git a/dep/include/zthread/GuardedClass.h b/dep/include/zthread/GuardedClass.h new file mode 100644 index 00000000000..4ef3879cb08 --- /dev/null +++ b/dep/include/zthread/GuardedClass.h @@ -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. + * + */ + +#ifndef __GUARDEDCLASS_H__ +#define __GUARDEDCLASS_H__ + +#include "zthread/Guard.h" +#include "zthread/Mutex.h" + +namespace ZThread { + + /** + * @class GuardedClass + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-20T20:17:34-0400> + * @version 2.3.0 + * + * A simple wrapper template that uses Guard's to provide + * serialized access to an objects member functions. + */ + template <class T, class LockType = Mutex> + class GuardedClass { + + LockType _lock; + T* _ptr; + + class TransferedScope { + public: + + template <class LockType1, class LockType2> + static void shareScope(LockHolder<LockType1>& l1, + LockHolder<LockType2>& l2) { + l1.disable(); + l2.getLock().acquire(); + } + + template <class LockType1> + static void createScope(LockHolder<LockType1>& l) { + // Don't acquire the lock when scope the Guard is created + } + + template <class LockType1> + static void destroyScope(LockHolder<LockType1>& l) { + l.getLock().release(); + } + + }; + + class Proxy : Guard<LockType, TransferedScope> { + + T* _object; + + public: + + Proxy(LockType& lock, T* object) : + Guard<LockType, TransferedScope>(lock), _object(object) { } + + T* operator->() { + return _object; + } + + }; + + GuardedClass(); + GuardedClass& operator=(const GuardedClass&); + + public: + + GuardedClass(T* ptr) : _ptr(ptr) {} + ~GuardedClass() { + if(_ptr) + delete _ptr; + } + + Proxy operator->() { + Proxy p(_lock, _ptr); + return p; + } + + }; + +} // namespace ZThread + +#endif // __ZTGUARDEDCLASS_H__ diff --git a/dep/include/zthread/Lockable.h b/dep/include/zthread/Lockable.h new file mode 100644 index 00000000000..32f7eeda97b --- /dev/null +++ b/dep/include/zthread/Lockable.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 __ZTLOCKABLE_H__ +#define __ZTLOCKABLE_H__ + +#include "zthread/Exceptions.h" + +namespace ZThread { + + /** + * @class Lockable + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T10:33:32-0400> + * @version 2.3.0 + * + * The Lockable interface defines a common method of adding general <i>acquire-release</i> + * semantics to an object. An <i>acquire-release</i> protocol does not necessarily imply + * exclusive access. + */ + class Lockable { + public: + + //! Destroy a Lockable object. + virtual ~Lockable() {} + + /** + * Acquire the Lockable object. + * + * This method may or may not block the caller for an indefinite amount + * of time. Those details are defined by specializations of this class. + * + * @exception Interrupted_Exception thrown if the calling thread is interrupted before + * the operation completes. + * + * @post The Lockable is acquired only if no exception was thrown. + */ + virtual void acquire() = 0; + + /** + * Attempt to acquire the Lockable object. + * + * This method may or may not block the caller for a definite amount + * of time. Those details are defined by specializations of this class; + * however, this method includes a timeout value that can be used to + * limit the maximum amount of time that a specialization <i>could</i> block. + * + * @param timeout - maximum amount of time (milliseconds) this method could block + * + * @return + * - <em>true</em> if the operation completes and the Lockable is acquired before + * the timeout expires. + * - <em>false</em> if the operation times out before the Lockable can be acquired. + * + * @exception Interrupted_Exception thrown if the calling thread is interrupted before + * the operation completes. + * + * @post The Lockable is acquired only if no exception was thrown. + */ + virtual bool tryAcquire(unsigned long timeout) = 0; + + /** + * Release the Lockable object. + * + * This method may or may not block the caller for an indefinite amount + * of time. Those details are defined by specializations of this class. + * + * @post The Lockable is released only if no exception was thrown. + */ + virtual void release() = 0; + + }; + + +} // namespace ZThread + +#endif // __ZTLOCKABLE_H__ diff --git a/dep/include/zthread/LockedQueue.h b/dep/include/zthread/LockedQueue.h new file mode 100644 index 00000000000..a1f0df26431 --- /dev/null +++ b/dep/include/zthread/LockedQueue.h @@ -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. + * + */ + +#ifndef __ZTLOCKEDQUEUE_H__ +#define __ZTLOCKEDQUEUE_H__ + +#include "zthread/Guard.h" +#include "zthread/Queue.h" + +#include <deque> + +namespace ZThread { + + /** + * @class LockedQueue + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T11:42:33-0400> + * @version 2.3.0 + * + * A LockedQueue is the simple Queue implementation that provides + * serialized access to the values added to it. + */ + template <class T, class LockType, typename StorageType=std::deque<T> > + class LockedQueue : public Queue<T> { + + //! Serialize access to the Queue + LockType _lock; + + //! Storage backing the queue + StorageType _queue; + + //! Cancellation flag + volatile bool _canceled; + + public: + + //! Create a LockedQueue + LockedQueue() : _canceled(false) {} + + //! Destroy a LockedQueue + virtual ~LockedQueue() { } + + /** + * @see Queue::add(const T& item) + */ + virtual void add(const T& item) { + + Guard<LockType> g(_lock); + + if(_canceled) + throw Cancellation_Exception(); + + _queue.push_back(item); + + } + + /** + * @see Queue::add(const T& item, unsigned long timeout) + */ + virtual bool add(const T& item, unsigned long timeout) { + + try { + + Guard<LockType> g(_lock, timeout); + + if(_canceled) + throw Cancellation_Exception(); + + _queue.push_back(item); + + } catch(Timeout_Exception&) { return false; } + + return true; + + } + + /** + * @see Queue::next() + */ + virtual T next() { + + Guard<LockType> g(_lock); + + if(_queue.empty() && _canceled) + throw Cancellation_Exception(); + + if(_queue.empty()) + throw NoSuchElement_Exception(); + + T item = _queue.front(); + _queue.pop_front(); + + return item; + + } + + + /** + * @see Queue::next(unsigned long timeout) + */ + virtual T next(unsigned long timeout) { + + Guard<LockType> g(_lock, timeout); + + if(_queue.empty() && _canceled) + throw Cancellation_Exception(); + + if(_queue.empty()) + throw NoSuchElement_Exception(); + + T item = _queue.front(); + _queue.pop_front(); + + return item; + + } + + virtual T front() + { + Guard<LockType> g(_lock); + + if(_queue.empty()) + throw NoSuchElement_Exception(); + + return _queue.front(); + } + + /** + * @see Queue::cancel() + */ + virtual void cancel() { + + Guard<LockType> g(_lock); + + _canceled = true; + + } + + /** + * @see Queue::isCanceled() + */ + virtual bool isCanceled() { + + // Faster check since the queue will not become un-canceled + if(_canceled) + return true; + + Guard<LockType> g(_lock); + + return _canceled; + + } + + /** + * @see Queue::size() + */ + virtual size_t size() { + + Guard<LockType> g(_lock); + return _queue.size(); + + } + + /** + * @see Queue::size(unsigned long timeout) + */ + virtual size_t size(unsigned long timeout) { + + Guard<LockType> g(_lock, timeout); + return _queue.size(); + + } + + }; /* LockedQueue */ + +} // namespace ZThread + +#endif // __ZTLOCKEDQUEUE_H__ diff --git a/dep/include/zthread/MonitoredQueue.h b/dep/include/zthread/MonitoredQueue.h new file mode 100644 index 00000000000..8578fe62b96 --- /dev/null +++ b/dep/include/zthread/MonitoredQueue.h @@ -0,0 +1,345 @@ +/* + * 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 __ZTMONITOREDQUEUE_H__ +#define __ZTMONITOREDQUEUE_H__ + +#include "zthread/Condition.h" +#include "zthread/Guard.h" +#include "zthread/Queue.h" + +#include <deque> + +namespace ZThread { + + /** + * @class MonitoredQueue + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T20:23:28-0400> + * @version 2.3.0 + * + * A MonitoredQueue is a Queue implementation that provides serialized access to the + * items added to it. + * + * - Threads calling the empty() methods will be blocked until the BoundedQueue becomes empty. + * - Threads calling the next() methods will be blocked until the BoundedQueue has a value to + * return. + * + * @see Queue + */ + template <class T, class LockType, typename StorageType=std::deque<T> > + class MonitoredQueue : public Queue<T>, public Lockable { + + //! Serialize access + LockType _lock; + + //! Signaled on not empty + Condition _notEmpty; + + //! Signaled on empty + Condition _isEmpty; + + //! Storage backing the queue + StorageType _queue; + + //! Cancellation flag + volatile bool _canceled; + + public: + + //! Create a new MonitoredQueue + MonitoredQueue() + : _notEmpty(_lock), _isEmpty(_lock), _canceled(false) {} + + //! Destroy a MonitoredQueue, delete remaining items + virtual ~MonitoredQueue() { } + + /** + * Add a value to this Queue. + * + * @param item value to be added to the Queue + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Interrupted_Exception thrown if the thread was interrupted while waiting + * to add a value + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post If no exception is thrown, a copy of <i>item</i> will have been added to the Queue. + * + * @see Queue::add(const T& item) + */ + virtual void add(const T& item) { + + Guard<LockType> g(_lock); + + // Allow no further additions in the canceled state + if(_canceled) + throw Cancellation_Exception(); + + _queue.push_back( item ); + + _notEmpty.signal(); // Wake one waiter + + } + + /** + * Add a value to this Queue. + * + * @param item value to be added to the Queue + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return + * - <em>true</em> if a copy of <i>item</i> can be added before <i>timeout</i> + * milliseconds elapse. + * - <em>false</em> otherwise. + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Interrupted_Exception thrown if the thread was interrupted while waiting + * to add a value + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post If no exception is thrown, a copy of <i>item</i> will have been added to the Queue. + * + * @see Queue::add(const T& item, unsigned long timeout) + */ + virtual bool add(const T& item, unsigned long timeout) { + + try { + + Guard<LockType> g(_lock, timeout); + + if(_canceled) + throw Cancellation_Exception(); + + _queue.push_back(item); + + _notEmpty.signal(); + + } catch(Timeout_Exception&) { return false; } + + return true; + + } + + /** + * Retrieve and remove a value from this Queue. + * + * If invoked when there are no values present to return then the calling thread + * will be blocked until a value arrives in the Queue. + * + * @return <em>T</em> next available value + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Interrupted_Exception thrown if the thread was interrupted while waiting + * to retrieve a value + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post The value returned will have been removed from the Queue. + */ + virtual T next() { + + Guard<LockType> g(_lock); + + while (_queue.empty() && !_canceled) + _notEmpty.wait(); + + if(_queue.empty()) // Queue canceled + throw Cancellation_Exception(); + + T item = _queue.front(); + _queue.pop_front(); + + if(_queue.empty()) // Wake empty waiters + _isEmpty.broadcast(); + + return item; + + } + + /** + * Retrieve and remove a value from this Queue. + * + * If invoked when there are no values present to return then the calling thread + * will be blocked until a value arrives in the Queue. + * + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return <em>T</em> next available value + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Timeout_Exception thrown if the timeout expires before a value + * can be retrieved. + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post The value returned will have been removed from the Queue. + */ + virtual T next(unsigned long timeout) { + + Guard<LockType> g(_lock, timeout); + + while(_queue.empty() && !_canceled) { + if(!_notEmpty.wait(timeout)) + throw Timeout_Exception(); + } + + if( _queue.empty()) // Queue canceled + throw Cancellation_Exception(); + + T item = _queue.front(); + _queue.pop_front(); + + if(_queue.empty()) // Wake empty waiters + _isEmpty.broadcast(); + + return item; + + } + + + /** + * Cancel this queue. + * + * @post Any threads blocked by a next() function will throw a Cancellation_Exception. + * + * @see Queue::cancel() + */ + virtual void cancel() { + + Guard<LockType> g(_lock); + + _canceled = true; + _notEmpty.broadcast(); // Wake next() waiters + + } + + /** + * @see Queue::isCanceled() + */ + virtual bool isCanceled() { + + // Faster check since the queue will not become un-canceled + if(_canceled) + return true; + + Guard<LockType> g(_lock); + + return _canceled; + + } + + + /** + * @see Queue::size() + */ + virtual size_t size() { + + Guard<LockType> g(_lock); + return _queue.size(); + + } + + /** + * @see Queue::size(unsigned long timeout) + */ + virtual size_t size(unsigned long timeout) { + + Guard<LockType> g(_lock, timeout); + return _queue.size(); + + } + + /** + * Test whether any values are available in this Queue. + * + * The calling thread is blocked until there are no values present + * in the Queue. + * + * @return + * - <em>true</em> if there are no values available. + * - <em>false</em> if there <i>are</i> values available. + * + * @see Queue::empty() + */ + virtual bool empty() { + + Guard<LockType> g(_lock); + + while(!_queue.empty()) // Wait for an empty signal + _isEmpty.wait(); + + return true; + + } + + /** + * Test whether any values are available in this Queue. + * + * The calling thread is blocked until there are no values present + * in the Queue. + * + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return + * - <em>true</em> if there are no values available. + * - <em>false</em> if there <i>are</i> values available. + * + * @exception Timeout_Exception thrown if <i>timeout</i> milliseconds + * expire before a value becomes available + * + * @see Queue::empty() + */ + virtual bool empty(unsigned long timeout) { + + Guard<LockType> g(_lock, timeout); + + while(!_queue.empty()) // Wait for an empty signal + _isEmpty.wait(timeout); + + return true; + + } + + public: + + virtual void acquire() { + _lock.acquire(); + } + + virtual bool tryAcquire(unsigned long timeout) { + return _lock.tryAcquire(timeout); + } + + virtual void release() { + _lock.release(); + } + + + }; /* MonitoredQueue */ + + +} // namespace ZThread + +#endif // __ZTMONITOREDQUEUE_H__ + diff --git a/dep/include/zthread/Mutex.h b/dep/include/zthread/Mutex.h new file mode 100644 index 00000000000..1b521b1598d --- /dev/null +++ b/dep/include/zthread/Mutex.h @@ -0,0 +1,135 @@ +/* + * 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 __ZTMUTEX_H__ +#define __ZTMUTEX_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + class FifoMutexImpl; + + /** + * @class Mutex + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T19:35:28-0400> + * @version 2.2.1 + * + * A Mutex is used to provide serialized (one thread at a time) access to some portion + * of code. This is accomplished by attempting to acquire the Mutex before entering that + * piece of code, and by releasing the Mutex when leaving that region. It is a non-reentrant, + * MUTual EXclusion Lockable object. + * + * @see Guard + * + * <b>Scheduling</b> + * + * Threads competing to acquire() a Mutex are granted access in FIFO order. + * + * <b>Error Checking</b> + * + * A Mutex will throw a Deadlock_Exception if an attempt to acquire a Mutex more + * than once is made from the context of the same thread. + * + * A Mutex will throw an InvalidOp_Exception if an attempt to release a Mutex is + * made from the context of a thread that does not currently own that Mutex. + */ + class ZTHREAD_API Mutex : public Lockable, private NonCopyable { + + FifoMutexImpl* _impl; + + public: + + //! Create a new Mutex. + Mutex(); + + //! Destroy this Mutex. + virtual ~Mutex(); + + /** + * Acquire a Mutex, possibly blocking until either the current owner of the + * Mutex releases it or until an exception is thrown. + * + * Only one thread may acquire() the Mutex at any given time. + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * @exception Deadlock_Exception thrown when the same thread attempts to acquire + * a Mutex more than once, without having first release()ed it. + * + * @pre the calling thread must not have already acquired Mutex + * + * @post the calling thread successfully acquired Mutex only if no exception + * was thrown. + * + * @see Lockable::acquire() + */ + virtual void acquire(); + + /** + * Acquire a Mutex, possibly blocking until the current owner of the + * Mutex releases it, until an exception is thrown or until the given amount + * of time expires. + * + * Only one thread may acquire the Mutex at any given time. + * + * @param timeout maximum amount of time (milliseconds) this method could block + * @return + * - <em>true</em> if the lock was acquired + * - <em>false</em> if the lock was acquired + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * @exception Deadlock_Exception thrown when the same thread attempts to acquire + * a Mutex more than once, without having first released it. + * + * @pre the calling thread must not have already acquired Mutex + * + * @post the calling thread successfully acquired Mutex only if no exception + * was thrown. + * + * @see Lockable::tryAcquire(unsigned long timeout) + */ + virtual bool tryAcquire(unsigned long timeout); + + /** + * Release a Mutex allowing another thread to acquire it. + * + * @exception InvalidOp_Exception - thrown if there is an attempt to release is + * a Mutex that was not owner by the calling thread. + * + * @pre the calling thread must have first acquired the Mutex. + * @post the calling thread successfully released Mutex only if no exception + * was thrown. + * + * @see Lockable::release() + */ + virtual void release(); + + }; + + +} // namespace ZThread + +#endif // __ZTMUTEX_H__ diff --git a/dep/include/zthread/NonCopyable.h b/dep/include/zthread/NonCopyable.h new file mode 100644 index 00000000000..5c33f345f46 --- /dev/null +++ b/dep/include/zthread/NonCopyable.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 __ZTNONCOPYABLE_H__ +#define __ZTNONCOPYABLE_H__ + +namespace ZThread { + + /** + * @class NonCopyable + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T19:36:00-0400> + * @version 2.2.11 + * + * Some objects kind of objects should not be copied. This is particularly true + * of objects involved in providing mutually exclusive access to something + * (e.g. Mutexes, Queues, Semaphores, etc.) + * + * Based on Dave Abrahams contribution to the Boost library. + */ + class NonCopyable { + + //! Restrict the copy constructor + NonCopyable(const NonCopyable&); + + //! Restrict the assignment operator + const NonCopyable& operator=(const NonCopyable&); + + protected: + + //! Create a NonCopyable object + NonCopyable() { } + + //! Destroy a NonCopyable object + ~NonCopyable() { } + + }; /* NonCopyable */ + +} // namespace ZThread + +#endif // __ZTNONCOPYABLE_H__ diff --git a/dep/include/zthread/PoolExecutor.h b/dep/include/zthread/PoolExecutor.h new file mode 100644 index 00000000000..82f5c4f05ba --- /dev/null +++ b/dep/include/zthread/PoolExecutor.h @@ -0,0 +1,178 @@ +/* + * 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 __ZTPOOLEXECUTOR_H__ +#define __ZTPOOLEXECUTOR_H__ + +#include "zthread/Executor.h" +#include "zthread/CountedPtr.h" +#include "zthread/Thread.h" + +namespace ZThread { + + namespace { class ExecutorImpl; } + + /** + * @class PoolExecutor + * + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T22:41:07-0400> + * @version 2.3.0 + * + * A PoolExecutor spawns a set of threads that are used to run tasks + * that are submitted in parallel. A PoolExecutor supports the following + * optional operations, + * + * - <em>cancel</em>()ing a PoolExecutor will cause it to stop accepting + * new tasks. + * + * - <em>interrupt</em>()ing a PoolExecutor will cause the any thread running + * a task which was submitted prior to the invocation of this function to + * be interrupted during the execution of that task. + * + * - <em>wait</em>()ing on a PoolExecutor will block the calling thread + * until all tasks that were submitted prior to the invocation of this function + * have completed. + * + * @see Executor. + */ + class PoolExecutor : public Executor { + + //! Reference to the internal implementation + CountedPtr< ExecutorImpl > _impl; + + //! Cancellation task + Task _shutdown; + + public: + + /** + * Create a PoolExecutor + * + * @param n number of threads to service tasks with + */ + PoolExecutor(size_t n); + + //! Destroy a PoolExecutor + virtual ~PoolExecutor(); + + /** + * Invoking this function causes each task that had been submitted prior to + * this function to be interrupted. Tasks submitted after the invocation of + * this function are unaffected. + * + * @post Any task submitted prior to the invocation of this function will be + * run in the context of an interrupted thread. + * @post Any thread already executing a task which was submitted prior to the + * invocation of this function will be interrupted. + */ + virtual void interrupt(); + + /** + * Alter the number of threads being used to execute submitted tasks. + * + * @param n number of worker threads. + * + * @pre <i>n</i> must be greater than 0. + * @post <i>n</i> threads will be executing tasks submitted to this executor. + * + * @exception InvalidOp_Exception thrown if the new number of threads + * <i>n</i> is less than 1. + */ + void size(size_t n); + + /** + * Get the current number of threads being used to execute submitted tasks. + * + * @return n number of worker threads. + */ + size_t size(); + + /** + * Submit a task to this Executor. + * + * This will not block the calling thread very long. The submitted task will + * be executed at some later point by another thread. + * + * @param task Task to be run by a thread managed by this executor + * + * @pre The Executor should have been canceled prior to this invocation. + * @post The submitted task will be run at some point in the future by this Executor. + * + * @exception Cancellation_Exception thrown if the Executor was canceled prior to + * the invocation of this function. + * + * @see PoolExecutor::cancel() + * @see Executor::execute(const Task& task) + */ + virtual void execute(const Task& task); + + /** + * @see Cancelable::cancel() + */ + virtual void cancel(); + + /** + * @see Cancelable::isCanceled() + */ + virtual bool isCanceled(); + + /** + * Block the calling thread until all tasks submitted prior to this invocation + * complete. + * + * @exception Interrupted_Exception thrown if the calling thread is interrupted + * before the set of tasks being wait for can complete. + * + * @see Waitable::wait() + */ + virtual void wait(); + + /** + * Block the calling thread until all tasks submitted prior to this invocation + * complete or until the calling thread is interrupted. + * + * @param timeout maximum amount of time, in milliseconds, to wait for the + * currently submitted set of Tasks to complete. + * + * @exception Interrupted_Exception thrown if the calling thread is interrupted + * before the set of tasks being wait for can complete. + * + * @return + * - <em>true</em> if the set of tasks being wait for complete before + * <i>timeout</i> milliseconds elapse. + * - <em>false</em> otherwise. + * + * @see Waitable::wait(unsigned long timeout) + */ + virtual bool wait(unsigned long timeout); + + }; /* PoolExecutor */ + + +} // namespace ZThread + +#endif // __ZTPOOLEXECUTOR_H__ + + + + diff --git a/dep/include/zthread/Priority.h b/dep/include/zthread/Priority.h new file mode 100644 index 00000000000..907d1f153a8 --- /dev/null +++ b/dep/include/zthread/Priority.h @@ -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 __ZTPRIORITY_H__ +#define __ZTPRIORITY_H__ + +namespace ZThread { + + //! Priorities + typedef enum { + + Low, + Medium = Low + 1, + High = Low + 2 + + } Priority; + +} + +#endif // __ZTPRIORITY_H__ diff --git a/dep/include/zthread/PriorityCondition.h b/dep/include/zthread/PriorityCondition.h new file mode 100644 index 00000000000..1fd86c41c11 --- /dev/null +++ b/dep/include/zthread/PriorityCondition.h @@ -0,0 +1,89 @@ +/* + * 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 __ZTPRIORITYCONDITION_H__ +#define __ZTPRIORITYCONDITION_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" +#include "zthread/Waitable.h" + +namespace ZThread { + + class PriorityConditionImpl; + + /** + * @class PriorityCondition + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T17:35:28-0400> + * @version 2.2.1 + * + * A PriorityCondition is a Condition that is sensitive to thread priority. + * + * @see Condition + * + * <b>Scheduling</b> + * + * Threads blocked on a PriorityCondition are resumed in priority order, highest priority + * first + */ + class ZTHREAD_API PriorityCondition : public Waitable, private NonCopyable { + + PriorityConditionImpl* _impl; + + public: + + /** + * @see Condition::Condition(Lockable& l) + */ + PriorityCondition(Lockable& l); + + /** + * @see Condition::~Condition() + */ + ~PriorityCondition(); + + /** + * @see Condition::signal() + */ + void signal(); + + /** + * @see Condition::broadcast() + */ + void broadcast(); + + /** + * @see Condition::wait() + */ + virtual void wait(); + + /** + * @see Condition::wait(unsigned long timeout) + */ + virtual bool wait(unsigned long timeout); + + }; + +} // namespace ZThread + +#endif // __ZTPRIORITYCONDITION_H__ diff --git a/dep/include/zthread/PriorityInheritanceMutex.h b/dep/include/zthread/PriorityInheritanceMutex.h new file mode 100644 index 00000000000..1a5f5bfd300 --- /dev/null +++ b/dep/include/zthread/PriorityInheritanceMutex.h @@ -0,0 +1,93 @@ +/* + * 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 __ZTPRIORITYINHERITANCEMUTEX_H__ +#define __ZTPRIORITYINHERITANCEMUTEX_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + class PriorityInheritanceMutexImpl; + + /** + * @class PriorityInheritanceMutex + * + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T19:37:36-0400> + * @version 2.2.1 + * + * A PriorityInheritanceMutex is similar to a PriorityMutex, it is a non-reentrant, + * priority sensitive MUTual EXclusion Lockable object. It differs only in its + * scheduling policy. + * + * @see PriorityMutex + * + * <b>Scheduling</b> + * + * Threads competing to acquire() a PriorityInheritanceMutex are granted access in + * order of priority. Threads with a higher priority will be given access first. + * + * When a higher priority thread tries to acquire() a PriorityInheritanceMutex and is + * about to be blocked by a lower priority thread that has already acquire()d it, the + * lower priority thread will temporarily have its effective priority raised to that + * of the higher priority thread until it release()s the mutex; at which point its + * previous priority will be restored. + */ + class ZTHREAD_API PriorityInheritanceMutex : public Lockable, private NonCopyable { + + PriorityInheritanceMutexImpl* _impl; + + public: + + /** + * @see Mutex::Mutex() + */ + PriorityInheritanceMutex(); + + /** + * @see Mutex::~Mutex() + */ + virtual ~PriorityInheritanceMutex(); + + /** + * @see Mutex::acquire() + */ + virtual void acquire(); + + /** + * @see Mutex::tryAcquire(unsigned long timeout) + */ + virtual bool tryAcquire(unsigned long timeout); + + /** + * @see Mutex::release() + */ + virtual void release(); + + }; + + +} // namespace ZThread + +#endif // __ZTPRIORITYINHERITANCEMUTEX_H__ diff --git a/dep/include/zthread/PriorityMutex.h b/dep/include/zthread/PriorityMutex.h new file mode 100644 index 00000000000..477c8d9fd4d --- /dev/null +++ b/dep/include/zthread/PriorityMutex.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 __ZTPRIORITYMUTEX_H__ +#define __ZTPRIORITYMUTEX_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + class PriorityMutexImpl; + + /** + * @class PriorityMutex + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T17:35:46-0400> + * @version 2.2.1 + * + * A PriorityMutex is similar to a Mutex, with exception that a PriorityMutex + * has a difference scheduling policy. It is a non-reentrant, priority sensitive + * MUTual EXclusion Lockable object. + * + * @see Mutex + * + * <b>Scheduling</b> + * + * Threads competing to acquire() a Mutex are granted access in order of priority. Threads + * with a higher priority will be given access first. + */ + class ZTHREAD_API PriorityMutex : public Lockable, private NonCopyable { + + PriorityMutexImpl* _impl; + + public: + + /** + * @see Mutex::Mutex() + */ + PriorityMutex(); + + /** + * @see Mutex::~Mutex() + */ + virtual ~PriorityMutex(); + + /** + * @see Mutex::acquire() + */ + virtual void acquire(); + + /** + * @see Mutex::tryAcquire(unsigned long timeout) + */ + virtual bool tryAcquire(unsigned long timeout); + + /** + * @see Mutex::release() + */ + virtual void release(); + + }; + + +} // namespace ZThread + +#endif // __ZTPRIORITYMUTEX_H__ diff --git a/dep/include/zthread/PrioritySemaphore.h b/dep/include/zthread/PrioritySemaphore.h new file mode 100644 index 00000000000..54ef2c48c52 --- /dev/null +++ b/dep/include/zthread/PrioritySemaphore.h @@ -0,0 +1,111 @@ +/* + * 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 __ZTPRIORITYSEMAPHORE_H__ +#define __ZTPRIORITYSEMAPHORE_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + class PrioritySemaphoreImpl; + + /** + * @class PrioritySemaphore + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T15:36:07-0400> + * @version 2.2.1 + * + * A PrioritySemaphore operates in the same way as a Semaphore. Its an owner-less + * Lockable object that is sensitive to priority. + * + * <b>Scheduling</b> + * + * Threads blocked on a PrioritySemaphore are resumed in priority order, highest + * priority first. + * + * <b>Error Checking</b> + * + * An attempt to increase a PrioritySemaphore beyond its maximum value will result in + * an InvalidOp_Exception. + * + * @see Semaphore + */ + class ZTHREAD_API PrioritySemaphore : public Lockable, private NonCopyable { + + PrioritySemaphoreImpl* _impl; + + public: + + /** + * @see Semaphore::Semaphore(int count, unsigned int maxCount) + */ + PrioritySemaphore(int count = 1, unsigned int maxCount = 1); + + /** + * @see Semaphore::~Semaphore() + */ + virtual ~PrioritySemaphore(); + + /** + * @see Semaphore::wait() + */ + void wait(); + + /** + * @see Semaphore::tryWait(unsigned long) + */ + bool tryWait(unsigned long); + + /** + * @see Semaphore::post() + */ + void post(); + + /** + * @see Semaphore::count() + */ + virtual int count(); + + /** + * @see Semaphore::tryAcquire(unsigned long timeout) + */ + virtual bool tryAcquire(unsigned long timeout); + + /** + * @see Semaphore::acquire() + */ + virtual void acquire(); + + /** + * @see Semaphore::release() + */ + virtual void release(); + + }; + + +} // namespace ZThread + +#endif // __ZTPRIORITYSEMAPHORE_H__ diff --git a/dep/include/zthread/Queue.h b/dep/include/zthread/Queue.h new file mode 100644 index 00000000000..98b83a10c63 --- /dev/null +++ b/dep/include/zthread/Queue.h @@ -0,0 +1,189 @@ +/* + * 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 __ZTQUEUE_H__ +#define __ZTQUEUE_H__ + +#include "zthread/Cancelable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + /** + * @class Queue + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T11:32:42-0400> + * @version 2.3.0 + * + * A Queue defines an interface for a value-oriented collection objects (similar to + * STL collections). + */ + template <typename T> + class Queue : public Cancelable, private NonCopyable { + public: + + //! Destroy a Queue + virtual ~Queue() { } + + /** + * Add an object to this Queue. + * + * @param item value to be added to the Queue + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post If no exception is thrown, a copy of <i>item</i> will have been added to the Queue. + */ + virtual void add(const T& item) = 0; + + /** + * Add an object to this Queue. + * + * @param item value to be added to the Queue + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return + * - <em>true</em> if a copy of <i>item</i> can be added before <i>timeout</i> + * milliseconds elapse. + * - <em>false</em> otherwise. + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post If this function returns true a copy of <i>item</i> will have been added to the Queue. + */ + virtual bool add(const T& item, unsigned long timeout) = 0; + + /** + * Retrieve and remove a value from this Queue. + * + * @return <em>T</em> next available value + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post The value returned will have been removed from the Queue. + */ + virtual T next() = 0; + + /** + * Retrieve and remove a value from this Queue. + * + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return <em>T</em> next available value + * + * @exception Cancellation_Exception thrown if this Queue has been canceled. + * @exception Timeout_Exception thrown if the timeout expires before a value + * can be retrieved. + * + * @pre The Queue should not have been canceled prior to the invocation of this function. + * @post The value returned will have been removed from the Queue. + */ + virtual T next(unsigned long timeout) = 0; + + /** + * Canceling a Queue disables it, disallowing further additions. Values already + * present in the Queue can still be retrieved and are still available through + * the next() methods. + * + * Canceling a Queue more than once has no effect. + * + * @post The next() methods will continue to return objects until + * the Queue has been emptied. + * @post Once emptied, the next() methods will throw a Cancellation_Exception. + * @post The add() methods will throw a Cancellation_Exceptions from this point on. + */ + virtual void cancel() = 0; + + /** + * Count the values present in this Queue. + * + * @return <em>size_t</em> number of elements available in the Queue. + */ + virtual size_t size() = 0; + + /** + * Count the values present in this Queue. + * + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return <em>size_t</em> number of elements available in the Queue. + * + * @exception Timeout_Exception thrown if <i>timeout</i> milliseconds + * expire before a value becomes available + */ + virtual size_t size(unsigned long timeout) = 0; + + /** + * Test whether any values are available in this Queue. + * + * @return + * - <em>true</em> if there are no values available. + * - <em>false</em> if there <i>are</i> values available. + */ + virtual bool empty() { + + try { + + return size() == 0; + + } catch(Cancellation_Exception&) { } + + return true; + + } + + /** + * Test whether any values are available in this Queue. + * + * @param timeout maximum amount of time (milliseconds) this method may block + * the calling thread. + * + * @return + * - <em>true</em> if there are no values available. + * - <em>false</em> if there <i>are</i> values available. + * + * @exception Timeout_Exception thrown if <i>timeout</i> milliseconds + * expire before a value becomes available + */ + virtual bool empty(unsigned long timeout) { + + try { + + return size(timeout) == 0; + + } catch(Cancellation_Exception&) { } + + return true; + + } + + }; /* Queue */ + +} // namespace ZThread + +#endif // __ZTQUEUE_H__ diff --git a/dep/include/zthread/ReadWriteLock.h b/dep/include/zthread/ReadWriteLock.h new file mode 100644 index 00000000000..e01643f1993 --- /dev/null +++ b/dep/include/zthread/ReadWriteLock.h @@ -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. + * + */ + +#ifndef __ZTREADWRITELOCK_H__ +#define __ZTREADWRITELOCK_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + /** + * @class ReadWriteLock + * + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T10:17:31-0400> + * @version 2.2.7 + * + * A ReadWriteLock provides a set of coordinated Lockable objects that can be used to + * guard an object; One for read-only access, and another for read-write access. + * + * @see BiasedReadWriteLock + * @see FairReadWriteLock + */ + class ReadWriteLock : public NonCopyable { + public: + + /** + * Create a ReadWriteLock + * + * @exception Initialization_Exception thrown if resources could not be + * allocated for this object. + */ + ReadWriteLock() {} + + //! Destroy this ReadWriteLock + virtual ~ReadWriteLock() {} + + /** + * Get a reference to the read-only Lockable. + * + * @return <em>Lockable&</em> reference to a Lockable that provides read-only + * access. + */ + virtual Lockable& getReadLock() = 0; + + /** + * Get a reference to the read-write Lockable. + * + * @return <em>Lockable&</em> reference to a Lockable that provides read-write + * access. + */ + virtual Lockable& getWriteLock() = 0; + + + }; /* ReadWriteLock */ + + +}; // __ZTREADWRITELOCK_H__ + +#endif diff --git a/dep/include/zthread/RecursiveMutex.h b/dep/include/zthread/RecursiveMutex.h new file mode 100644 index 00000000000..7dda9c5119b --- /dev/null +++ b/dep/include/zthread/RecursiveMutex.h @@ -0,0 +1,123 @@ +/* + * 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 __ZTRECURSIVEMUTEX_H__ +#define __ZTRECURSIVEMUTEX_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + class RecursiveMutexImpl; + + /** + * @class RecursiveMutex + * + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T17:51:33-0400> + * @version 2.2.1 + * + * A RecursiveMutex is a recursive, MUTual EXclusion Lockable object. It is + * recursive because it can be acquire()d and release()d more than once + * by the same thread, instead of causing a Deadlock_Exception. + * + * @see Mutex + * @see Guard + * + * <b>Scheduling</b> + * + * Threads competing to acquire() a Mutex are granted access in FIFO order. + * + * <b>Error Checking</b> + * + * A Mutex will throw an InvalidOp_Exception if an attempt to release() a Mutex is + * made from the context of a thread that does not currently own that Mutex. + */ + class ZTHREAD_API RecursiveMutex : public Lockable, private NonCopyable { + + RecursiveMutexImpl* _impl; + + public: + + //! Create a new RecursiveMutex. + RecursiveMutex(); + + //! Destroy this RecursiveMutex. + virtual ~RecursiveMutex(); + + /** + * Acquire a RecursiveMutex, possibly blocking until the the current owner of the + * releases it or until an exception is thrown. + * + * Only one thread may acquire the RecursiveMutex at any given time. + * The same thread may acquire a RecursiveMutex multiple times. + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * + * @post the calling thread successfully acquire ed RecursiveMutex only if no exception + * was thrown. + * + * @see Lockable::acquire() + */ + virtual void acquire(); + + /** + * Acquire a RecursiveMutex, possibly blocking until the the current owner + * releases it, until an exception is thrown or until the given amount + * of time expires. + * + * Only one thread may acquire the RecursiveMutex at any given time. + * The same thread may acquire a RecursiveMutex multiple times. + * + * @param timeout maximum amount of time (milliseconds) this method could block + * @return + * - <em>true</em> if the lock was acquired + * - <em>false</em> if the lock was acquired + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * + * @post the calling thread successfully acquired RecursiveMutex only if no exception + * was thrown. + * + * @see Lockable::tryAcquire(unsigned long timeout) + */ + virtual bool tryAcquire(unsigned long timeout); + + + /** + * Release exclusive access. No safety or state checks are performed. + * + * @pre This should not be called more times than the acquire() method was + * called. + * + * @see Lockable::release() + */ + virtual void release(); + + }; + +} // namespace ZThread + +#endif // __ZTRECURSIVEMUTEX_H__ diff --git a/dep/include/zthread/Runnable.h b/dep/include/zthread/Runnable.h new file mode 100644 index 00000000000..98628530a14 --- /dev/null +++ b/dep/include/zthread/Runnable.h @@ -0,0 +1,58 @@ +/* + * 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 __ZTRUNNABLE_H__ +#define __ZTRUNNABLE_H__ + +#include "zthread/Config.h" + +namespace ZThread { + + /** + * @class Runnable + * + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T17:45:35-0400> + * @version 2.2.11 + * + * Encapsulates a Runnable task. + */ + class Runnable { + public: + + /** + * Runnables should never throw in their destructors + */ + virtual ~Runnable() {} + + /** + * Task to be performed in another thread of execution + */ + virtual void run() = 0; + + }; + + +} + +#endif // __ZTRUNNABLE_H__ diff --git a/dep/include/zthread/Semaphore.h b/dep/include/zthread/Semaphore.h new file mode 100644 index 00000000000..2a9e4d02d03 --- /dev/null +++ b/dep/include/zthread/Semaphore.h @@ -0,0 +1,150 @@ +/* + * 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 __ZTSEMAPHORE_H__ +#define __ZTSEMAPHORE_H__ + +#include "zthread/Lockable.h" +#include "zthread/NonCopyable.h" + +namespace ZThread { + + class FifoSemaphoreImpl; + + /** + * @class Semaphore + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T15:28:01-0400> + * @version 2.2.1 + * + * A Semaphore is an owner-less Lockable object. Its probably best described as + * a set of 'permits'. A Semaphore is initialized with an initial count and + * a maximum count, these would correspond to the number of 'permits' currently + * available and the number of' permits' in total. + * + * - Acquiring the Semaphore means taking a permit, but if there are none + * (the count is 0) the Semaphore will block the calling thread. + * + * - Releasing the Semaphore means returning a permit, unblocking a thread + * waiting for one. + * + * A Semaphore with an initial value of 1 and maximum value of 1 will act as + * a Mutex. + * + * Threads blocked on a Semaphore are resumed in FIFO order. + * + */ + class ZTHREAD_API Semaphore : public Lockable, private NonCopyable { + + FifoSemaphoreImpl* _impl; + + public: + + /** + * Create a new Semaphore. + * + * @param count initial count + * @param maxCount maximum count + */ + Semaphore(int count = 1, unsigned int maxCount = 1); + + //! Destroy the Semaphore + virtual ~Semaphore(); + + /** + * <i>Provided to reflect the traditional Semaphore semantics</i> + * + * @see acquire() + */ + void wait(); + + + /** + * <i>Provided to reflect the traditional Semaphore semantics</i> + * + * @see tryAcquire(unsigned long timeout) + */ + bool tryWait(unsigned long timeout); + + /** + * <i>Provided to reflect the traditional Semaphore semantics</i> + * + * @see release() + */ + void post(); + + + /** + * Get the current count of the semaphore. + * + * This value may change immediately after this function returns to the calling thread. + * + * @return <em>int</em> count + */ + virtual int count(); + + /** + * Decrement the count, blocking that calling thread if the count becomes 0 or + * less than 0. The calling thread will remain blocked until the count is + * raised above 0, an exception is thrown or the given amount of time expires. + * + * @param timeout maximum amount of time (milliseconds) this method could block + * + * @return + * - <em>true</em> if the Semaphore was acquired before <i>timeout</i> milliseconds elapse. + * - <em>false</em> otherwise. + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * + * @see Lockable::tryAcquire(unsigned long timeout) + */ + virtual bool tryAcquire(unsigned long timeout); + + + /** + * Decrement the count, blocking that calling thread if the count becomes 0 or + * less than 0. The calling thread will remain blocked until the count is + * raised above 0 or if an exception is thrown. + * + * @exception Interrupted_Exception thrown when the calling thread is interrupted. + * A thread may be interrupted at any time, prematurely ending any wait. + * + * @see Lockable::acquire() + */ + virtual void acquire(); + + /** + * Increment the count, unblocking one thread if count is positive. + * + * @exception InvalidOp_Exception thrown if the maximum count would be exceeded. + * + * @see Lockable::release() + */ + virtual void release(); + + }; + + +} // namespace ZThread + +#endif // __ZTSEMAPHORE_H__ diff --git a/dep/include/zthread/Singleton.h b/dep/include/zthread/Singleton.h new file mode 100644 index 00000000000..b66c9d0898a --- /dev/null +++ b/dep/include/zthread/Singleton.h @@ -0,0 +1,249 @@ +/* + * 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 __ZTSINGLETON_H__ +#define __ZTSINGLETON_H__ + +#include "zthread/Guard.h" +#include "zthread/FastMutex.h" +#include <assert.h> + +namespace ZThread { + +// +// This policy controls how an object is instantiated +// as well as how and when its destroyed. Phoenix-style +// singletons are not supported easily with type of policy, +// this is intentional since I do not believe that is in +// the true spirit of a singleton. +// +// InstantiationPolicContract { +// +// create(pointer_type&) +// +// } + +/** + * @class LocalStaticInstantiation + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T17:57:45-0400> + * @version 2.2.0 + * + * The LocalStaticInstantiation policy allows the creation + * and lifetime of an instance of a particular type + * to be managed using static local values. This will + * abide by the standard C++ rules for static objects + * lifetimes. + */ +class LocalStaticInstantiation { +protected: + + /** + * Create an instance of an object, using a local static. The + * object will be destroyed by the system. + * + * @param ptr reference to location to receive the address + * of the allocated object + */ + template <class T> + static void create(T*& ptr) { + + static T instance; + ptr = &instance; + + } + +}; + +//! Helper class +template <class T> +class StaticInstantiationHelper { + //! Friend class + friend class StaticInstantiation; + //! Holder + static T instance; + + }; + + template <class T> + T StaticInstantiationHelper<T>::instance; + +/** + * @class StaticInstantiation + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T17:57:45-0400> + * @version 2.2.0 + * + * The StaticInstantiation policy allows the creation + * and lifetime of an instance of a particular type + * to be managed using static instantiation. This will + * abide by the standard C++ rules for static objects + * lifetimes. + */ +class StaticInstantiation { +protected: + + /** + * Create an instance of an object using by simply allocating it statically. + * + * @param ptr reference to location to receive the address + * of the allocated object + */ + template <class T> + static void create(T*& ptr) { + ptr = &StaticInstantiationHelper<T>::instance; + } + +}; + +//! SingletonDestroyer +template <class T> +class Destroyer { + + T* doomed; + + public: + + Destroyer(T* q) : doomed(q) { + assert(doomed); + } + + ~Destroyer(); + +}; + +template <class T> +Destroyer<T>::~Destroyer() { + + try { + + if(doomed) + delete doomed; + + } catch(...) { } + + doomed = 0; + +} + + +/** + * @class LazyInstantiation + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T17:57:45-0400> + * @version 2.2.0 + * + * The LazyInstantiation policy allows the creation + * and lifetime of an instance of a particular type + * to be managed using dynamic allocation and a singleton + * destroyer. This will abide by the standard C++ rules + * for static objects lifetimes. + */ +class LazyInstantiation { +protected: + + /** + * Create an instance of an object, using new, that will be + * destroyed when an associated Destroyer object (allocated + * statically) goes out of scope. + * + * @param ptr reference to location to receive the address + * of the allocated object + */ + template <class T> + static void create(T*& ptr) { + + ptr = new T; + static Destroyer<T> destroyer(ptr); + + } + +}; + + +/** + * @class Singleton + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T17:57:45-0400> + * @version 2.2.0 + * + * Based on the work of John Vlissidles in his book 'Pattern Hatching' + * an article by Douglas Schmidtt on double-checked locking and policy + * templates described by Andrei Alexandrescu. + * + * This is a thread safe wrapper for creating Singleton classes. The + * synchronization method and instantiation methods can be changed + * easily by specifying different policy implementations as the + * templates parameters. + * + * @code + * + * // Most common Singleton + * Singletion<LonesomeType> + * + * // Singleton that uses static storage + * Singletion<LonesomeType, StaticInstantiation> + * + * // Single-threaded singleton that uses static storage (Meyers-like) + * Singletion<LonesomeType, LocalStaticInstantiation, NotLocked> + * + * @endcode + */ +template <class T, class InstantiationPolicy=LazyInstantiation, class LockType=FastMutex> +class Singleton : private InstantiationPolicy, private NonCopyable { +public: + + /** + * Provide access to the single instance through double-checked locking + * + * @return T* single instance + */ + static T* instance(); + +}; + +template <class T, class InstantiationPolicy, class LockType> +T* Singleton<T, InstantiationPolicy, LockType>::instance() { + + // Uses local static storage to avoid static construction + // sequence issues. (regaring when the lock is created) + static T* ptr = 0; + static LockType lock; + + if(!ptr) { + + Guard<LockType, LockedScope> g(lock); + if(!ptr) + InstantiationPolicy::create(ptr); + + } + + return const_cast<T*>(ptr); + + } + + +}; + +#endif + + diff --git a/dep/include/zthread/SynchronousExecutor.h b/dep/include/zthread/SynchronousExecutor.h new file mode 100644 index 00000000000..b6dbbef6af6 --- /dev/null +++ b/dep/include/zthread/SynchronousExecutor.h @@ -0,0 +1,126 @@ +/* + * 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 __ZTSYNCHRONOUSEXECUTOR_H__ +#define __ZTSYNCHRONOUSEXECUTOR_H__ + +#include "zthread/Executor.h" +#include "zthread/Guard.h" +#include "zthread/Mutex.h" +#include "zthread/Thread.h" + +namespace ZThread { + + /** + * @class SynchronousExecutor + * + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T22:33:51-0400> + * @version 2.3.0 + * + * A SynchronousExecutor is an Executor which runs tasks using the thread that + * submits the task. It runs tasks serially, one at a time, in the order they + * were submitted to the executor. + * + * @see Executor. + */ + class SynchronousExecutor : public Executor { + + //! Serialize access + Mutex _lock; + + //! Cancellation flag + bool _canceled; + + public: + + //! Create a new SynchronousExecutor + SynchronousExecutor(); + + //! Destroy a SynchronousExecutor + virtual ~SynchronousExecutor(); + + /** + * This operation is not supported by this executor. + */ + virtual void interrupt(); + + /** + * Submit a task to this Executor, blocking the calling thread until the + * task is executed. + * + * @param task Task to be run by a thread managed by this executor + * + * @pre The Executor should have been canceled prior to this invocation. + * @post The submitted task will be run at some point in the future by this Executor. + * + * @exception Cancellation_Exception thrown if the Executor was canceled prior to + * the invocation of this function. + * + * @see Executor::execute(const Task& task) + */ + virtual void execute(const Task& task); + + /** + * @see Cancelable::cancel() + */ + virtual void cancel(); + + /** + * @see Cancelable::cancel() + */ + virtual bool isCanceled(); + + /** + * Block the calling thread until all tasks submitted prior to this invocation + * complete. + * + * @exception Interrupted_Exception thrown if the calling thread is interrupted + * before the set of tasks being wait for can complete. + * + * @see Executor::wait() + */ + virtual void wait(); + + /** + * Block the calling thread until all tasks submitted prior to this invocation + * complete or until the calling thread is interrupted. + * + * @param timeout - maximum amount of time, in milliseconds, to wait for the + * currently submitted set of Tasks to complete. + * + * @exception Interrupted_Exception thrown if the calling thread is interrupted + * before the set of tasks being wait for can complete. + * + * @return + * - <em>true</em> if the set of tasks being wait for complete before + * <i>timeout</i> milliseconds elapse. + * - <em>false</em> othewise. + */ + virtual bool wait(unsigned long timeout); + + + }; /* SynchronousExecutor */ + +} // namespace ZThread + +#endif // __ZTSYNCHRONOUSEXECUTOR_H__ diff --git a/dep/include/zthread/Task.h b/dep/include/zthread/Task.h new file mode 100644 index 00000000000..6503be66f33 --- /dev/null +++ b/dep/include/zthread/Task.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 __ZTTASK_H__ +#define __ZTTASK_H__ + +#include "zthread/CountedPtr.h" +#include "zthread/Runnable.h" + +namespace ZThread { + + class ThreadImpl; + + /** + * @class Task + * + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-20T05:22:38-0400> + * @version 2.3.0 + * + * A Task provides a CountedPtr wrapper for Runnable objects. + * This wrapper enables an implicit conversion from a + * <i>Runnable*</i> to a <i>Task</i> adding some syntactic sugar + * to the interface. + */ + class ZTHREAD_API Task : public CountedPtr<Runnable, AtomicCount> { + public: + + +#if !defined(_MSC_VER) || (_MSC_VER > 1200) + + Task(Runnable* raw) + : CountedPtr<Runnable, AtomicCount>(raw) { } + +#endif + + template <typename U> + Task(U* raw) + : CountedPtr<Runnable, AtomicCount>(raw) { } + + Task(const CountedPtr<Runnable, AtomicCount>& ptr) + : CountedPtr<Runnable, AtomicCount>(ptr) { } + + template <typename U, typename V> + Task(const CountedPtr<U, V>& ptr) + : CountedPtr<Runnable, AtomicCount>(ptr) { } + + void operator()() { + (*this)->run(); + } + + }; /* Task */ + +} // namespace ZThread + +#endif // __ZTTASK_H__ + + + diff --git a/dep/include/zthread/Thread.h b/dep/include/zthread/Thread.h new file mode 100644 index 00000000000..e1700c737fa --- /dev/null +++ b/dep/include/zthread/Thread.h @@ -0,0 +1,381 @@ +/* + * 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 __ZTTHREAD_H__ +#define __ZTTHREAD_H__ + +#include "zthread/Cancelable.h" +#include "zthread/Priority.h" +#include "zthread/NonCopyable.h" +#include "zthread/Task.h" +#include "zthread/Waitable.h" + +namespace ZThread { + + class ThreadImpl; + + /** + * @class Thread + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-27T11:17:59-0400> + * @version 2.3.0 + * + * + * @see Task + * @see Executor + * + * <h2>Examples</h2> + * - <a href="#ex1">Launching a task</a> + * - <a href="#ex2">Waiting for a task</a> + * - <a href="#ex3">Sharing a task</a> + * + * <h2><a name="ex1">Launching a task</a></h2> + * + * A thread is started simply by constructing a thread object and giving + * it a task to perform. The thread will continue to run its task, even + * after the Thread object used to launch the thread has gone out of scope. + * + * @code + * #include "zthread/Thread.h" + * #include <iostream> + * + * using namespace ZThread; + * + * class aRunnable : public Runnable { + * + * void run() { + * + * Thread::sleep(1000); + * std::cout << "Hello from another thread" << std::endl; + * + * } + * + * }; + * + * int main() { + * + * try { + * + * // Implictly constructs a Task + * Thread t(new aRunnable); + * + * } catch(Synchronization_Exception& e) { + * std::cerr << e.what() << std::endl; + * } + * + * std::cout << "Hello from the main thread" << std::endl; + * + * // Output: + * + * // Hello from the main thread + * // Hello from another thread + * + * return 0; + * + * } + * + * @endcode + * + * <h2><a name="ex2">Waiting for a task</a></h2> + * + * A user can exercise some simple synchronization by waiting for a thread + * to complete running its task. + * + * @code + * #include "zthread/Thread.h" + * #include <iostream> + * + * using namespace ZThread; + * + * class aRunnable : public Runnable { + * public: + * + * void run() { + * + * Thread::sleep(1000); + * std::cout << "Hello from another thread" << std::endl; + * + * } + * + * }; + * + * int main() { + * + * try { + * + * // Implictly constructs a Task + * Thread t(new aRunnable); + * t.wait(); + * + * } catch(Synchronization_Exception& e) { + * std::cerr << e.what() << std::endl; + * } + * + * std::cout << "Hello from the main thread" << std::endl; + * + * // Output: + * + * // Hello from another thread + * // Hello from the main thread + * + * return 0; + * + * } + * + * @endcode + * + * <h2><a name="ex3">Sharing a task</a></h2> + * + * The same task can be shared by more than one thread. A Task is constructed + * from a Runnable, and that Task object is copied by value and handed off to + * each thread. + * + * @code + * #include "zthread/Thread.h" + * #include <iostream> + * + * using namespace ZThread; + * + * class aRunnable : public Runnable { + * + * void run() { + * + * Thread::sleep(1000); + * std::cout << "Hello from another thread" << std::endl; + * + * } + * + * }; + * + * int main() { + * + * try { + * + * // Explictly constructs a Task + * Task task(new aRunnable); + * + * // Two threads created to run the same Task + * Thread t1(task); + * Thread t2(task); + * + * } catch(Synchronization_Exception& e) { + * std::cerr << e.what() << std::endl; + * } + * + * std::cout << "Hello from the main thread" << std::endl; + * + * // Output: + * + * // Hello from the main thread + * // Hello from another thread + * // Hello from another thread + * + * return 0; + * + * } + * + * @endcode + */ + class ZTHREAD_API Thread + : public Cancelable, public Waitable, public NonCopyable { + + //! Delegate + ThreadImpl* _impl; + + public: + + /** + * Create a Thread that represents the current thread. + * <em>Using the static members of Thread should be preferred over using this constructor</em> + */ + Thread(); + + /** + * Create a Thread that spawns a new thread to run the given task. + * + * @param task Task to be run by a thread managed by this executor + * @param autoCancel flag to requestion automatic cancellation + * + * @post if the <i>autoCancel</i> flag was true, this thread will + * automatically be canceled when main() goes out of scope. + */ + Thread(const Task&, bool autoCancel = false); + + //! Destroy the Thread + ~Thread(); + + //! Comparison operator + bool operator==(const Thread& t) const; + + //! Comparison operator + inline bool operator!=(const Thread& t) const { + return !(*this == t); + } + + /** + * Wait for the thread represented by this object to complete its task. + * The calling thread is blocked until the thread represented by this + * object exits. + * + * @exception Deadlock_Exception thrown if thread attempts to join itself + * @exception InvalidOp_Exception thrown if the thread cannot be joined + * @exception Interrupted_Exception thrown if the joining thread has been interrupt()ed + */ + void wait(); + + /** + * Wait for the thread represented by this object to complete its task. + * The calling thread is blocked until the thread represented by this + * object exits, or until the timeout expires. + * + * @param timeout maximum amount of time (milliseconds) this method + * could block the calling thread. + * + * @return + * - <em>true</em> if the thread task complete before <i>timeout</i> + * milliseconds elapse. + * - <em>false</em> othewise. + * + * @exception Deadlock_Exception thrown if thread attempts to join itself + * @exception InvalidOp_Exception thrown if the thread cannot be joined + * @exception Interrupted_Exception thrown if the joining thread has been interrupt()ed + */ + bool wait(unsigned long timeout); + + /** + * Change the priority of this Thread. This will change the actual + * priority of the thread when the OS supports it. + * + * If there is no real priority support, it's simulated. + * + * @param p - new Priority + */ + void setPriority(Priority p); + + /** + * Get the priority of this Thread. + * + * @return Priority + */ + Priority getPriority(); + + /** + * Interrupts this thread, setting the <i>interrupted</i> status of the thread. + * This status is cleared by one of three methods. + * + * If this thread is blocked when this method is called, the thread will + * abort that blocking operation with an Interrupted_Exception. + * + * - The first is by attempting an operation on a synchronization object that + * would normally block the calling thread; Instead of blocking the calling + * the calling thread, the function that would normally block will thrown an + * Interrupted_Exception and clear the <i>interrupted</i> status of the thread. + * + * - The second is by calling Thread::interrupted(). + * + * - The third is by calling Thread::canceled(). + * + * Threads already blocked by an operation on a synchronization object will abort + * that operation with an Interrupted_Exception, clearing the threads <i>interrupted</i> + * status as in the first case described above. + * + * Interrupting a thread that is no longer running will have no effect. + * + * @return + * - <em>true</em> if the thread was interrupted while not blocked by a wait + * on a synchronization object. + * - <em>false</em> othewise. + */ + bool interrupt(); + + /** + * Tests whether the current Thread has been interrupt()ed, clearing + * its interruption status. + * + * @return + * - <em>true</em> if the Thread was interrupted. + * - <em>false</em> otherwise. + * + * @post The <i>interrupted</i> status of the current thread will be cleared, + * allowing it to perform a blocking operation on a synchronization + * object without throwing an exception. + */ + static bool interrupted(); + + /** + * Tests whether the current Thread has been canceled, and clears the + * interrupted status. + * + * @return bool true only if the Thread::cancel() has been invoked. + */ + static bool canceled(); + + /** + * Tests whether this thread has been canceled. If called from the context + * of this thread, the interrupted status is cleared. + * + * @return + * - <em>true</em> if the Thread was canceled. + * - <em>false</em> otherwise. + * + * @see Cancelable::isCanceled() + */ + virtual bool isCanceled(); + + /** + * Interrupt and cancel this thread in a single operation. The thread will + * return <em>true</em> whenever its cancelation status is tested in the future. + * + * @exception InvalidOp_Exception thrown if a thread attempts to cancel itself + * + * @see Thread::interrupt() + * @see Cancelable::cancel() + */ + virtual void cancel(); + + /** + * Put the currently executing thread to sleep for a given amount of + * time. + * + * @param timeout maximum amount of time (milliseconds) this method could block + * + * @exception Interrupted_Exception thrown if the threads sleep is interrupted + * before <i>timeout</i> milliseconds expire. + */ + static void sleep(unsigned long timeout); + + /** + * Cause the currently executing thread to yield, allowing the scheduler + * to assign some execution time to another thread. + */ + static void yield(); + + + }; /* Thread */ + + +} // namespace ZThread + +#endif // __ZTTHREAD_H__ + + + diff --git a/dep/include/zthread/ThreadLocal.h b/dep/include/zthread/ThreadLocal.h new file mode 100644 index 00000000000..bb83a0fe3ef --- /dev/null +++ b/dep/include/zthread/ThreadLocal.h @@ -0,0 +1,382 @@ +/* + * 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 __ZTTHREADLOCAL_H__ +#define __ZTTHREADLOCAL_H__ + +#include "zthread/ThreadLocalImpl.h" + +namespace ZThread { + + /** + * @class ThreadLocal + * + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-27T11:18:21-0400> + * @version 2.3.0 + * + * Provides access to store and retrieve value types to and from a thread local + * storage context. A thread local storage context consists of the calling thread + * a specific ThreadLocal object. Since this context is specific to each thread + * whenever a value is stored in a ThreadLocal that is accessible from multiple + * threads, it can only be retrieved by the thread that stored it. + * + * The first time a thread accesses the value associated with a thread local storage + * context, a value is created. That value is either an initial value (determined by + * InitialValueT) or an inherited value (determined by ChildValueT). + * + * - If a threads parent had no value associated with a ThreadLocal when the thread was created, + * then the InitialValueT functor is used to create an initial value. + * + * - If a threads parent did have a value associated with a ThreadLocal when the thread was + * created, then the childValueT functor is used to create an initial value. + * + * Not all ThreadLocal's support the inheritance of values from parent threads. The default + * behavoir is to create values through the InitialValueT functor for all thread when + * they first access a thread local storage context. + * + * - Inheritance is enabled automatically when a user supplies a ChildValueT functor other + * than the default one supplied. + * + * - Inheritance can be controlled explicitly by the user through a third functor, + * InheritableValueT. + * + * <h2>Examples</h2> + * + * - <a href="#ex1">Default initial value</a> + * - <a href="#ex2">User-specified initial value</a> + * - <a href="#ex3">User-specified inherited value</a> + * + * <h2><a name="ex1">Default initial value</a></h2> + * A ThreadLocal that does not inherit, and uses the default value + * for an int as its initial value. + * + * @code + * + * #include "zthread/ThreadLocal.h" + * #include "zthread/Thread.h" + * #include <iostream> + * + * using namespace ZThread; + * + * class aRunnable : public Runnable { + * ThreadLocal<int> localValue; + * public: + * void run() { + * std::cout << localValue.get() << std::endl; + * } + * }; + * + * int main() { + * + * // Create a shared task to display ThreadLocal values + * Task task(new aRunnable); + * + * Thread t0(task); t0.wait(); + * Thread t1(task); t1.wait(); + * Thread t2(task); t2.wait(); + * + * // Output: + * + * // 0 + * // 0 + * // 0 + * + * return 0; + * + * } + * + * @endcode + * + * <h2><a name="ex2">User-specified initial value</a></h2> + * A ThreadLocal that does not inherit, and uses a custom initial value. + * + * @code + * + * #include "zthread/ThreadLocal.h" + * #include "zthread/Thread.h" + * #include <iostream> + * + * using namespace ZThread; + * + * struct anInitialValueFn { + * int operator()() { + * static int next = 100; + * int val = next; next += 100; + * return val; + * } + * }; + * + * class aRunnable : public Runnable { + * ThreadLocal<int, anInitialValueFn> localValue; + * public: + * void run() { + * std::cout << localValue.get() << std::endl; + * } + * }; + * + * int main() { + * + * // Create a shared task to display ThreadLocal values + * Task task(new aRunnable); + * + * Thread t0(task); t0.wait(); + * Thread t1(task); t1.wait(); + * Thread t2(task); t2.wait(); + * + * // Output: + * + * // 100 + * // 200 + * // 300 + * + * return 0; + * + * } + * + * @endcode + * + * <h2><a name="ex3">User-specified inherited value</a></h2> + * A ThreadLocal that does inherit and modify child values. + * (The default initial value functor is used) + * + * @code + * + * #include "zthread/ThreadLocal.h" + * #include "zthread/Thread.h" + * #include <iostream> + * + * using namespace ZThread; + * + * struct anInheritedValueFn { + * int operator()(int val) { + * return val + 100; + * } + * }; + * + * // This Runnable associates no ThreadLocal value in the main thread; so + * // none of the child threads have anything to inherit. + * class aRunnable : public Runnable { + * ThreadLocal<int, ThreadLocalImpl::InitialValueFn<int>, anInheritedValueFn> localValue; + * public: + * void run() { + * std::cout << localValue.get() << std::endl; + * } + * }; + * + * // This Runnable associates a ThreadLocal value in the main thread which + * // is inherited when the child threads are created. + * class anotherRunnable : public Runnable { + * ThreadLocal<int, ThreadLocalImpl::InitialValueFn<int>, anInheritedValueFn> localValue; + * public: + * anotherRunnable() { + * localValue.set(100); + * } + * void run() { + * std::cout << localValue.get() << std::endl; + * } + * }; + * + * int main() { + * + * // Create a shared task to display ThreadLocal values + * Task task(new aRunnable); + * + * Thread t0(task); t0.wait(); + * Thread t1(task); t1.wait(); + * Thread t2(task); t2.wait(); + * + * // Output: + * + * // 0 + * // 0 + * // 0 + * + * task = Task(new anotherRunnable); + * + * Thread t10(task); t10.wait(); + * Thread t11(task); t11.wait(); + * Thread t12(task); t12.wait(); + * + * // Output: + * + * // 200 + * // 200 + * // 200 + * + * return 0; + * + * } + * + * @endcode + * + * <h2>Parameters</h2> + * + * <em>InitialValueT</em> + * + * This template parameter should indicate the functor used to set + * the initial value. It should support the following operator: + * + * <code> + * // required operator + * T operator() + * + * // supported expression + * InitialValueT()() + * </code> + * + * + * <em>ChildValueT</em> + * + * This template parameter should indicate the functor used to set + * the value that will be inherited by thread whose parent have associated + * a value with the ThreadLocal's context at the time they are created. + * It should support the following operator: + * + * <code> + * // required operator + * T operator(const T& parentValue) + * + * // supported expression + * ChildValueT()(parentValue) + * </code> + * + * + * <em>InheritableValueT</em> + * + * This template parameter should indicate the functor, used to determine + * wheather or not this ThreadLocal will allow values from a parent threads + * context to be inherited by child threads when they are created. + * It should support the following operator: + * + * <code> + * // required operator + * bool operator(const T& childValueFunctor) + * + * // supported expression + * InheritableValueT()( ChildValueT() ) + * </code> + * + */ + template < + typename T, + typename InitialValueT = ThreadLocalImpl::InitialValueFn<T>, + typename ChildValueT = ThreadLocalImpl::UniqueChildValueFn, + typename InheritableValueT = ThreadLocalImpl::InheritableValueFn + > + class ThreadLocal : private ThreadLocalImpl { + + typedef ThreadLocalImpl::ValuePtr ValuePtr; + + class Value : public ThreadLocalImpl::Value { + + T value; + + public: + + Value() : value( InitialValueT()() ) { } + + Value(const Value& v) : value( ChildValueT()(v.value) ) { } + + virtual ~Value() { } + + operator T() { return value; } + + const Value& operator=(const T& v) { value = v; } + + virtual bool isInheritable() const { + return InheritableValueT()( ChildValueT() ); + } + + virtual ValuePtr clone() const { + return ValuePtr( new Value(*this) ); + } + + }; + + static ValuePtr createValue() { + return ValuePtr( new Value ); + } + + public: + + /** + * Get the value associated with the context (this ThreadLocal and + * the calling thread) of the invoker. If no value is currently + * associated, then an intial value is created and associated; that value + * is returned. + * + * @return <em>T</em> associated value. + * + * @post If no value has been associated with the invoking context + * then an inital value will be associated. That value is + * created by the <em>InitialValueT</em> functor. + */ + T get() const { + return (T)reinterpret_cast<Value&>( *value(&createValue) ); + } + + /** + * Replace the value associated with the context (this ThreadLocal and + * the calling thread) of the invoker. If no value is currently + * associated, then an intial value is first created and subsequently + * replaced by the new value. + * + * @param v value of type <em>T</em> to associate. + * + * @post If no value has been associated with the invoking context + * then an inital value will first be associated. That value is + * created by the <em>InitialValueT</em> functor and then + * replaced with the new value. + */ + void set(T v) const { + reinterpret_cast<Value&>( *value(&createValue) ) = v; + } + + /** + * Remove any value current associated with this ThreadLocal. + * + * @post Upon thier next invocation the get() and set() functions will behave as + * if no value has been associated with this ThreadLocal and an + * initial value will be generated. + */ + void clear() const { + ThreadLocalImpl::clear(); + } + + /** + * Remove any value current associated with <em>any</em> ThreadLocal. + * + * @post Upon thier next invocation the get() and set() functions will behave as + * if no value has been associated with <em>any</em> ThreadLocal and new + * initial values will be generated. + */ + static void clearAll() { + ThreadLocalImpl::clearAll(); + } + + }; + + +} // namespace ZThread + +#endif // __ZTTHREADLOCAL_H__ diff --git a/dep/include/zthread/ThreadLocalImpl.h b/dep/include/zthread/ThreadLocalImpl.h new file mode 100644 index 00000000000..3b4046f8f58 --- /dev/null +++ b/dep/include/zthread/ThreadLocalImpl.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 __ZTTHREADLOCALIMPL_H__ +#define __ZTTHREADLOCALIMPL_H__ + +#include "zthread/CountedPtr.h" + +namespace ZThread { + + /** + * @class ThreadLocalImpl + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-27T10:23:19-0400> + * @version 2.3.0 + * + * @see ThreadLocal + */ + class ZTHREAD_API ThreadLocalImpl : private NonCopyable { + public: + + class Value; + typedef CountedPtr<Value, size_t> ValuePtr; + + //! + class Value { + Value& operator=(const Value&); + public: + virtual ~Value() {} + virtual bool isInheritable() const = 0; + virtual ValuePtr clone() const = 0; + }; + + //! Create a ThreadLocalImpl + ThreadLocalImpl(); + + //! Destroy a ThreadLocalImpl + ~ThreadLocalImpl(); + + /** + * @class InitialValueFn + */ + template <typename T> + struct InitialValueFn { + T operator()() { return T(); } + }; + + /** + * @class ChildValueFn + */ + struct ChildValueFn { + template <typename T> + T operator()(const T& value) { return T(value); } + }; + + /** + * @class UniqueChildValueFn + */ + struct UniqueChildValueFn : public ChildValueFn { }; + + /** + * @class InheritableValueFn + */ + struct InheritableValueFn { + + template <typename T> + bool operator()(const T&) { return true; } + + bool operator()(const UniqueChildValueFn&) { return false; } + + }; + + protected: + + //! Get the Value for the current thread + ValuePtr value( ValuePtr (*pfn)() ) const; + + //! Clear any value set for this thread + void clear() const; + + //! Clear any value set with any ThreadLocal for this thread + static void clearAll(); + + }; + +} // __ZTTHREADLOCALIMPL_H__ + +#endif + diff --git a/dep/include/zthread/ThreadedExecutor.h b/dep/include/zthread/ThreadedExecutor.h new file mode 100644 index 00000000000..9bc29b3c497 --- /dev/null +++ b/dep/include/zthread/ThreadedExecutor.h @@ -0,0 +1,136 @@ +/* + * 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 __ZTTHREADEDEXECUTOR_H__ +#define __ZTTHREADEDEXECUTOR_H__ + +#include "zthread/Executor.h" +#include "zthread/CountedPtr.h" + +namespace ZThread { + + namespace { class ExecutorImpl; } + + /** + * @class ThreadedExecutor + * + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T22:39:13-0400> + * @version 2.3.0 + * + * A ThreadedExecutor spawns a new thread to execute each task submitted. + * A ThreadedExecutor supports the following optional operations, + * + * - <em>cancel</em>()ing a ThreadedExecutor will cause it to stop accepting + * new tasks. + * + * - <em>interrupt</em>()ing a ThreadedExecutor will cause the any thread running + * a task which was submitted prior to the invocation of this function to + * be interrupted during the execution of that task. + * + * - <em>wait</em>()ing on a ThreadedExecutor will block the calling thread + * until all tasks that were submitted prior to the invocation of this function + * have completed. + * + * @see Executor. + */ + class ThreadedExecutor : public Executor { + + CountedPtr< ExecutorImpl > _impl; + + public: + + //! Create a new ThreadedExecutor + ThreadedExecutor(); + + //! Destroy a ThreadedExecutor + virtual ~ThreadedExecutor(); + + /** + * Interrupting a ThreadedExecutor will cause an interrupt() to be sent + * to every Task that has been submitted at the time this function is + * called. Tasks that are submitted after this function is called will + * not be interrupt()ed; unless this function is invoked again(). + */ + virtual void interrupt(); + + /** + * Submit a task to this Executor. This will not block the current thread + * for very long. A new thread will be created and the task will be run() + * within the context of that new thread. + * + * @exception Cancellation_Exception thrown if this Executor has been canceled. + * The Task being submitted will not be executed by this Executor. + * + * @see Executor::execute(const Task&) + */ + virtual void execute(const Task&); + + /** + * @see Cancelable::cancel() + */ + virtual void cancel(); + + /** + * @see Cancelable::isCanceled() + */ + virtual bool isCanceled(); + + /** + * Waiting on a ThreadedExecutor will block the current thread until all + * tasks submitted to the Executor up until the time this function was called + * have completed. + * + * Tasks submitted after this function is called will not delay a thread that + * was already waiting on the Executor any longer. In order to wait for + * those tasks to complete as well, another wait() would be needed. + * + * @exception Interrupted_Exception thrown if the calling thread is interrupted + * before the set of tasks for which it was waiting complete. + * + * @see Waitable::wait() + */ + virtual void wait(); + + /** + * Operates the same as ThreadedExecutor::wait() but with a timeout. + * + * @param timeout maximum amount of time, in milliseconds, to wait for the + * currently submitted set of Tasks to complete. + * + * @exception Interrupted_Exception thrown if the calling thread is interrupt()ed + * while waiting for the current set of Tasks to complete. + * + * @return + * - <em>true</em> if the set of tasks running at the time this function is invoked complete + * before <i>timeout</i> milliseconds elapse. + * - <em>false</em> othewise. + * + * @see Waitable::wait(unsigned long timeout) + */ + virtual bool wait(unsigned long timeout); + + }; /* ThreadedExecutor */ + +} // namespace ZThread + +#endif // __ZTTHREADEDEXECUTOR_H__ diff --git a/dep/include/zthread/Time.h b/dep/include/zthread/Time.h new file mode 100644 index 00000000000..374c4fd6bf0 --- /dev/null +++ b/dep/include/zthread/Time.h @@ -0,0 +1,225 @@ +/* + * 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 __ZTTIME_H__ +#define __ZTTIME_H__ + +#include "zthread/Config.h" + +namespace ZThread { + +/** + * @class Time + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T17:52:46-0400> + * @version 2.2.11 + * + * The Time class provides access to time values relative to when the program + * was started. In other words, this class might be thought of as a timer that + * starts at 0 and counts upwards. This class offers millisecond resolution. + */ +class ZTHREAD_API Time { + + unsigned long _seconds; + unsigned long _milliseconds; + + //! Create a new Time object + Time(unsigned long secs, unsigned long millis) + : _seconds(secs), _milliseconds(millis) { } + + /** + * Set the number of milliseconds in this Time object. + * + * @param millis - new milliseconds value + * @return unsigned long old milliseconds value + */ + unsigned long milliseconds(unsigned long millis) { + + unsigned long n = _milliseconds; + _milliseconds = millis; + + return n; + + } + + /** + * Set the number of seconds in this Time object. + * + * @param secs - new seconds value + * @return unsigned long old seconds value + */ + unsigned long seconds(unsigned long secs) { + + unsigned long n = _seconds; + _seconds = secs; + + return n; + + } + + public: + + + /** + * Create a Time object with the current time relative to the + * beginning of the program. + */ + Time(); + + /** + * Create a Time object by copying another. + * + * @param t - Time object to copy. + */ + Time(const Time& t) + : _seconds(t._seconds), _milliseconds(t._milliseconds) { } + + + /** + * Get the number of milliseconds in this Time object. + * + * @return unsigned long milliseconds value + */ + unsigned long milliseconds() const { + return _milliseconds; + } + + /** + * Get the number of seconds in this Time object. + * + * @return unsigned long seconds value + */ + unsigned long seconds() const { + return _seconds; + } + + /** + * Add some number of milliseconds to this Time object. + * + * @param millis - number of milliseconds to add to this Time object + * @return const Time& this object + */ + const Time& operator+=(unsigned long millis) { + + _milliseconds += millis; + _seconds += (_milliseconds / 1000); + _milliseconds %= 1000; + + return *this; + + } + + /** + * Subtract some number of milliseconds to this Time object. + * + * @param millis - number of milliseconds to subtract from this Time object + * @return const Time& this object + */ +const Time& operator-=(unsigned long millis) { + + if(_milliseconds > millis) + _milliseconds -= millis; + + else { + + while(_seconds > 0 && _milliseconds < millis) { + + _milliseconds += 1000; + _seconds -= 1; + + } + + _milliseconds = (_milliseconds < millis) ? 0 : (_milliseconds - millis); + + } + + return *this; + +} + + + /** + * Add the value of another Time object to this one. + * + * @param t - Time object whose value should be added to this object + * @return const Time& this object + */ + const Time& operator+=(const Time& t) { + + _milliseconds += t.milliseconds(); + _seconds += (_milliseconds / 1000) + t.seconds(); + _milliseconds %= 1000; + + return *this; + + } + + /** + * Subtract the value of another Time object from this one. + * This function has a floor of 0. + * + * @param t - Time object whose value should be subtracted from this object + * @return const Time& this object + */ +const Time& operator-=(const Time& t) { + + unsigned long millis = t.milliseconds(); + unsigned long secs = t.seconds(); + + if(_seconds >= secs) { + + if(_milliseconds > millis) { + _milliseconds -= millis; + _seconds -= secs; + + } else { + + while(_seconds > 0 && _milliseconds < millis) { + + _milliseconds += 1000; + _seconds -= 1; + + } + + _milliseconds = (_milliseconds < millis) ? 0 : (_milliseconds - millis); + _seconds = (_seconds < secs) ? 0 : (_seconds - secs); + + } + + } else { + + _milliseconds = 0; + _seconds = 0; + + } + + return *this; + +} + +}; + + + +} // namespace ZThread + +#endif // __ZTTIME_H__ diff --git a/dep/include/zthread/Waitable.h b/dep/include/zthread/Waitable.h new file mode 100644 index 00000000000..3d925f2a691 --- /dev/null +++ b/dep/include/zthread/Waitable.h @@ -0,0 +1,94 @@ +/* + * 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 __ZTWAITABLE_H__ +#define __ZTWAITABLE_H__ + +#include "zthread/Exceptions.h" + +namespace ZThread { + + /** + * @class Waitable + * + * @author Eric Crahen <http://www.code-foo.com> + * @date <2003-07-16T22:16:41-0400> + * @version 2.3.0 + * + * The Waitable interface defines a common method of adding generic <i>wait</i> semantics + * to a class. + * + * <b>Waiting</b> + * + * An object implementing the Waitable interface externalizes a mechanism for testing + * some internal condition. Another object may <i>wait()</i>s for a Waitable object; + * in doing so, it wait()s for that condition to become true by blocking the caller + * while the condition is false. + * + * For example, a Condition is Waitable object that extends <i>wait</i> semantics + * so that wait()ing means a thread is blocked until some external stimulus + * specifically performs an operation on the Condition to make its internal condition true. + * (serialization aside) + * + * A Barrier extends <i>wait</i> semantics so that wait()ing mean waiting for other + * waiters, and may include automatically resetting the condition once a wait is complete. + * + * @see Condition + * @see Barrier + * @see Executor + */ + class Waitable { + public: + + //! Destroy a Waitable object. + virtual ~Waitable() {} + + /** + * Waiting on an object will generally cause the calling thread to be blocked + * for some indefinite period of time. The thread executing will not proceed + * any further until the Waitable object releases it unless or an exception + * is thrown. + */ + virtual void wait() = 0; + + /** + * Waiting on an object will generally cause the calling thread to be blocked + * for some indefinite period of time. The thread executing will not proceed + * any further until the Waitable object releases it unless or an exception + * is thrown. + * + * @param timeout maximum amount of time, in milliseconds, to spend waiting. + * + * @return + * - <em>true</em> if the set of tasks being wait for complete before + * <i>timeout</i> milliseconds elapse. + * - <em>false</em> othewise. + */ + virtual bool wait(unsigned long timeout) = 0; + + + }; /* Waitable */ + + +} // namespace ZThread + +#endif // __ZTWAITABLE_H__ diff --git a/dep/include/zthread/ZThread.h b/dep/include/zthread/ZThread.h new file mode 100644 index 00000000000..1df5bb67a7c --- /dev/null +++ b/dep/include/zthread/ZThread.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 __ZTLIBRARY_H__ +#define __ZTLIBRARY_H__ + + +#include "zthread/Barrier.h" +#include "zthread/BiasedReadWriteLock.h" +#include "zthread/BlockingQueue.h" +#include "zthread/BoundedQueue.h" +#include "zthread/Cancelable.h" +#include "zthread/ClassLockable.h" +#include "zthread/ConcurrentExecutor.h" +#include "zthread/Condition.h" +#include "zthread/Config.h" +#include "zthread/CountedPtr.h" +#include "zthread/CountingSemaphore.h" +#include "zthread/Exceptions.h" +#include "zthread/Executor.h" +#include "zthread/FairReadWriteLock.h" +#include "zthread/FastMutex.h" +#include "zthread/FastRecursiveMutex.h" +#include "zthread/Guard.h" +#include "zthread/Lockable.h" +#include "zthread/LockedQueue.h" +#include "zthread/MonitoredQueue.h" +#include "zthread/Mutex.h" +#include "zthread/NonCopyable.h" +#include "zthread/PoolExecutor.h" +#include "zthread/Priority.h" +#include "zthread/PriorityCondition.h" +#include "zthread/PriorityInheritanceMutex.h" +#include "zthread/PriorityMutex.h" +#include "zthread/PrioritySemaphore.h" +#include "zthread/Queue.h" +#include "zthread/ReadWriteLock.h" +#include "zthread/RecursiveMutex.h" +#include "zthread/Runnable.h" +#include "zthread/Semaphore.h" +#include "zthread/Singleton.h" +#include "zthread/SynchronousExecutor.h" +#include "zthread/Thread.h" +#include "zthread/ThreadLocal.h" +#include "zthread/Time.h" +#include "zthread/Waitable.h" + +#endif |