Yet more tabs to spaces

--HG--
branch : trunk
This commit is contained in:
Paradox
2009-02-17 20:10:49 -06:00
parent 14234c86fa
commit 3931b802f1
38 changed files with 702 additions and 702 deletions
+7 -7
View File
@@ -24,7 +24,7 @@
namespace ZThread { namespace ZThread {
ConcurrentExecutor::ConcurrentExecutor() ConcurrentExecutor::ConcurrentExecutor()
: _executor(1) {} : _executor(1) {}
void ConcurrentExecutor::interrupt() { void ConcurrentExecutor::interrupt() {
@@ -34,21 +34,21 @@ namespace ZThread {
void ConcurrentExecutor::execute(const Task& task) { void ConcurrentExecutor::execute(const Task& task) {
_executor.execute(task); _executor.execute(task);
} }
void ConcurrentExecutor::cancel() { void ConcurrentExecutor::cancel() {
_executor.cancel(); _executor.cancel();
} }
bool ConcurrentExecutor::isCanceled() { bool ConcurrentExecutor::isCanceled() {
return _executor.isCanceled(); return _executor.isCanceled();
} }
void ConcurrentExecutor::wait() { void ConcurrentExecutor::wait() {
_executor.wait(); _executor.wait();
} }
bool ConcurrentExecutor::wait(unsigned long timeout) { bool ConcurrentExecutor::wait(unsigned long timeout) {
return _executor.wait(timeout); return _executor.wait(timeout);
} }
} }
+3 -3
View File
@@ -32,14 +32,14 @@ namespace ZThread {
}; };
Condition::Condition(Lockable& lock) { Condition::Condition(Lockable& lock) {
_impl = new FifoConditionImpl(lock); _impl = new FifoConditionImpl(lock);
} }
Condition::~Condition() { Condition::~Condition() {
if(_impl != 0) if(_impl != 0)
delete _impl; delete _impl;
@@ -64,7 +64,7 @@ namespace ZThread {
void Condition::signal() { void Condition::signal() {
_impl->signal(); _impl->signal();
} }
+2 -2
View File
@@ -29,9 +29,9 @@ namespace ZThread {
CountingSemaphore::CountingSemaphore(int initialCount) { CountingSemaphore::CountingSemaphore(int initialCount) {
_impl = new FifoSemaphoreImpl(initialCount, 0 , false); _impl = new FifoSemaphoreImpl(initialCount, 0 , false);
} }
+2 -2
View File
@@ -28,7 +28,7 @@ namespace ZThread {
FastMutex::FastMutex() : _lock(new FastLock) { } FastMutex::FastMutex() : _lock(new FastLock) { }
FastMutex::~FastMutex() { FastMutex::~FastMutex() {
delete _lock; delete _lock;
} }
@@ -39,7 +39,7 @@ namespace ZThread {
} }
bool FastMutex::tryAcquire(unsigned long timeout) { bool FastMutex::tryAcquire(unsigned long timeout) {
return _lock->tryAcquire(timeout); return _lock->tryAcquire(timeout);
} }
+3 -3
View File
@@ -25,10 +25,10 @@
namespace ZThread { namespace ZThread {
FastRecursiveMutex::FastRecursiveMutex() FastRecursiveMutex::FastRecursiveMutex()
: _lock(new FastRecursiveLock) { } : _lock(new FastRecursiveLock) { }
FastRecursiveMutex::~FastRecursiveMutex() FastRecursiveMutex::~FastRecursiveMutex()
{ delete _lock; } { delete _lock; }
@@ -39,7 +39,7 @@ namespace ZThread {
} }
bool FastRecursiveMutex::tryAcquire(unsigned long timeout) { bool FastRecursiveMutex::tryAcquire(unsigned long timeout) {
return _lock->tryAcquire(timeout); return _lock->tryAcquire(timeout);
} }
+2 -2
View File
@@ -26,10 +26,10 @@
#include "Monitor.h" #include "Monitor.h"
// This file will select an implementation for a Monitor based on // This file will select an implementation for a Monitor based on
// what Monitor.h selects. This method is for selecting the // what Monitor.h selects. This method is for selecting the
// source files, to improve portability. Currently, the project is // source files, to improve portability. Currently, the project is
// based on the autoconf tool-set, which doesn't support conditional // based on the autoconf tool-set, which doesn't support conditional
// compilation well. Additionally, this should make the library // compilation well. Additionally, this should make the library
// easier to port since its working around conditional compilation // easier to port since its working around conditional compilation
// by using C++ features and people won't have to fiddle around with // by using C++ features and people won't have to fiddle around with
// their make tool as much to compile the source // their make tool as much to compile the source
+1 -1
View File
@@ -64,5 +64,5 @@ namespace ZThread {
} // namespace ZThread } // namespace ZThread
+102 -102
View File
@@ -42,7 +42,7 @@ namespace ZThread {
class WaiterQueue { class WaiterQueue {
typedef std::deque<ThreadImpl*> ThreadList; typedef std::deque<ThreadImpl*> ThreadList;
typedef struct group_t { typedef struct group_t {
size_t id; size_t id;
size_t count; size_t count;
@@ -68,14 +68,14 @@ namespace ZThread {
void operator()(const Group& grp) { count += grp.count; } void operator()(const Group& grp) { count += grp.count; }
operator size_t() { return count; } operator size_t() { return count; }
}; };
FastMutex _lock; FastMutex _lock;
GroupList _list; GroupList _list;
size_t _id; size_t _id;
size_t _generation; size_t _generation;
public: public:
WaiterQueue() : _id(0), _generation(0) { WaiterQueue() : _id(0), _generation(0) {
// At least one empty-group exists // At least one empty-group exists
_list.push_back( Group(_id++) ); _list.push_back( Group(_id++) );
@@ -89,7 +89,7 @@ namespace ZThread {
*/ */
bool wait(unsigned long timeout) { bool wait(unsigned long timeout) {
ThreadImpl* current = ThreadImpl::current(); ThreadImpl* current = ThreadImpl::current();
Monitor& m = current->getMonitor(); Monitor& m = current->getMonitor();
Monitor::STATE state; Monitor::STATE state;
@@ -103,15 +103,15 @@ namespace ZThread {
if((size_t)std::for_each(_list.begin(), _list.end(), counter()) < 1) if((size_t)std::for_each(_list.begin(), _list.end(), counter()) < 1)
return true; return true;
// Update the waiter list for the active group // Update the waiter list for the active group
_list.back().waiters.push_back(current); _list.back().waiters.push_back(current);
size_t n = _list.back().id; size_t n = _list.back().id;
m.acquire(); m.acquire();
{ {
Guard<FastMutex, UnlockedScope> g2(g1); Guard<FastMutex, UnlockedScope> g2(g1);
state = timeout == 0 ? m.wait() : m.wait(timeout); state = timeout == 0 ? m.wait() : m.wait(timeout);
} }
@@ -142,22 +142,22 @@ namespace ZThread {
throw Interrupted_Exception(); throw Interrupted_Exception();
default: default:
throw Synchronization_Exception(); throw Synchronization_Exception();
} }
return true; return true;
} }
/** /**
* Increment the active group count * Increment the active group count
* *
* @pre at least 1 empty group exists * @pre at least 1 empty group exists
* @post at least 1 non-empty group exists * @post at least 1 non-empty group exists
*/ */
std::pair<size_t, size_t> increment() { std::pair<size_t, size_t> increment() {
Guard<FastMutex> g(_lock); Guard<FastMutex> g(_lock);
// At least one empty-group exists // At least one empty-group exists
assert(!_list.empty()); assert(!_list.empty());
@@ -176,7 +176,7 @@ namespace ZThread {
// When the active group is being incremented, insert a new active group // When the active group is being incremented, insert a new active group
// to replace it if there were waiting threads // to replace it if there were waiting threads
if(i == --_list.end() && !i->waiters.empty()) if(i == --_list.end() && !i->waiters.empty())
_list.push_back(Group(_id++)); _list.push_back(Group(_id++));
// At least 1 non-empty group exists // At least 1 non-empty group exists
@@ -185,27 +185,27 @@ namespace ZThread {
return std::make_pair(n, _generation); return std::make_pair(n, _generation);
} }
/** /**
* Decrease the count for the group with the given id. * Decrease the count for the group with the given id.
* *
* @param n group id * @param n group id
* *
* @pre At least 1 non-empty group exists * @pre At least 1 non-empty group exists
* @post At least 1 empty group exists * @post At least 1 empty group exists
*/ */
void decrement(size_t n) { void decrement(size_t n) {
Guard<FastMutex> g1(_lock); Guard<FastMutex> g1(_lock);
// At least 1 non-empty group exists // At least 1 non-empty group exists
assert((size_t)std::for_each(_list.begin(), _list.end(), counter()) > 0); assert((size_t)std::for_each(_list.begin(), _list.end(), counter()) > 0);
// Find the requested group // Find the requested group
GroupList::iterator i = std::find_if(_list.begin(), _list.end(), by_id(n)); GroupList::iterator i = std::find_if(_list.begin(), _list.end(), by_id(n));
if(i == _list.end()) { if(i == _list.end()) {
// A group should never have been removed until // A group should never have been removed until
// the final task in that group completed // the final task in that group completed
assert(0); assert(0);
@@ -214,11 +214,11 @@ namespace ZThread {
// Decrease the count for tasks in this group, // Decrease the count for tasks in this group,
if(--i->count == 0 && i == _list.begin()) { if(--i->count == 0 && i == _list.begin()) {
do { do {
// When the first group completes, wake all waiters for every // When the first group completes, wake all waiters for every
// group, starting from the first until a group that is not // group, starting from the first until a group that is not
// complete is reached // complete is reached
/* /*
@@ -226,29 +226,29 @@ namespace ZThread {
if(i == --_list.end() && i->waiters.empty()) if(i == --_list.end() && i->waiters.empty())
break; break;
*/ */
if( awaken(*i) ) { if( awaken(*i) ) {
// If all waiters were awakened, remove the group // If all waiters were awakened, remove the group
i = _list.erase(i); i = _list.erase(i);
} else { } else {
{ {
// Otherwise, unlock and yield allowing the waiter // Otherwise, unlock and yield allowing the waiter
// lists to be updated if other threads are busy // lists to be updated if other threads are busy
Guard<FastLock, UnlockedScope> g2(g1); Guard<FastLock, UnlockedScope> g2(g1);
ThreadImpl::yield(); ThreadImpl::yield();
} }
i = _list.begin(); i = _list.begin();
} }
} while(i != _list.end() && i->count == 0); } while(i != _list.end() && i->count == 0);
// Ensure that an active group exists // Ensure that an active group exists
if(_list.empty()) if(_list.empty())
_list.push_back( Group(++_id) ); _list.push_back( Group(++_id) );
@@ -257,7 +257,7 @@ namespace ZThread {
// At least one group exists // At least one group exists
assert(!_list.empty()); assert(!_list.empty());
} }
/** /**
@@ -268,40 +268,40 @@ namespace ZThread {
return next ? _generation++ : _generation; return next ? _generation++ : _generation;
} }
private: private:
/** /**
* Awaken all the waiters remaining in the given group * Awaken all the waiters remaining in the given group
* *
* @return * @return
* - true if all the waiting threads were successfully awakened. * - true if all the waiting threads were successfully awakened.
* - false if there were one or more threads that could not be awakened. * - false if there were one or more threads that could not be awakened.
*/ */
bool awaken(Group& grp) { bool awaken(Group& grp) {
// Go through the waiter list in the given group; // Go through the waiter list in the given group;
for(ThreadList::iterator i = grp.waiters.begin(); i != grp.waiters.end();) { for(ThreadList::iterator i = grp.waiters.begin(); i != grp.waiters.end();) {
ThreadImpl* impl = *i; ThreadImpl* impl = *i;
Monitor& m = impl->getMonitor(); Monitor& m = impl->getMonitor();
// Try the monitor lock, if it cant be locked skip to the next waiter // Try the monitor lock, if it cant be locked skip to the next waiter
if(m.tryAcquire()) { if(m.tryAcquire()) {
// Notify the monitor & remove from the waiter list so time isn't // Notify the monitor & remove from the waiter list so time isn't
// wasted checking it again. // wasted checking it again.
i = grp.waiters.erase(i); i = grp.waiters.erase(i);
// Try to wake the waiter, it doesn't matter if this is successful // Try to wake the waiter, it doesn't matter if this is successful
// or not (only fails when the monitor is already going to stop waiting). // or not (only fails when the monitor is already going to stop waiting).
m.notify(); m.notify();
m.release(); m.release();
} else ++i; } else ++i;
} }
return grp.waiters.empty(); return grp.waiters.empty();
} }
@@ -310,13 +310,13 @@ namespace ZThread {
/** /**
* @class GroupedRunnable * @class GroupedRunnable
* *
* Wrap a task with group and generation information. * Wrap a task with group and generation information.
* *
* - 'group' allows tasks to be grouped together so that lists of waiting * - 'group' allows tasks to be grouped together so that lists of waiting
* threads can be managed. * threads can be managed.
* *
* - 'generation' allows tasks to be interrupted * - 'generation' allows tasks to be interrupted
*/ */
class GroupedRunnable : public Runnable { class GroupedRunnable : public Runnable {
@@ -329,10 +329,10 @@ namespace ZThread {
public: public:
GroupedRunnable(const Task& task, WaiterQueue& queue) GroupedRunnable(const Task& task, WaiterQueue& queue)
: _task(task), _queue(queue) { : _task(task), _queue(queue) {
std::pair<size_t, size_t> pr( _queue.increment() ); std::pair<size_t, size_t> pr( _queue.increment() );
_group = pr.first; _group = pr.first;
_generation = pr.second; _generation = pr.second;
@@ -368,10 +368,10 @@ namespace ZThread {
* *
*/ */
class ExecutorImpl { class ExecutorImpl {
typedef MonitoredQueue<ExecutorTask, FastMutex> TaskQueue; typedef MonitoredQueue<ExecutorTask, FastMutex> TaskQueue;
typedef std::deque<ThreadImpl*> ThreadList; typedef std::deque<ThreadImpl*> ThreadList;
TaskQueue _taskQueue; TaskQueue _taskQueue;
WaiterQueue _waitingQueue; WaiterQueue _waitingQueue;
@@ -380,19 +380,19 @@ namespace ZThread {
public: public:
ExecutorImpl() : _size(0) {} ExecutorImpl() : _size(0) {}
void registerThread() { void registerThread() {
Guard<TaskQueue> g(_taskQueue); Guard<TaskQueue> g(_taskQueue);
ThreadImpl* impl = ThreadImpl::current(); ThreadImpl* impl = ThreadImpl::current();
_threads.push_back(impl); _threads.push_back(impl);
// current cancel if too many threads are being created // current cancel if too many threads are being created
if(_threads.size() > _size) if(_threads.size() > _size)
impl->cancel(); impl->cancel();
} }
@@ -408,14 +408,14 @@ namespace ZThread {
// Wrap the task with a grouped task // Wrap the task with a grouped task
GroupedRunnable* runnable = new GroupedRunnable(task, _waitingQueue); GroupedRunnable* runnable = new GroupedRunnable(task, _waitingQueue);
try { try {
_taskQueue.add( ExecutorTask(runnable) ); _taskQueue.add( ExecutorTask(runnable) );
} catch(...) { } catch(...) {
// Incase the queue is canceled between the time the WaiterQueue is // Incase the queue is canceled between the time the WaiterQueue is
// updated and the task is added to the TaskQueue // updated and the task is added to the TaskQueue
_waitingQueue.decrement( runnable->group() ); _waitingQueue.decrement( runnable->group() );
throw; throw;
@@ -430,41 +430,41 @@ namespace ZThread {
_waitingQueue.generation(true); _waitingQueue.generation(true);
Guard<TaskQueue> g(_taskQueue); Guard<TaskQueue> g(_taskQueue);
// Interrupt all threads currently running, thier tasks would be // Interrupt all threads currently running, thier tasks would be
// from an older generation // from an older generation
for(ThreadList::iterator i = _threads.begin(); i != _threads.end(); ++i) for(ThreadList::iterator i = _threads.begin(); i != _threads.end(); ++i)
(*i)->interrupt(); (*i)->interrupt();
} }
//! Adjust the number of desired workers and return the number of Threads needed //! Adjust the number of desired workers and return the number of Threads needed
size_t workers(size_t n) { size_t workers(size_t n) {
Guard<TaskQueue> g(_taskQueue); Guard<TaskQueue> g(_taskQueue);
size_t m = (_size < n) ? (n - _size) : 0; size_t m = (_size < n) ? (n - _size) : 0;
_size = n; _size = n;
return m; return m;
} }
size_t workers() { size_t workers() {
Guard<TaskQueue> g(_taskQueue); Guard<TaskQueue> g(_taskQueue);
return _size; return _size;
} }
ExecutorTask next() { ExecutorTask next() {
ExecutorTask task; ExecutorTask task;
// Draw the task from the queue // Draw the task from the queue
for(;;) { for(;;) {
try { try {
task = _taskQueue.next(); task = _taskQueue.next();
break; break;
@@ -473,13 +473,13 @@ namespace ZThread {
// Ignore interruption here, it can only come from // Ignore interruption here, it can only come from
// another thread interrupt()ing the executor. The // another thread interrupt()ing the executor. The
// thread was interrupted in the hopes it was busy // thread was interrupted in the hopes it was busy
// with a task // with a task
} }
} }
// Interrupt the thread running the tasks when the generation // Interrupt the thread running the tasks when the generation
// does not match the current generation // does not match the current generation
if( task->generation() != _waitingQueue.generation() ) if( task->generation() != _waitingQueue.generation() )
@@ -512,31 +512,31 @@ namespace ZThread {
class Worker : public Runnable { class Worker : public Runnable {
CountedPtr< ExecutorImpl > _impl; CountedPtr< ExecutorImpl > _impl;
public: public:
//! Create a Worker that draws upon the given Queue //! Create a Worker that draws upon the given Queue
Worker(const CountedPtr< ExecutorImpl >& impl) Worker(const CountedPtr< ExecutorImpl >& impl)
: _impl(impl) { } : _impl(impl) { }
//! Run until Thread or Queue are canceled //! Run until Thread or Queue are canceled
void run() { void run() {
_impl->registerThread(); _impl->registerThread();
// Run until the Queue is canceled // Run until the Queue is canceled
while(!Thread::canceled()) { while(!Thread::canceled()) {
// Draw tasks from the queue // Draw tasks from the queue
ExecutorTask task( _impl->next() ); ExecutorTask task( _impl->next() );
task->run(); task->run();
} }
_impl->unregisterThread(); _impl->unregisterThread();
} }
}; /* Worker */ }; /* Worker */
@@ -547,10 +547,10 @@ namespace ZThread {
public: public:
Shutdown(const CountedPtr< ExecutorImpl >& impl) Shutdown(const CountedPtr< ExecutorImpl >& impl)
: _impl(impl) { } : _impl(impl) { }
void run() { void run() {
_impl->cancel(); _impl->cancel();
} }
@@ -560,35 +560,35 @@ namespace ZThread {
PoolExecutor::PoolExecutor(size_t n) PoolExecutor::PoolExecutor(size_t n)
: _impl( new ExecutorImpl() ), _shutdown( new Shutdown(_impl) ) { : _impl( new ExecutorImpl() ), _shutdown( new Shutdown(_impl) ) {
size(n); size(n);
// Request cancelation when main() exits // Request cancelation when main() exits
ThreadQueue::instance()->insertShutdownTask(_shutdown); ThreadQueue::instance()->insertShutdownTask(_shutdown);
} }
PoolExecutor::~PoolExecutor() { PoolExecutor::~PoolExecutor() {
try { try {
/** /**
* If the shutdown task for this executor has not already been * If the shutdown task for this executor has not already been
* selected to run, then run it locally * selected to run, then run it locally
*/ */
if(ThreadQueue::instance()->removeShutdownTask(_shutdown)) if(ThreadQueue::instance()->removeShutdownTask(_shutdown))
_shutdown->run(); _shutdown->run();
} catch(...) { } } catch(...) { }
} }
void PoolExecutor::interrupt() { void PoolExecutor::interrupt() {
_impl->interrupt(); _impl->interrupt();
} }
void PoolExecutor::size(size_t n) { void PoolExecutor::size(size_t n) {
if(n < 1) if(n < 1)
throw InvalidOp_Exception(); throw InvalidOp_Exception();
@@ -604,26 +604,26 @@ namespace ZThread {
void PoolExecutor::execute(const Task& task) { void PoolExecutor::execute(const Task& task) {
// Enqueue the task, the Queue will reject it with a // Enqueue the task, the Queue will reject it with a
// Cancelation_Exception if the Executor has been canceled // Cancelation_Exception if the Executor has been canceled
_impl->execute(task); _impl->execute(task);
} }
void PoolExecutor::cancel() { void PoolExecutor::cancel() {
_impl->cancel(); _impl->cancel();
} }
bool PoolExecutor::isCanceled() { bool PoolExecutor::isCanceled() {
return _impl->isCanceled(); return _impl->isCanceled();
} }
void PoolExecutor::wait() { void PoolExecutor::wait() {
_impl->wait(0); _impl->wait(0);
} }
bool PoolExecutor::wait(unsigned long timeout) { bool PoolExecutor::wait(unsigned long timeout) {
return _impl->wait(timeout == 0 ? 1 : timeout); return _impl->wait(timeout == 0 ? 1 : timeout);
} }
} }
+2 -2
View File
@@ -32,14 +32,14 @@ namespace ZThread {
}; };
PriorityCondition::PriorityCondition(Lockable& lock) { PriorityCondition::PriorityCondition(Lockable& lock) {
_impl = new PriorityConditionImpl(lock); _impl = new PriorityConditionImpl(lock);
} }
PriorityCondition::~PriorityCondition() { PriorityCondition::~PriorityCondition() {
if(_impl != 0) if(_impl != 0)
delete _impl; delete _impl;
+14 -14
View File
@@ -28,28 +28,28 @@
namespace ZThread { namespace ZThread {
class InheritPriorityBehavior : public NullBehavior { class InheritPriorityBehavior : public NullBehavior {
ThreadImpl* owner; ThreadImpl* owner;
Priority p; Priority p;
protected: protected:
// Temporarily raise the effective priority of the owner // Temporarily raise the effective priority of the owner
inline void waiterArrived(ThreadImpl* impl) { inline void waiterArrived(ThreadImpl* impl) {
Priority q = impl->getPriority(); Priority q = impl->getPriority();
if((int)q > (int)p) { if((int)q > (int)p) {
ThreadOps::setPriority(impl, p); ThreadOps::setPriority(impl, p);
p = q; p = q;
} }
} }
// Note the owners priority // Note the owners priority
inline void ownerAcquired(ThreadImpl* impl) { inline void ownerAcquired(ThreadImpl* impl) {
p = impl->getPriority(); p = impl->getPriority();
owner = impl; owner = impl;
@@ -57,7 +57,7 @@ namespace ZThread {
} }
// Restore its original priority // Restore its original priority
inline void ownerReleased(ThreadImpl* impl) { inline void ownerReleased(ThreadImpl* impl) {
if(p > owner->getPriority()) if(p > owner->getPriority())
ThreadOps::setPriority(impl, impl->getPriority()); ThreadOps::setPriority(impl, impl->getPriority());
@@ -66,18 +66,18 @@ namespace ZThread {
}; };
class PriorityInheritanceMutexImpl : class PriorityInheritanceMutexImpl :
public MutexImpl<priority_list, InheritPriorityBehavior> { }; public MutexImpl<priority_list, InheritPriorityBehavior> { };
PriorityInheritanceMutex::PriorityInheritanceMutex() { PriorityInheritanceMutex::PriorityInheritanceMutex() {
_impl = new PriorityInheritanceMutexImpl(); _impl = new PriorityInheritanceMutexImpl();
} }
PriorityInheritanceMutex::~PriorityInheritanceMutex() { PriorityInheritanceMutex::~PriorityInheritanceMutex() {
if(_impl != 0) if(_impl != 0)
delete _impl; delete _impl;
} }
@@ -85,7 +85,7 @@ namespace ZThread {
// P // P
void PriorityInheritanceMutex::acquire() { void PriorityInheritanceMutex::acquire() {
_impl->acquire(); _impl->acquire();
} }
@@ -93,14 +93,14 @@ namespace ZThread {
// P // P
bool PriorityInheritanceMutex::tryAcquire(unsigned long ms) { bool PriorityInheritanceMutex::tryAcquire(unsigned long ms) {
return _impl->tryAcquire(ms); return _impl->tryAcquire(ms);
} }
// V // V
void PriorityInheritanceMutex::release() { void PriorityInheritanceMutex::release() {
_impl->release(); _impl->release();
} }
+7 -7
View File
@@ -29,15 +29,15 @@ namespace ZThread {
class PriorityMutexImpl : public MutexImpl<priority_list, NullBehavior> { }; class PriorityMutexImpl : public MutexImpl<priority_list, NullBehavior> { };
PriorityMutex::PriorityMutex() { PriorityMutex::PriorityMutex() {
_impl = new PriorityMutexImpl(); _impl = new PriorityMutexImpl();
} }
PriorityMutex::~PriorityMutex() { PriorityMutex::~PriorityMutex() {
if(_impl != 0) if(_impl != 0)
delete _impl; delete _impl;
} }
@@ -45,7 +45,7 @@ namespace ZThread {
// P // P
void PriorityMutex::acquire() { void PriorityMutex::acquire() {
_impl->acquire(); _impl->acquire();
} }
@@ -53,14 +53,14 @@ namespace ZThread {
// P // P
bool PriorityMutex::tryAcquire(unsigned long ms) { bool PriorityMutex::tryAcquire(unsigned long ms) {
return _impl->tryAcquire(ms); return _impl->tryAcquire(ms);
} }
// V // V
void PriorityMutex::release() { void PriorityMutex::release() {
_impl->release(); _impl->release();
} }
+4 -4
View File
@@ -26,10 +26,10 @@
namespace ZThread { namespace ZThread {
class PrioritySemaphoreImpl : public SemaphoreImpl<priority_list> { class PrioritySemaphoreImpl : public SemaphoreImpl<priority_list> {
public: public:
PrioritySemaphoreImpl(int count, unsigned int maxCount) PrioritySemaphoreImpl(int count, unsigned int maxCount)
: SemaphoreImpl<priority_list>(count, maxCount, true) { } : SemaphoreImpl<priority_list>(count, maxCount, true) { }
}; };
@@ -41,9 +41,9 @@ namespace ZThread {
* @param maxCount maximum size of the semaphore count * @param maxCount maximum size of the semaphore count
*/ */
PrioritySemaphore::PrioritySemaphore(int count, unsigned int maxCount) { PrioritySemaphore::PrioritySemaphore(int count, unsigned int maxCount) {
_impl = new PrioritySemaphoreImpl(count, maxCount); _impl = new PrioritySemaphoreImpl(count, maxCount);
} }
PrioritySemaphore::~PrioritySemaphore() { PrioritySemaphore::~PrioritySemaphore() {
+6 -6
View File
@@ -26,14 +26,14 @@
namespace ZThread { namespace ZThread {
RecursiveMutex::RecursiveMutex() { RecursiveMutex::RecursiveMutex() {
_impl = new RecursiveMutexImpl(); _impl = new RecursiveMutexImpl();
} }
RecursiveMutex::~RecursiveMutex() { RecursiveMutex::~RecursiveMutex() {
if(_impl != (RecursiveMutexImpl*)0 ) if(_impl != (RecursiveMutexImpl*)0 )
delete _impl; delete _impl;
} }
@@ -41,20 +41,20 @@ namespace ZThread {
void RecursiveMutex::acquire() { void RecursiveMutex::acquire() {
_impl->acquire(); _impl->acquire();
} }
bool RecursiveMutex::tryAcquire(unsigned long ms) { bool RecursiveMutex::tryAcquire(unsigned long ms) {
return _impl->tryAcquire(ms); return _impl->tryAcquire(ms);
} }
void RecursiveMutex::release() { void RecursiveMutex::release() {
_impl->release(); _impl->release();
} }
+38 -38
View File
@@ -39,9 +39,9 @@ namespace ZThread {
* @exception Initialization_Exception thrown if resources could not be * @exception Initialization_Exception thrown if resources could not be
* properly allocated * properly allocated
*/ */
RecursiveMutexImpl::RecursiveMutexImpl() RecursiveMutexImpl::RecursiveMutexImpl()
: _owner(0), _count(0) { : _owner(0), _count(0) {
} }
/** /**
@@ -52,14 +52,14 @@ namespace ZThread {
#ifndef NDEBUG #ifndef NDEBUG
// It is an error to destroy a mutex that has not been released // It is an error to destroy a mutex that has not been released
if(_owner != 0) { if(_owner != 0) {
ZTDEBUG("** You are destroying a mutex which was never released. **\n"); ZTDEBUG("** You are destroying a mutex which was never released. **\n");
assert(0); // Destroyed mutex while in use assert(0); // Destroyed mutex while in use
} }
if(!_waiters.empty()) { if(!_waiters.empty()) {
ZTDEBUG("** You are destroying a mutex which is blocking %d threads. **\n", _waiters.size()); ZTDEBUG("** You are destroying a mutex which is blocking %d threads. **\n", _waiters.size());
assert(0); // Destroyed mutex while in use assert(0); // Destroyed mutex while in use
@@ -78,10 +78,10 @@ namespace ZThread {
Monitor::STATE state; Monitor::STATE state;
Guard<FastLock> g1(_lock); Guard<FastLock> g1(_lock);
// If there is an entry count and the current thread is // If there is an entry count and the current thread is
// the owner, increment the count and continue. // the owner, increment the count and continue.
if(_owner == &m) if(_owner == &m)
_count++; _count++;
else { else {
@@ -91,11 +91,11 @@ namespace ZThread {
assert(_count == 0); assert(_count == 0);
_owner = &m; _owner = &m;
_count++; _count++;
} else { // Otherwise, wait() } else { // Otherwise, wait()
_waiters.push_back(&m); _waiters.push_back(&m);
m.acquire(); m.acquire();
@@ -108,7 +108,7 @@ namespace ZThread {
} }
m.release(); m.release();
// Remove from waiter list, regarless of weather release() is called or // Remove from waiter list, regarless of weather release() is called or
// not. The monitor is sticky, so its possible a state 'stuck' from a // not. The monitor is sticky, so its possible a state 'stuck' from a
// previous operation and will leave the wait() w/o release() having // previous operation and will leave the wait() w/o release() having
@@ -117,39 +117,39 @@ namespace ZThread {
if(i != _waiters.end()) if(i != _waiters.end())
_waiters.erase(i); _waiters.erase(i);
// If awoke due to a notify(), take ownership. // If awoke due to a notify(), take ownership.
switch(state) { switch(state) {
case Monitor::SIGNALED: case Monitor::SIGNALED:
assert(_owner == 0); assert(_owner == 0);
assert(_count == 0); assert(_count == 0);
_owner = &m; _owner = &m;
_count++; _count++;
break; break;
case Monitor::INTERRUPTED: case Monitor::INTERRUPTED:
throw Interrupted_Exception(); throw Interrupted_Exception();
default: default:
throw Synchronization_Exception(); throw Synchronization_Exception();
} }
} }
} }
} }
bool RecursiveMutexImpl::tryAcquire(unsigned long timeout) { bool RecursiveMutexImpl::tryAcquire(unsigned long timeout) {
// Get the monitor for the current thread // Get the monitor for the current thread
Monitor& m = ThreadImpl::current()->getMonitor(); Monitor& m = ThreadImpl::current()->getMonitor();
Guard<FastLock> g1(_lock); Guard<FastLock> g1(_lock);
// If there is an entry count and the current thread is // If there is an entry count and the current thread is
// the owner, increment the count and continue. // the owner, increment the count and continue.
if(_owner == &m) if(_owner == &m)
_count++; _count++;
@@ -176,14 +176,14 @@ namespace ZThread {
m.acquire(); m.acquire();
{ {
Guard<FastLock, UnlockedScope> g2(g1); Guard<FastLock, UnlockedScope> g2(g1);
state = m.wait(timeout); state = m.wait(timeout);
} }
m.release(); m.release();
} }
// Remove from waiter list, regarless of weather release() is called or // Remove from waiter list, regarless of weather release() is called or
@@ -194,7 +194,7 @@ namespace ZThread {
if(i != _waiters.end()) if(i != _waiters.end())
_waiters.erase(i); _waiters.erase(i);
// If awoke due to a notify(), take ownership. // If awoke due to a notify(), take ownership.
switch(state) { switch(state) {
case Monitor::SIGNALED: case Monitor::SIGNALED:
@@ -203,21 +203,21 @@ namespace ZThread {
_owner = &m; _owner = &m;
_count++; _count++;
break; break;
case Monitor::INTERRUPTED: case Monitor::INTERRUPTED:
throw Interrupted_Exception(); throw Interrupted_Exception();
case Monitor::TIMEDOUT: case Monitor::TIMEDOUT:
return false; return false;
default: default:
throw Synchronization_Exception(); throw Synchronization_Exception();
} }
} }
} }
return true; return true;
@@ -237,7 +237,7 @@ namespace ZThread {
// Update the count, if it has reached 0, wake another waiter. // Update the count, if it has reached 0, wake another waiter.
if(--_count == 0) { if(--_count == 0) {
_owner = 0; _owner = 0;
// Try to find a waiter with a backoff & retry scheme // Try to find a waiter with a backoff & retry scheme
@@ -245,24 +245,24 @@ namespace ZThread {
// Go through the list, attempt to notify() a waiter. // Go through the list, attempt to notify() a waiter.
for(List::iterator i = _waiters.begin(); i != _waiters.end();) { for(List::iterator i = _waiters.begin(); i != _waiters.end();) {
// Try the monitor lock, if it cant be locked skip to the next waiter // Try the monitor lock, if it cant be locked skip to the next waiter
Monitor* n = *i; Monitor* n = *i;
if(n->tryAcquire()) { if(n->tryAcquire()) {
// If notify() is not sucessful, it is because the wait() has already // If notify() is not sucessful, it is because the wait() has already
// been ended (killed/interrupted/notify'd) // been ended (killed/interrupted/notify'd)
bool woke = n->notify(); bool woke = n->notify();
n->release(); n->release();
// Once notify() succeeds, return // Once notify() succeeds, return
if(woke) if(woke)
return; return;
} else ++i; } else ++i;
} }
if(_waiters.empty()) if(_waiters.empty())
return; return;
@@ -276,7 +276,7 @@ namespace ZThread {
} }
} }
} }
} // namespace ZThread } // namespace ZThread
+2 -2
View File
@@ -32,9 +32,9 @@ namespace ZThread {
* @param maxCount maximum size of the semaphore count * @param maxCount maximum size of the semaphore count
*/ */
Semaphore::Semaphore(int count, unsigned int maxCount) { Semaphore::Semaphore(int count, unsigned int maxCount) {
_impl = new FifoSemaphoreImpl(count, maxCount, true); _impl = new FifoSemaphoreImpl(count, maxCount, true);
} }
Semaphore::~Semaphore() { Semaphore::~Semaphore() {
+20 -20
View File
@@ -24,12 +24,12 @@
namespace ZThread { namespace ZThread {
SynchronousExecutor::SynchronousExecutor() SynchronousExecutor::SynchronousExecutor()
: _canceled(false) {} : _canceled(false) {}
SynchronousExecutor::~SynchronousExecutor() { SynchronousExecutor::~SynchronousExecutor() {
} }
void SynchronousExecutor::cancel() { void SynchronousExecutor::cancel() {
Guard<Mutex> g(_lock); Guard<Mutex> g(_lock);
@@ -38,41 +38,41 @@ namespace ZThread {
} }
bool SynchronousExecutor::isCanceled() { bool SynchronousExecutor::isCanceled() {
Guard<Mutex> g(_lock); Guard<Mutex> g(_lock);
return _canceled; return _canceled;
} }
void SynchronousExecutor::interrupt() { void SynchronousExecutor::interrupt() {
} }
void SynchronousExecutor::execute(const Task& task) { void SynchronousExecutor::execute(const Task& task) {
// Canceled Executors will not accept new tasks, quick // Canceled Executors will not accept new tasks, quick
// check to avoid excessive locking in the canceled state // check to avoid excessive locking in the canceled state
if(_canceled) if(_canceled)
throw Cancellation_Exception(); throw Cancellation_Exception();
Guard<Mutex> g(_lock); Guard<Mutex> g(_lock);
if(_canceled) // Double check if(_canceled) // Double check
throw Cancellation_Exception(); throw Cancellation_Exception();
// Run the task. // Run the task.
Task(task)->run(); Task(task)->run();
} }
void SynchronousExecutor::wait() { void SynchronousExecutor::wait() {
if(Thread::interrupted()) if(Thread::interrupted())
throw Interrupted_Exception(); throw Interrupted_Exception();
Guard<Mutex> g(_lock); Guard<Mutex> g(_lock);
} }
/** /**
* @see Executor::wait(unsigned long) * @see Executor::wait(unsigned long)
*/ */
@@ -80,11 +80,11 @@ namespace ZThread {
if(Thread::interrupted()) if(Thread::interrupted())
throw Interrupted_Exception(); throw Interrupted_Exception();
Guard<Mutex> g(_lock); Guard<Mutex> g(_lock);
return true; return true;
} }
} }
+10 -10
View File
@@ -27,20 +27,20 @@
namespace ZThread { namespace ZThread {
Thread::Thread() Thread::Thread()
: _impl( ThreadImpl::current() ) { : _impl( ThreadImpl::current() ) {
// ThreadImpl's start out life with a reference count // ThreadImpl's start out life with a reference count
// of one, and the they are added to the ThreadQueue. // of one, and the they are added to the ThreadQueue.
_impl->addReference(); _impl->addReference();
} }
Thread::Thread(const Task& task, bool autoCancel) Thread::Thread(const Task& task, bool autoCancel)
: _impl( new ThreadImpl(task, autoCancel) ) { : _impl( new ThreadImpl(task, autoCancel) ) {
_impl->addReference(); _impl->addReference();
} }
bool Thread::operator==(const Thread& t) const { bool Thread::operator==(const Thread& t) const {
@@ -94,7 +94,7 @@ namespace ZThread {
return _impl->interrupt(); return _impl->interrupt();
} }
void Thread::cancel() { void Thread::cancel() {
if(ThreadImpl::current() == _impl) if(ThreadImpl::current() == _impl)
@@ -102,7 +102,7 @@ namespace ZThread {
_impl->cancel(); _impl->cancel();
} }
bool Thread::isCanceled() { bool Thread::isCanceled() {
@@ -124,4 +124,4 @@ namespace ZThread {
} }
} // namespace ZThread } // namespace ZThread
+141 -141
View File
@@ -34,88 +34,88 @@ namespace ZThread {
TSS<ThreadImpl*> ThreadImpl::_threadMap; TSS<ThreadImpl*> ThreadImpl::_threadMap;
namespace { namespace {
class Launcher : public Runnable { class Launcher : public Runnable {
ThreadImpl* x; ThreadImpl* x;
ThreadImpl* y; ThreadImpl* y;
Task z; Task z;
public: public:
Launcher(ThreadImpl* a, ThreadImpl* b, const Task& c) : x(a), y(b), z(c) {} Launcher(ThreadImpl* a, ThreadImpl* b, const Task& c) : x(a), y(b), z(c) {}
void run() { void run() {
y->dispatch(x,y,z); y->dispatch(x,y,z);
} }
}; };
} }
ThreadImpl::ThreadImpl() ThreadImpl::ThreadImpl()
: _state(State::REFERENCE), _priority(Medium), _autoCancel(false) { : _state(State::REFERENCE), _priority(Medium), _autoCancel(false) {
ZTDEBUG("Reference thread created.\n"); ZTDEBUG("Reference thread created.\n");
} }
ThreadImpl::ThreadImpl(const Task& task, bool autoCancel) ThreadImpl::ThreadImpl(const Task& task, bool autoCancel)
: _state(State::IDLE), _priority(Medium), _autoCancel(autoCancel) { : _state(State::IDLE), _priority(Medium), _autoCancel(autoCancel) {
ZTDEBUG("User thread created.\n"); ZTDEBUG("User thread created.\n");
start(task); start(task);
} }
ThreadImpl::~ThreadImpl() { ThreadImpl::~ThreadImpl() {
_tls.clear(); _tls.clear();
if(isActive()) { if(isActive()) {
ZTDEBUG("You are destroying an executing thread!\n"); ZTDEBUG("You are destroying an executing thread!\n");
abort(); abort();
} }
ZTDEBUG("Thread destroyed.\n"); ZTDEBUG("Thread destroyed.\n");
} }
Monitor& ThreadImpl::getMonitor() { Monitor& ThreadImpl::getMonitor() {
return _monitor; return _monitor;
} }
void ThreadImpl::cancel(bool autoCancel) { void ThreadImpl::cancel(bool autoCancel) {
if(!autoCancel || _autoCancel) if(!autoCancel || _autoCancel)
_monitor.cancel(); _monitor.cancel();
} }
bool ThreadImpl::interrupt() { bool ThreadImpl::interrupt() {
return _monitor.interrupt(); return _monitor.interrupt();
} }
bool ThreadImpl::isInterrupted() { bool ThreadImpl::isInterrupted() {
return _monitor.isInterrupted(); return _monitor.isInterrupted();
} }
bool ThreadImpl::isCanceled() { bool ThreadImpl::isCanceled() {
return _monitor.isCanceled(); return _monitor.isCanceled();
} }
Priority ThreadImpl::getPriority() const { Priority ThreadImpl::getPriority() const {
return _priority; return _priority;
} }
bool ThreadImpl::isReference() { bool ThreadImpl::isReference() {
return _state.isReference(); return _state.isReference();
} }
/** /**
* Join the thread, blocking the caller until it is interrupted or until * Join the thread, blocking the caller until it is interrupted or until
* the thread represented by this object exits. * the thread represented by this object exits.
@@ -124,27 +124,27 @@ namespace ZThread {
* joined. * joined.
*/ */
bool ThreadImpl::join(unsigned long timeout) { bool ThreadImpl::join(unsigned long timeout) {
// Serial access to this ThreadImpl's state // Serial access to this ThreadImpl's state
Guard<Monitor> g1(_monitor); Guard<Monitor> g1(_monitor);
// Make sure a thread is not trying to join() itself. // Make sure a thread is not trying to join() itself.
if(ThreadOps::isCurrent(this)) if(ThreadOps::isCurrent(this))
throw Deadlock_Exception("Cannot join self."); throw Deadlock_Exception("Cannot join self.");
// Reference threads can't be joined. // Reference threads can't be joined.
if(_state.isReference()) if(_state.isReference())
throw InvalidOp_Exception("Can not join this thread."); throw InvalidOp_Exception("Can not join this thread.");
/* /*
TODO: Insert cyclic join check. TODO: Insert cyclic join check.
*/ */
// If the task has not completed yet, wait for completion // If the task has not completed yet, wait for completion
if(!_state.isJoined()) { if(!_state.isJoined()) {
// Add the current thread to the joiner list // Add the current thread to the joiner list
ThreadImpl* impl = current(); ThreadImpl* impl = current();
_joiners.push_back(impl); _joiners.push_back(impl);
@@ -153,49 +153,49 @@ namespace ZThread {
{ // Release this ThreadImpl's lock while the joiner sleeps { // Release this ThreadImpl's lock while the joiner sleeps
_monitor.release(); _monitor.release();
Guard<Monitor> g3(impl->getMonitor()); Guard<Monitor> g3(impl->getMonitor());
result = impl->_monitor.wait(timeout); result = impl->_monitor.wait(timeout);
_monitor.acquire(); _monitor.acquire();
} }
// Update the joiner list // Update the joiner list
List::iterator i = std::find(_joiners.begin(), _joiners.end(), impl); List::iterator i = std::find(_joiners.begin(), _joiners.end(), impl);
if(i != _joiners.end()) if(i != _joiners.end())
_joiners.erase(i); _joiners.erase(i);
switch(result) { switch(result) {
case Monitor::TIMEDOUT: case Monitor::TIMEDOUT:
return false; return false;
case Monitor::INTERRUPTED: case Monitor::INTERRUPTED:
throw Interrupted_Exception(); throw Interrupted_Exception();
default: default:
break; break;
} }
} }
return true; return true;
} }
/** /**
* Translate the priority into a pthread value, and update the thread priority. * Translate the priority into a pthread value, and update the thread priority.
* *
* This is not available on all platforms, and probably works differently * This is not available on all platforms, and probably works differently
* the platforms that do support it. Pthreads does not have very portable * the platforms that do support it. Pthreads does not have very portable
* priority support as far I am aware. * priority support as far I am aware.
* *
* If SCHED_OTHER is not supported priority values are still set but * If SCHED_OTHER is not supported priority values are still set but
* dont not actually in affect anything. * dont not actually in affect anything.
* *
* @param prio PRIORITY value * @param prio PRIORITY value
@@ -204,18 +204,18 @@ namespace ZThread {
* @exception InvalidOp_Exception thrown by IDLE, JOINING or JOINED threads. * @exception InvalidOp_Exception thrown by IDLE, JOINING or JOINED threads.
*/ */
void ThreadImpl::setPriority(Priority p) { void ThreadImpl::setPriority(Priority p) {
Guard<Monitor> g(_monitor); Guard<Monitor> g(_monitor);
// Only set the native priority when the thread is running // Only set the native priority when the thread is running
if(_state.isRunning()) if(_state.isRunning())
ThreadOps::setPriority(this, p); ThreadOps::setPriority(this, p);
_priority = p; _priority = p;
} }
/** /**
* Test the state Monitor of this thread to determine if the thread * Test the state Monitor of this thread to determine if the thread
* is an active thread created by zthreads. * is an active thread created by zthreads.
@@ -223,13 +223,13 @@ namespace ZThread {
* @return bool indicating the activity of the thread. * @return bool indicating the activity of the thread.
*/ */
bool ThreadImpl::isActive() { bool ThreadImpl::isActive() {
Guard<Monitor> g(_monitor); Guard<Monitor> g(_monitor);
return _state.isRunning(); return _state.isRunning();
} }
/** /**
* Get a reference to an implmenetation that maps to the current thread. * Get a reference to an implmenetation that maps to the current thread.
* Accomplished by checking the TLS map. This will always return a valid * Accomplished by checking the TLS map. This will always return a valid
@@ -237,98 +237,98 @@ namespace ZThread {
* *
* @return ThreadImpl* current implementation that maps to the * @return ThreadImpl* current implementation that maps to the
* executing thread. * executing thread.
*/ */
ThreadImpl* ThreadImpl::current() { ThreadImpl* ThreadImpl::current() {
// Get the ThreadImpl previously mapped onto the executing thread. // Get the ThreadImpl previously mapped onto the executing thread.
ThreadImpl* impl = _threadMap.get(); ThreadImpl* impl = _threadMap.get();
// Create a reference thread for any threads that have been 'discovered' // Create a reference thread for any threads that have been 'discovered'
// because they are not created by ZThreads. // because they are not created by ZThreads.
if(impl == 0) { if(impl == 0) {
// Create a ThreadImpl to represent this thread. // Create a ThreadImpl to represent this thread.
impl = new ThreadImpl(); impl = new ThreadImpl();
impl->_state.setReference(); impl->_state.setReference();
ThreadOps::activate(impl); ThreadOps::activate(impl);
// Map a reference thread and insert it into the queue // Map a reference thread and insert it into the queue
_threadMap.set(impl); _threadMap.set(impl);
ThreadQueue::instance()->insertReferenceThread(impl); ThreadQueue::instance()->insertReferenceThread(impl);
} }
assert(impl != 0); assert(impl != 0);
return impl; return impl;
} }
/** /**
* Make current thread sleep for the given number of milliseconds. * Make current thread sleep for the given number of milliseconds.
* This sleep can be interrupt()ed. * This sleep can be interrupt()ed.
* *
* @param ms timeout for the sleep. * @param ms timeout for the sleep.
* *
* @post the calling thread is blocked by waiting on the internal condition * @post the calling thread is blocked by waiting on the internal condition
* variable. This can be signaled in the monitor of an interrupt * variable. This can be signaled in the monitor of an interrupt
*/ */
void ThreadImpl::sleep(unsigned long ms) { void ThreadImpl::sleep(unsigned long ms) {
// Make sleep()ing for 0 milliseconds equivalent to a yield. // Make sleep()ing for 0 milliseconds equivalent to a yield.
if(ms == 0) { if(ms == 0) {
yield(); yield();
return; return;
} }
// Get the monitor for the current thread // Get the monitor for the current thread
Monitor& monitor = current()->getMonitor(); Monitor& monitor = current()->getMonitor();
// Acquire that threads Monitor with a Guard // Acquire that threads Monitor with a Guard
Guard<Monitor> g(monitor); Guard<Monitor> g(monitor);
for(;;) { for(;;) {
switch(monitor.wait(ms)) { switch(monitor.wait(ms)) {
case Monitor::INTERRUPTED: case Monitor::INTERRUPTED:
throw Interrupted_Exception(); throw Interrupted_Exception();
default: default:
return; return;
} }
} }
} }
/** /**
* Yield the current timeslice to another thread. * Yield the current timeslice to another thread.
* If sched_yield() is available it is used. * If sched_yield() is available it is used.
* Otherwise, the state Monitor for this thread is used to simiulate a * Otherwise, the state Monitor for this thread is used to simiulate a
* yield by blocking for 1 millisecond, which should give the * yield by blocking for 1 millisecond, which should give the
* scheduler a chance to schedule another thread. * scheduler a chance to schedule another thread.
*/ */
void ThreadImpl::yield() { void ThreadImpl::yield() {
// Try to yield with the native operation. If it fails, then // Try to yield with the native operation. If it fails, then
// simulate with a short wait() on the monitor. // simulate with a short wait() on the monitor.
if(!ThreadOps::yield()) { if(!ThreadOps::yield()) {
// Get the monitor for the current thread // Get the monitor for the current thread
Monitor& monitor = current()->getMonitor(); Monitor& monitor = current()->getMonitor();
// Attempt a wait(). // Attempt a wait().
Guard<Monitor> g(monitor); Guard<Monitor> g(monitor);
monitor.wait(1); monitor.wait(1);
} }
} }
void ThreadImpl::start(const Task& task) { void ThreadImpl::start(const Task& task) {
@@ -338,9 +338,9 @@ namespace ZThread {
// A Thread must be idle in order to be eligable to run a task. // A Thread must be idle in order to be eligable to run a task.
if(!_state.isIdle()) if(!_state.isIdle())
throw InvalidOp_Exception("Thread is not idle."); throw InvalidOp_Exception("Thread is not idle.");
_state.setRunning(); _state.setRunning();
// Spawn a new thread, blocking the parent (current) thread until // Spawn a new thread, blocking the parent (current) thread until
// the child starts. // the child starts.
@@ -353,14 +353,14 @@ namespace ZThread {
if(!spawn(&launch)) { if(!spawn(&launch)) {
// Return to the idle state & report the error if it doesn't work out. // Return to the idle state & report the error if it doesn't work out.
_state.setIdle(); _state.setIdle();
throw Synchronization_Exception(); throw Synchronization_Exception();
} }
// Wait, uninterruptably, for the child's signal. The parent thread // Wait, uninterruptably, for the child's signal. The parent thread
// still can be interrupted and killed; it just won't take effect // still can be interrupted and killed; it just won't take effect
// until the child has started. // until the child has started.
Guard<Monitor, DeferredInterruptionScope> g3(parent->_monitor); Guard<Monitor, DeferredInterruptionScope> g3(parent->_monitor);
@@ -368,7 +368,7 @@ namespace ZThread {
if(parent->_monitor.wait() != Monitor::SIGNALED) { if(parent->_monitor.wait() != Monitor::SIGNALED) {
assert(0); assert(0);
} }
} }
@@ -378,23 +378,23 @@ namespace ZThread {
// Map the implementation object onto the running thread. // Map the implementation object onto the running thread.
_threadMap.set(impl); _threadMap.set(impl);
// Update the reference count on a ThreadImpl before the 'Thread' // Update the reference count on a ThreadImpl before the 'Thread'
// that owns it can go out of scope (by signaling the parent) // that owns it can go out of scope (by signaling the parent)
impl->addReference(); impl->addReference();
// Update the priority of the thread // Update the priority of the thread
if(parent->_state.isReference()) if(parent->_state.isReference())
ThreadOps::setPriority(impl, ThreadOps::setPriority(impl,
parent->_state.isReference() ? impl->_priority : parent->_priority); parent->_state.isReference() ? impl->_priority : parent->_priority);
// Inherit ThreadLocal values from the parent // Inherit ThreadLocal values from the parent
typedef ThreadLocalMap::const_iterator It; typedef ThreadLocalMap::const_iterator It;
for(It i = parent->getThreadLocalMap().begin(); i != parent->getThreadLocalMap().end(); ++i) for(It i = parent->getThreadLocalMap().begin(); i != parent->getThreadLocalMap().end(); ++i)
if( (i->second)->isInheritable() ) if( (i->second)->isInheritable() )
impl->getThreadLocalMap()[ i->first ] = (i->second)->clone(); impl->getThreadLocalMap()[ i->first ] = (i->second)->clone();
// Insert a user-thread mapping // Insert a user-thread mapping
ThreadQueue::instance()->insertUserThread(impl); ThreadQueue::instance()->insertUserThread(impl);
// Wake the parent once the thread is setup // Wake the parent once the thread is setup
parent->_monitor.notify(); parent->_monitor.notify();
@@ -403,65 +403,65 @@ namespace ZThread {
// not catch exceptions, let program terminate // not catch exceptions, let program terminate
//try { //try {
task->run(); task->run();
//} catch(...) { //} catch(...) {
// Result of running a task that threw an exception. // Result of running a task that threw an exception.
// ZTDEBUG("The task has thrown an unhandled exception\n"); // ZTDEBUG("The task has thrown an unhandled exception\n");
//assert(0); // UQ1: Go to debugger... //assert(0); // UQ1: Go to debugger...
//} //}
ZTDEBUG("Thread joining...\n"); ZTDEBUG("Thread joining...\n");
{ // Update the state of the thread { // Update the state of the thread
Guard<Monitor> g(impl->_monitor); Guard<Monitor> g(impl->_monitor);
impl->_state.setJoined(); impl->_state.setJoined();
// Wake the joiners that will be easy to join first // Wake the joiners that will be easy to join first
for(List::iterator i = impl->_joiners.begin(); i != impl->_joiners.end();) { for(List::iterator i = impl->_joiners.begin(); i != impl->_joiners.end();) {
ThreadImpl* joiner = *i; ThreadImpl* joiner = *i;
Monitor& m = joiner->getMonitor(); Monitor& m = joiner->getMonitor();
if(m.tryAcquire()) { if(m.tryAcquire()) {
m.notify(); m.notify();
m.release(); m.release();
i = impl->_joiners.erase(i); i = impl->_joiners.erase(i);
} else } else
++i; ++i;
} }
// Wake the joiners that might take a while next // Wake the joiners that might take a while next
for(List::iterator i = impl->_joiners.begin(); i != impl->_joiners.end(); ++i) { for(List::iterator i = impl->_joiners.begin(); i != impl->_joiners.end(); ++i) {
ThreadImpl* joiner = *i; ThreadImpl* joiner = *i;
Monitor& m = joiner->getMonitor(); Monitor& m = joiner->getMonitor();
m.acquire(); m.acquire();
m.notify(); m.notify();
m.release(); m.release();
} }
} }
ZTDEBUG("Thread exiting...\n"); ZTDEBUG("Thread exiting...\n");
// Insert a pending-thread mapping, allowing the resources to be reclaimed // Insert a pending-thread mapping, allowing the resources to be reclaimed
ThreadQueue::instance()->insertPendingThread(impl); ThreadQueue::instance()->insertPendingThread(impl);
// Cleanup ThreadLocal values // Cleanup ThreadLocal values
impl->getThreadLocalMap().clear(); impl->getThreadLocalMap().clear();
// Update the reference count allowing it to be destroyed // Update the reference count allowing it to be destroyed
impl->delReference(); impl->delReference();
} }
+11 -11
View File
@@ -27,13 +27,13 @@ namespace ZThread {
ThreadLocalImpl::ThreadLocalImpl() {} ThreadLocalImpl::ThreadLocalImpl() {}
ThreadLocalImpl::~ThreadLocalImpl() {} ThreadLocalImpl::~ThreadLocalImpl() {}
void ThreadLocalImpl::clearAll() { void ThreadLocalImpl::clearAll() {
typedef ThreadImpl::ThreadLocalMap Map; typedef ThreadImpl::ThreadLocalMap Map;
Map& m = ThreadImpl::current()->getThreadLocalMap(); Map& m = ThreadImpl::current()->getThreadLocalMap();
m.clear(); m.clear();
} }
@@ -42,25 +42,25 @@ namespace ZThread {
typedef ThreadImpl::ThreadLocalMap Map; typedef ThreadImpl::ThreadLocalMap Map;
Map& m = ThreadImpl::current()->getThreadLocalMap(); Map& m = ThreadImpl::current()->getThreadLocalMap();
Map::iterator i = m.find(this); Map::iterator i = m.find(this);
if(i != m.end()) if(i != m.end())
m.erase(i); m.erase(i);
} }
ThreadLocalImpl::ValuePtr ThreadLocalImpl::value( ValuePtr(*pfn)() ) const { ThreadLocalImpl::ValuePtr ThreadLocalImpl::value( ValuePtr(*pfn)() ) const {
typedef ThreadImpl::ThreadLocalMap Map; typedef ThreadImpl::ThreadLocalMap Map;
Map& m = ThreadImpl::current()->getThreadLocalMap(); Map& m = ThreadImpl::current()->getThreadLocalMap();
Map::iterator i = m.find(this); Map::iterator i = m.find(this);
if(i != m.end()) if(i != m.end())
return i->second; return i->second;
m[ this ] = ValuePtr( pfn() ); m[ this ] = ValuePtr( pfn() );
return m[ this ]; return m[ this ];
} }
} // namespace ZThread } // namespace ZThread
+2 -2
View File
@@ -26,10 +26,10 @@
#include "ThreadOps.h" #include "ThreadOps.h"
// This file will select an implementation for a ThreadOps based on // This file will select an implementation for a ThreadOps based on
// what ThreadOps.h selects. This method is for selecting the // what ThreadOps.h selects. This method is for selecting the
// source files, to improve portability. Currently, the project is // source files, to improve portability. Currently, the project is
// based on the autoconf tool-set, which doesn't support conditional // based on the autoconf tool-set, which doesn't support conditional
// compilation well. Additionally, this should make the library // compilation well. Additionally, this should make the library
// easier to port since its working around conditional compilation // easier to port since its working around conditional compilation
// by using C++ features and people won't have to fiddle around with // by using C++ features and people won't have to fiddle around with
// their make tool as much to compile the source // their make tool as much to compile the source
+43 -43
View File
@@ -29,9 +29,9 @@
#include <deque> #include <deque>
namespace ZThread { namespace ZThread {
ThreadQueue::ThreadQueue() ThreadQueue::ThreadQueue()
: _waiter(0) { : _waiter(0) {
ZTDEBUG("ThreadQueue created\n"); ZTDEBUG("ThreadQueue created\n");
@@ -52,36 +52,36 @@ namespace ZThread {
TaskList shutdownTasks; TaskList shutdownTasks;
{ // Check the queue to for pending user threads { // Check the queue to for pending user threads
Guard<FastLock> g(_lock); Guard<FastLock> g(_lock);
waitRequired = (_waiter != (ThreadImpl*)1); waitRequired = (_waiter != (ThreadImpl*)1);
_waiter = impl; _waiter = impl;
threadsWaiting = !_userThreads.empty() || !_pendingThreads.empty(); threadsWaiting = !_userThreads.empty() || !_pendingThreads.empty();
//ZTDEBUG("Wait required: %d\n", waitRequired); //ZTDEBUG("Wait required: %d\n", waitRequired);
//ZTDEBUG("Threads waiting: %d\n", threadsWaiting); //ZTDEBUG("Threads waiting: %d\n", threadsWaiting);
// Auto-cancel any active threads at the time main() goes out of scope // Auto-cancel any active threads at the time main() goes out of scope
// "force" a gentle exit from the executing tasks; eventually the user- // "force" a gentle exit from the executing tasks; eventually the user-
// threads will transition into pending-threads // threads will transition into pending-threads
pollUserThreads(); pollUserThreads();
// Remove all the tasks about to be run from the task list so an indication // Remove all the tasks about to be run from the task list so an indication
// can be given to threads calling removeShutdownTask() too late. // can be given to threads calling removeShutdownTask() too late.
std::remove_copy(_shutdownTasks.begin(), std::remove_copy(_shutdownTasks.begin(),
_shutdownTasks.end(), _shutdownTasks.end(),
std::back_inserter(shutdownTasks), std::back_inserter(shutdownTasks),
Task((Runnable*)0)); Task((Runnable*)0));
//ZTDEBUG("Threads waiting: %d\n", threadsWaiting); //ZTDEBUG("Threads waiting: %d\n", threadsWaiting);
} }
// Execute the shutdown tasks // Execute the shutdown tasks
for(TaskList::iterator i = shutdownTasks.begin(); i != shutdownTasks.end(); ++i) { for(TaskList::iterator i = shutdownTasks.begin(); i != shutdownTasks.end(); ++i) {
try { try {
(*i)->run(); (*i)->run();
} catch(...) { } } catch(...) { }
} }
@@ -93,20 +93,20 @@ namespace ZThread {
Monitor& m = _waiter->getMonitor(); Monitor& m = _waiter->getMonitor();
// Defer interruption while this thread waits for a signal from // Defer interruption while this thread waits for a signal from
// the last pending user thread // the last pending user thread
Guard<Monitor, CompoundScope<DeferredInterruptionScope, LockedScope> > g(m); Guard<Monitor, CompoundScope<DeferredInterruptionScope, LockedScope> > g(m);
//ZTDEBUG("Threads waiting: %d %d\n", _userThreads.size(), _pendingThreads.size()); //ZTDEBUG("Threads waiting: %d %d\n", _userThreads.size(), _pendingThreads.size());
// Avoid race-condition where the last threads are done with thier tasks, but // Avoid race-condition where the last threads are done with thier tasks, but
// only begin the final part of the clean up phase after this destructor begins // only begin the final part of the clean up phase after this destructor begins
// to run. Takes advantage of the fact that if all remaining threads have transitioned // to run. Takes advantage of the fact that if all remaining threads have transitioned
// into a pending state by the time execution reaches this point, then there is no // into a pending state by the time execution reaches this point, then there is no
// need to wait. // need to wait.
waitRequired = waitRequired && !(_userThreads.empty() && !_pendingThreads.empty()); waitRequired = waitRequired && !(_userThreads.empty() && !_pendingThreads.empty());
// Reference threads can't be interrupted or otherwise // Reference threads can't be interrupted or otherwise
// manipulated. The only signal this monitor will receive // manipulated. The only signal this monitor will receive
// at this point will be from the last pending thread. // at this point will be from the last pending thread.
if(waitRequired && m.wait() != Monitor::SIGNALED) { if(waitRequired && m.wait() != Monitor::SIGNALED) {
@@ -115,16 +115,16 @@ namespace ZThread {
// Join those pending threads // Join those pending threads
pollPendingThreads(); pollPendingThreads();
} }
// Clean up the reference threads // Clean up the reference threads
pollReferenceThreads(); pollReferenceThreads();
ZTDEBUG("ThreadQueue destroyed\n"); ZTDEBUG("ThreadQueue destroyed\n");
} }
void ThreadQueue::insertPendingThread(ThreadImpl* impl) { void ThreadQueue::insertPendingThread(ThreadImpl* impl) {
ZTDEBUG("insertPendingThread()\n"); ZTDEBUG("insertPendingThread()\n");
@@ -136,7 +136,7 @@ namespace ZThread {
_userThreads.erase(i); _userThreads.erase(i);
_pendingThreads.push_back(impl); _pendingThreads.push_back(impl);
// Wake the main thread,if its waiting, when the last pending-thread becomes available; // Wake the main thread,if its waiting, when the last pending-thread becomes available;
// Otherwise, take note that no wait for pending threads to finish is needed // Otherwise, take note that no wait for pending threads to finish is needed
if(_userThreads.empty()) if(_userThreads.empty())
@@ -171,7 +171,7 @@ namespace ZThread {
impl->cancel(true); impl->cancel(true);
ZTDEBUG("1 user-thread added.\n"); ZTDEBUG("1 user-thread added.\n");
} }
@@ -183,9 +183,9 @@ namespace ZThread {
ThreadImpl* impl = (ThreadImpl*)*i; ThreadImpl* impl = (ThreadImpl*)*i;
ThreadOps::join(impl); ThreadOps::join(impl);
impl->delReference(); impl->delReference();
i = _pendingThreads.erase(i); i = _pendingThreads.erase(i);
ZTDEBUG("1 pending-thread reclaimed.\n"); ZTDEBUG("1 pending-thread reclaimed.\n");
@@ -199,14 +199,14 @@ namespace ZThread {
ZTDEBUG("pollReferenceThreads()\n"); ZTDEBUG("pollReferenceThreads()\n");
for(ThreadList::iterator i = _referenceThreads.begin(); i != _referenceThreads.end(); ++i) { for(ThreadList::iterator i = _referenceThreads.begin(); i != _referenceThreads.end(); ++i) {
ThreadImpl* impl = (ThreadImpl*)*i; ThreadImpl* impl = (ThreadImpl*)*i;
impl->delReference(); impl->delReference();
ZTDEBUG("1 reference-thread reclaimed.\n"); ZTDEBUG("1 reference-thread reclaimed.\n");
} }
} }
void ThreadQueue::pollUserThreads() { void ThreadQueue::pollUserThreads() {
@@ -219,11 +219,11 @@ namespace ZThread {
impl->cancel(true); impl->cancel(true);
ZTDEBUG("1 user-thread reclaimed.\n"); ZTDEBUG("1 user-thread reclaimed.\n");
} }
} }
void ThreadQueue::insertShutdownTask(Task& task) { void ThreadQueue::insertShutdownTask(Task& task) {
bool hasWaiter = false; bool hasWaiter = false;
@@ -231,34 +231,34 @@ namespace ZThread {
{ {
Guard<FastLock> g(_lock); Guard<FastLock> g(_lock);
// Execute later when the ThreadQueue is destroyed // Execute later when the ThreadQueue is destroyed
if( !(hasWaiter = (_waiter != 0)) ) { if( !(hasWaiter = (_waiter != 0)) ) {
_shutdownTasks.push_back(task); _shutdownTasks.push_back(task);
//ZTDEBUG("1 shutdown task added. %d\n", _shutdownTasks.size()); //ZTDEBUG("1 shutdown task added. %d\n", _shutdownTasks.size());
} }
} }
// Execute immediately if things are shutting down // Execute immediately if things are shutting down
if(hasWaiter) if(hasWaiter)
task->run(); task->run();
} }
bool ThreadQueue::removeShutdownTask(const Task& task) { bool ThreadQueue::removeShutdownTask(const Task& task) {
Guard<FastLock> g(_lock); Guard<FastLock> g(_lock);
TaskList::iterator i = std::find(_shutdownTasks.begin(), _shutdownTasks.end(), task); TaskList::iterator i = std::find(_shutdownTasks.begin(), _shutdownTasks.end(), task);
bool removed = (i != _shutdownTasks.end()); bool removed = (i != _shutdownTasks.end());
if(removed) if(removed)
_shutdownTasks.erase(i); _shutdownTasks.erase(i);
//ZTDEBUG("1 shutdown task removed (%d)-%d\n", removed, _shutdownTasks.size()); //ZTDEBUG("1 shutdown task removed (%d)-%d\n", removed, _shutdownTasks.size());
return removed; return removed;
} }
+65 -65
View File
@@ -31,11 +31,11 @@ namespace ZThread {
namespace { namespace {
//! //!
class WaiterQueue { class WaiterQueue {
typedef std::deque<ThreadImpl*> ThreadList; typedef std::deque<ThreadImpl*> ThreadList;
typedef struct group_t { typedef struct group_t {
size_t id; size_t id;
size_t count; size_t count;
@@ -61,14 +61,14 @@ namespace ZThread {
void operator()(const Group& grp) { count += grp.count; } void operator()(const Group& grp) { count += grp.count; }
operator size_t() { return count; } operator size_t() { return count; }
}; };
FastMutex _lock; FastMutex _lock;
GroupList _list; GroupList _list;
size_t _id; size_t _id;
size_t _generation; size_t _generation;
public: public:
WaiterQueue() : _id(0), _generation(0) { WaiterQueue() : _id(0), _generation(0) {
// At least one empty-group exists // At least one empty-group exists
_list.push_back( Group(_id++) ); _list.push_back( Group(_id++) );
@@ -96,15 +96,15 @@ namespace ZThread {
if((size_t)std::for_each(_list.begin(), _list.end(), counter()) < 1) if((size_t)std::for_each(_list.begin(), _list.end(), counter()) < 1)
return true; return true;
// Update the waiter list for the active group // Update the waiter list for the active group
_list.back().waiters.push_back(self); _list.back().waiters.push_back(self);
size_t n = _list.back().id; size_t n = _list.back().id;
m.acquire(); m.acquire();
{ {
Guard<Lockable, UnlockedScope> g2(g1); Guard<Lockable, UnlockedScope> g2(g1);
state = timeout == 0 ? m.wait() : m.wait(timeout); state = timeout == 0 ? m.wait() : m.wait(timeout);
} }
@@ -135,22 +135,22 @@ namespace ZThread {
throw Interrupted_Exception(); throw Interrupted_Exception();
default: default:
throw Synchronization_Exception(); throw Synchronization_Exception();
} }
return true; return true;
} }
/** /**
* Increment the active group count * Increment the active group count
* *
* @pre at least 1 empty group exists * @pre at least 1 empty group exists
* @post at least 1 non-empty group exists * @post at least 1 non-empty group exists
*/ */
std::pair<size_t, size_t> increment() { std::pair<size_t, size_t> increment() {
Guard<FastMutex> g(_lock); Guard<FastMutex> g(_lock);
// At least one empty-group exists // At least one empty-group exists
assert(!_list.empty()); assert(!_list.empty());
@@ -169,7 +169,7 @@ namespace ZThread {
// When the active group is being incremented, insert a new active group // When the active group is being incremented, insert a new active group
// to replace it if there were waiting threads // to replace it if there were waiting threads
if(i == --_list.end() && !i->waiters.empty()) if(i == --_list.end() && !i->waiters.empty())
_list.push_back(Group(_id++)); _list.push_back(Group(_id++));
// At least 1 non-empty group exists // At least 1 non-empty group exists
@@ -178,13 +178,13 @@ namespace ZThread {
return std::make_pair(n, _generation); return std::make_pair(n, _generation);
} }
/** /**
* Decrease the count for the group with the given id. * Decrease the count for the group with the given id.
* *
* @param n group id * @param n group id
* *
* @pre At least 1 non-empty group exists * @pre At least 1 non-empty group exists
* @post At least 1 empty group exists * @post At least 1 empty group exists
*/ */
@@ -198,7 +198,7 @@ namespace ZThread {
// Find the requested group // Find the requested group
GroupList::iterator i = std::find_if(_list.begin(), _list.end(), by_id(n)); GroupList::iterator i = std::find_if(_list.begin(), _list.end(), by_id(n));
if(i == _list.end()) { if(i == _list.end()) {
// A group should never have been removed until // A group should never have been removed until
// the final task in that group completed // the final task in that group completed
assert(0); assert(0);
@@ -207,11 +207,11 @@ namespace ZThread {
// Decrease the count for tasks in this group, // Decrease the count for tasks in this group,
if(--i->count == 0 && i == _list.begin()) { if(--i->count == 0 && i == _list.begin()) {
do { do {
// When the first group completes, wake all waiters for every // When the first group completes, wake all waiters for every
// group, starting from the first until a group that is not // group, starting from the first until a group that is not
// complete is reached // complete is reached
/* /*
@@ -219,29 +219,29 @@ namespace ZThread {
if(i == --_list.end() && i->waiters.empty()) if(i == --_list.end() && i->waiters.empty())
break; break;
*/ */
if( awaken(*i) ) { if( awaken(*i) ) {
// If all waiters were awakened, remove the group // If all waiters were awakened, remove the group
i = _list.erase(i); i = _list.erase(i);
} else { } else {
{ {
// Otherwise, unlock and yield allowing the waiter // Otherwise, unlock and yield allowing the waiter
// lists to be updated if other threads are busy // lists to be updated if other threads are busy
Guard<FastLock, UnlockedScope> g2(g1); Guard<FastLock, UnlockedScope> g2(g1);
ThreadImpl::yield(); ThreadImpl::yield();
} }
i = _list.begin(); i = _list.begin();
} }
} while(i != _list.end() && i->count == 0); } while(i != _list.end() && i->count == 0);
// Ensure that an active group exists // Ensure that an active group exists
if(_list.empty()) if(_list.empty())
_list.push_back( Group(++_id) ); _list.push_back( Group(++_id) );
@@ -250,7 +250,7 @@ namespace ZThread {
// At least one group exists // At least one group exists
assert(!_list.empty()); assert(!_list.empty());
} }
/** /**
@@ -261,74 +261,74 @@ namespace ZThread {
return next ? _generation++ : _generation; return next ? _generation++ : _generation;
} }
private: private:
/** /**
* Awaken all the waiters remaining in the given group * Awaken all the waiters remaining in the given group
* *
* @return * @return
* - true if all the waiting threads were successfully awakened. * - true if all the waiting threads were successfully awakened.
* - false if there were one or more threads that could not be awakened. * - false if there were one or more threads that could not be awakened.
*/ */
bool awaken(Group& grp) { bool awaken(Group& grp) {
// Go through the waiter list in the given group; // Go through the waiter list in the given group;
for(ThreadList::iterator i = grp.waiters.begin(); i != grp.waiters.end();) { for(ThreadList::iterator i = grp.waiters.begin(); i != grp.waiters.end();) {
ThreadImpl* impl = *i; ThreadImpl* impl = *i;
Monitor& m = impl->getMonitor(); Monitor& m = impl->getMonitor();
// Try the monitor lock, if it cant be locked skip to the next waiter // Try the monitor lock, if it cant be locked skip to the next waiter
if(m.tryAcquire()) { if(m.tryAcquire()) {
// Notify the monitor & remove from the waiter list so time isn't // Notify the monitor & remove from the waiter list so time isn't
// wasted checking it again. // wasted checking it again.
i = grp.waiters.erase(i); i = grp.waiters.erase(i);
// Try to wake the waiter, it doesn't matter if this is successful // Try to wake the waiter, it doesn't matter if this is successful
// or not (only fails when the monitor is already going to stop waiting). // or not (only fails when the monitor is already going to stop waiting).
m.notify(); m.notify();
m.release(); m.release();
} else ++i; } else ++i;
} }
return grp.waiters.empty(); return grp.waiters.empty();
} }
}; };
//! Synchronization point for the Executor //! Synchronization point for the Executor
class ExecutorImpl { class ExecutorImpl {
typedef std::deque<ThreadImpl*> ThreadList; typedef std::deque<ThreadImpl*> ThreadList;
bool _canceled; bool _canceled;
FastMutex _lock; FastMutex _lock;
//! Worker threads //! Worker threads
ThreadList _threads; ThreadList _threads;
WaiterQueue _queue; WaiterQueue _queue;
public: public:
ExecutorImpl() : _canceled(false) {} ExecutorImpl() : _canceled(false) {}
WaiterQueue& getWaiterQueue() { WaiterQueue& getWaiterQueue() {
return _queue; return _queue;
} }
void registerThread(size_t generation) { void registerThread(size_t generation) {
// Interrupt slow starting threads // Interrupt slow starting threads
if(getWaiterQueue().generation() != generation) if(getWaiterQueue().generation() != generation)
ThreadImpl::current()->interrupt(); ThreadImpl::current()->interrupt();
// Enqueue for possible future interrupt() // Enqueue for possible future interrupt()
else { else {
Guard<FastMutex> g(_lock); Guard<FastMutex> g(_lock);
@@ -339,7 +339,7 @@ namespace ZThread {
} }
void unregisterThread() { void unregisterThread() {
Guard<FastMutex> g(_lock); Guard<FastMutex> g(_lock);
std::remove(_threads.begin(), _threads.end(), ThreadImpl::current() ); std::remove(_threads.begin(), _threads.end(), ThreadImpl::current() );
@@ -369,11 +369,11 @@ namespace ZThread {
// Interrupt all the registered threads // Interrupt all the registered threads
for(ThreadList::iterator i = _threads.begin(); i != _threads.end(); ++i) for(ThreadList::iterator i = _threads.begin(); i != _threads.end(); ++i)
(*i)->interrupt(); (*i)->interrupt();
// Bump the generation up, ensuring slow starting threads get this interrupt // Bump the generation up, ensuring slow starting threads get this interrupt
getWaiterQueue().generation( true ); getWaiterQueue().generation( true );
} }
}; /* ExecutorImpl */ }; /* ExecutorImpl */
@@ -392,7 +392,7 @@ namespace ZThread {
: _impl(impl), _task(task) { : _impl(impl), _task(task) {
std::pair<size_t, size_t> pr( _impl->getWaiterQueue().increment() ); std::pair<size_t, size_t> pr( _impl->getWaiterQueue().increment() );
_group = pr.first; _group = pr.first;
_generation = pr.second; _generation = pr.second;
@@ -405,20 +405,20 @@ namespace ZThread {
size_t generation() const { size_t generation() const {
return _generation; return _generation;
} }
void run() { void run() {
// Register this thread once its begun; the generation is used to ensure // Register this thread once its begun; the generation is used to ensure
// threads that are slow starting are properly interrupted // threads that are slow starting are properly interrupted
_impl->registerThread( generation() ); _impl->registerThread( generation() );
try { try {
_task->run(); _task->run();
} catch(...) { } catch(...) {
/* consume the exceptions the work propogates */ /* consume the exceptions the work propogates */
} }
_impl->getWaiterQueue().decrement( group() ); _impl->getWaiterQueue().decrement( group() );
// Unregister this thread // Unregister this thread
@@ -434,30 +434,30 @@ namespace ZThread {
ThreadedExecutor::ThreadedExecutor() : _impl(new ExecutorImpl) {} ThreadedExecutor::ThreadedExecutor() : _impl(new ExecutorImpl) {}
ThreadedExecutor::~ThreadedExecutor() {} ThreadedExecutor::~ThreadedExecutor() {}
void ThreadedExecutor::execute(const Task& task) { void ThreadedExecutor::execute(const Task& task) {
Thread t( new Worker(_impl, task) ); Thread t( new Worker(_impl, task) );
} }
void ThreadedExecutor::interrupt() { void ThreadedExecutor::interrupt() {
_impl->interrupt(); _impl->interrupt();
} }
void ThreadedExecutor::cancel() { void ThreadedExecutor::cancel() {
_impl->cancel(); _impl->cancel();
} }
bool ThreadedExecutor::isCanceled() { bool ThreadedExecutor::isCanceled() {
return _impl->isCanceled(); return _impl->isCanceled();
} }
void ThreadedExecutor::wait() { void ThreadedExecutor::wait() {
_impl->getWaiterQueue().wait(0); _impl->getWaiterQueue().wait(0);
} }
bool ThreadedExecutor::wait(unsigned long timeout) { bool ThreadedExecutor::wait(unsigned long timeout) {
return _impl->getWaiterQueue().wait(timeout == 0 ? 1 : timeout); return _impl->getWaiterQueue().wait(timeout == 0 ? 1 : timeout);
} }
+2 -2
View File
@@ -27,7 +27,7 @@
using namespace ZThread; using namespace ZThread;
Time::Time() { Time::Time() {
// System startup time // System startup time
static TimeStrategy firstHelper; static TimeStrategy firstHelper;
TimeStrategy helper; TimeStrategy helper;
@@ -37,7 +37,7 @@ Time::Time() {
now -= then; now -= then;
_seconds = now.seconds(); _seconds = now.seconds();
_milliseconds = now.milliseconds(); _milliseconds = now.milliseconds();
} }
+6 -6
View File
@@ -47,7 +47,7 @@ typedef struct atomic_count_t {
AtomicCount::AtomicCount() { AtomicCount::AtomicCount() {
_value = reinterpret_cast<void*>(new ATOMIC_COUNT); _value = reinterpret_cast<void*>(new ATOMIC_COUNT);
} }
AtomicCount::~AtomicCount() { AtomicCount::~AtomicCount() {
@@ -55,19 +55,19 @@ AtomicCount::~AtomicCount() {
delete reinterpret_cast<ATOMIC_COUNT*>(_value); delete reinterpret_cast<ATOMIC_COUNT*>(_value);
} }
void AtomicCount::increment() { void AtomicCount::increment() {
atomic_inc(&reinterpret_cast<ATOMIC_COUNT*>(_value)->count); atomic_inc(&reinterpret_cast<ATOMIC_COUNT*>(_value)->count);
} }
bool AtomicCount::decrement() { bool AtomicCount::decrement() {
return atomic_dec_and_test(&reinterpret_cast<ATOMIC_COUNT*>(_value)->count); return atomic_dec_and_test(&reinterpret_cast<ATOMIC_COUNT*>(_value)->count);
} }
}; };
#endif // __ZTATOMICCOUNTIMPL_H__ #endif // __ZTATOMICCOUNTIMPL_H__
+32 -32
View File
@@ -29,20 +29,20 @@
using namespace ZThread; using namespace ZThread;
Monitor::Monitor() : _owner(0), _waiting(false), _pending(false) { Monitor::Monitor() : _owner(0), _waiting(false), _pending(false) {
if(MPCreateSemaphore(1, 0, &_sema) != noErr) { if(MPCreateSemaphore(1, 0, &_sema) != noErr) {
assert(0); assert(0);
throw Initialization_Exception(); throw Initialization_Exception();
} }
} }
Monitor::~Monitor() throw() { Monitor::~Monitor() throw() {
assert(!_waiting); assert(!_waiting);
OSStatus status = MPDeleteSemaphore(_sema); OSStatus status = MPDeleteSemaphore(_sema);
if(status != noErr) if(status != noErr)
assert(false); assert(false);
} }
@@ -53,9 +53,9 @@ Monitor::STATE Monitor::wait(unsigned long timeout) {
// http://developer.apple.com/techpubs/macosx/Carbon/oss/MultiPServices/Multiprocessing_Services/index.html?http://developer.apple.com/techpubs/macosx/Carbon/oss/MultiPServices/Multiprocessing_Services/Functions/Creating_and_ssage_Queues.html // http://developer.apple.com/techpubs/macosx/Carbon/oss/MultiPServices/Multiprocessing_Services/index.html?http://developer.apple.com/techpubs/macosx/Carbon/oss/MultiPServices/Multiprocessing_Services/Functions/Creating_and_ssage_Queues.html
AbsoluteTime tTarget; AbsoluteTime tTarget;
Duration waitDuration = Duration waitDuration =
(timeout == 0) ? kDurationForever : (kDurationMillisecond * timeout); (timeout == 0) ? kDurationForever : (kDurationMillisecond * timeout);
if(waitDuration != kDurationForever) if(waitDuration != kDurationForever)
tTarget = AddDurationToAbsolute(waitDuration, UpTime()); tTarget = AddDurationToAbsolute(waitDuration, UpTime());
@@ -66,13 +66,13 @@ Monitor::STATE Monitor::wait(unsigned long timeout) {
_owner = MPCurrentTaskID(); _owner = MPCurrentTaskID();
STATE state(INVALID); STATE state(INVALID);
// Serialize access to the state of the Monitor // Serialize access to the state of the Monitor
// and test the state to determine if a wait is needed. // and test the state to determine if a wait is needed.
_waitLock.acquire(); _waitLock.acquire();
if(pending(ANYTHING)) { if(pending(ANYTHING)) {
// Return without waiting when possible // Return without waiting when possible
state = next(); state = next();
@@ -80,57 +80,57 @@ Monitor::STATE Monitor::wait(unsigned long timeout) {
return state; return state;
} }
// Unlock the external lock if a wait() is probably needed. // Unlock the external lock if a wait() is probably needed.
// Access to the state is still serial. // Access to the state is still serial.
_lock.release(); _lock.release();
// Wait for a transition in the state that is of interest, this // Wait for a transition in the state that is of interest, this
// allows waits to exclude certain flags (e.g. INTERRUPTED) // allows waits to exclude certain flags (e.g. INTERRUPTED)
// for a single wait() w/o actually discarding those flags - // for a single wait() w/o actually discarding those flags -
// they will remain set until a wait interested in those flags // they will remain set until a wait interested in those flags
// occurs. // occurs.
// Wait, ignoring signals // Wait, ignoring signals
_waiting = true; _waiting = true;
_waitLock.release(); _waitLock.release();
// Update the wait time // Update the wait time
if(waitDuration != kDurationForever) if(waitDuration != kDurationForever)
waitDuration = AbsoluteDeltaToDuration(tTarget, UpTime()); waitDuration = AbsoluteDeltaToDuration(tTarget, UpTime());
// Sleep until a signal arrives or a timeout occurs // Sleep until a signal arrives or a timeout occurs
OSStatus status = MPWaitOnSemaphore(_sema, waitDuration); OSStatus status = MPWaitOnSemaphore(_sema, waitDuration);
// Reacquire serialized access to the state // Reacquire serialized access to the state
_waitLock.acquire(); _waitLock.acquire();
// Awaken only when the event is set or the timeout expired // Awaken only when the event is set or the timeout expired
assert(status == kMPTimeoutErr || status == noErr); assert(status == kMPTimeoutErr || status == noErr);
if(status == kMPTimeoutErr) if(status == kMPTimeoutErr)
push(TIMEDOUT); push(TIMEDOUT);
// Get the next available STATE // Get the next available STATE
state = next(); state = next();
_waiting = false; _waiting = false;
// Its possible that a timeout will wake the thread before a signal is // Its possible that a timeout will wake the thread before a signal is
// delivered. Absorb that leftover so the next wait isn't aborted right away // delivered. Absorb that leftover so the next wait isn't aborted right away
if(status == kMPTimeoutErr && _pending) { if(status == kMPTimeoutErr && _pending) {
status = MPWaitOnSemaphore(_sema, kDurationForever); status = MPWaitOnSemaphore(_sema, kDurationForever);
assert(status == noErr); assert(status == noErr);
} }
_pending = false; _pending = false;
// Acquire the internal lock & release the external lock // Acquire the internal lock & release the external lock
_waitLock.release(); _waitLock.release();
// Reaquire the external lock, keep from deadlocking threads calling // Reaquire the external lock, keep from deadlocking threads calling
// notify(), interrupt(), etc. // notify(), interrupt(), etc.
_lock.acquire(); _lock.acquire();
@@ -143,7 +143,7 @@ bool Monitor::interrupt() {
// Serialize access to the state // Serialize access to the state
_waitLock.acquire(); _waitLock.acquire();
bool wasInterruptable = !pending(INTERRUPTED); bool wasInterruptable = !pending(INTERRUPTED);
bool hasWaiter = false; bool hasWaiter = false;
@@ -151,7 +151,7 @@ bool Monitor::interrupt() {
if(wasInterruptable) { if(wasInterruptable) {
push(INTERRUPTED); push(INTERRUPTED);
wasInterruptable = false; wasInterruptable = false;
if(_waiting && !_pending) { if(_waiting && !_pending) {
@@ -159,7 +159,7 @@ bool Monitor::interrupt() {
_pending = true; _pending = true;
hasWaiter = true; hasWaiter = true;
} else } else
wasInterruptable = !(_owner == MPCurrentTaskID()); wasInterruptable = !(_owner == MPCurrentTaskID());
} }
@@ -180,7 +180,7 @@ bool Monitor::isInterrupted() {
bool wasInterrupted = pending(INTERRUPTED); bool wasInterrupted = pending(INTERRUPTED);
clear(INTERRUPTED); clear(INTERRUPTED);
_waitLock.release(); _waitLock.release();
return wasInterrupted; return wasInterrupted;
@@ -227,12 +227,12 @@ bool Monitor::cancel() {
bool wasInterrupted = !pending(INTERRUPTED); bool wasInterrupted = !pending(INTERRUPTED);
bool hasWaiter = false; bool hasWaiter = false;
push(CANCELED); push(CANCELED);
// Update the state if theres a waiter // Update the state if theres a waiter
if(wasInterrupted) { if(wasInterrupted) {
push(INTERRUPTED); push(INTERRUPTED);
if(_waiting && !_pending) { if(_waiting && !_pending) {
@@ -243,9 +243,9 @@ bool Monitor::cancel() {
} }
} }
_waitLock.release(); _waitLock.release();
if(hasWaiter && !masked(Monitor::INTERRUPTED)) if(hasWaiter && !masked(Monitor::INTERRUPTED))
MPSignalSemaphore(_sema); MPSignalSemaphore(_sema);
@@ -254,12 +254,12 @@ bool Monitor::cancel() {
} }
bool Monitor::isCanceled() { bool Monitor::isCanceled() {
// Serialize access to the state // Serialize access to the state
_waitLock.acquire(); _waitLock.acquire();
bool wasCanceled = Status::examine(CANCELED); bool wasCanceled = Status::examine(CANCELED);
if(_owner == MPCurrentTaskID()) if(_owner == MPCurrentTaskID())
clear(INTERRUPTED); clear(INTERRUPTED);
+9 -9
View File
@@ -27,25 +27,25 @@
namespace ZThread { namespace ZThread {
const ThreadOps ThreadOps::INVALID(0); const ThreadOps ThreadOps::INVALID(0);
ThreadOps::ThreadOps() : _queue(0), _tid(0) {
ThreadOps::ThreadOps() : _queue(0), _tid(0) {
if(MPCreateQueue(&_queue) != noErr) if(MPCreateQueue(&_queue) != noErr)
throw Initialization_Exception(); throw Initialization_Exception();
} }
ThreadOps::~ThreadOps() throw() { ThreadOps::~ThreadOps() throw() {
if(_queue != 0) { if(_queue != 0) {
OSStatus status = MPDeleteQueue(_queue); OSStatus status = MPDeleteQueue(_queue);
if(status != noErr) if(status != noErr)
assert(0); assert(0);
} }
} }
bool ThreadOps::join(ThreadOps* ops) { bool ThreadOps::join(ThreadOps* ops) {
@@ -56,7 +56,7 @@ bool ThreadOps::join(ThreadOps* ops) {
OSStatus status = MPWaitOnQueue(ops->_queue, NULL, NULL, NULL, kDurationForever); OSStatus status = MPWaitOnQueue(ops->_queue, NULL, NULL, NULL, kDurationForever);
return status == noErr; return status == noErr;
} }
bool ThreadOps::yield() { bool ThreadOps::yield() {
@@ -91,13 +91,13 @@ OSStatus ThreadOps::_dispatch(void *arg) {
// Run the task from the correct context // Run the task from the correct context
task->run(); task->run();
// Exit the thread // Exit the thread
MPExit(noErr); MPExit(noErr);
return noErr; return noErr;
} }
} // namespace ZThread } // namespace ZThread
+51 -51
View File
@@ -31,19 +31,19 @@
namespace ZThread { namespace ZThread {
Monitor::Monitor() : _owner(0), _waiting(false) { Monitor::Monitor() : _owner(0), _waiting(false) {
pthread_cond_init(&_waitCond, 0); pthread_cond_init(&_waitCond, 0);
pthread_mutex_init(&_waitLock, 0); pthread_mutex_init(&_waitLock, 0);
} }
Monitor::~Monitor() { Monitor::~Monitor() {
assert(!_waiting); assert(!_waiting);
pthread_cond_destroy(&_waitCond); pthread_cond_destroy(&_waitCond);
pthread_mutex_destroy(&_waitLock); pthread_mutex_destroy(&_waitLock);
} }
Monitor::STATE Monitor::wait(unsigned long ms) { Monitor::STATE Monitor::wait(unsigned long ms) {
@@ -55,14 +55,14 @@ Monitor::STATE Monitor::wait(unsigned long ms) {
_owner = pthread_self(); _owner = pthread_self();
STATE state(INVALID); STATE state(INVALID);
// Serialize access to the state of the Monitor // Serialize access to the state of the Monitor
// and test the state to determine if a wait is needed. // and test the state to determine if a wait is needed.
pthread_mutex_lock(&_waitLock); pthread_mutex_lock(&_waitLock);
if(pending(ANYTHING)) { if(pending(ANYTHING)) {
// Return without waiting when possible // Return without waiting when possible
state = next(); state = next();
@@ -70,13 +70,13 @@ Monitor::STATE Monitor::wait(unsigned long ms) {
return state; return state;
} }
// Unlock the external lock if a wait() is probably needed. // Unlock the external lock if a wait() is probably needed.
// Access to the state is still serial. // Access to the state is still serial.
_lock.release(); _lock.release();
// Wait for a transition in the state that is of interest, this // Wait for a transition in the state that is of interest, this
// allows waits to exclude certain flags (e.g. INTERRUPTED) // allows waits to exclude certain flags (e.g. INTERRUPTED)
// for a single wait() w/o actually discarding those flags - // for a single wait() w/o actually discarding those flags -
// they will remain set until a wait interested in those flags // they will remain set until a wait interested in those flags
// occurs. // occurs.
@@ -85,20 +85,20 @@ Monitor::STATE Monitor::wait(unsigned long ms) {
// Wait, ignoring signals // Wait, ignoring signals
_waiting = true; _waiting = true;
int status = 0; int status = 0;
if(ms == 0) { // Wait forever if(ms == 0) { // Wait forever
do { // ignore signals unless the state is interesting do { // ignore signals unless the state is interesting
status = pthread_cond_wait(&_waitCond, &_waitLock); status = pthread_cond_wait(&_waitCond, &_waitLock);
} while(status == EINTR && !pending(ANYTHING)); } while(status == EINTR && !pending(ANYTHING));
// Akwaken only when a state is pending // Akwaken only when a state is pending
assert(status == 0); assert(status == 0);
} else { } else {
// Find the target time // Find the target time
TimeStrategy t; TimeStrategy t;
ms += t.milliseconds(); ms += t.milliseconds();
@@ -106,34 +106,34 @@ Monitor::STATE Monitor::wait(unsigned long ms) {
ms %= 1000; ms %= 1000;
// Convert to a timespec // Convert to a timespec
struct ::timespec timeout; struct ::timespec timeout;
timeout.tv_sec = s; timeout.tv_sec = s;
timeout.tv_nsec = ms*1000000; timeout.tv_nsec = ms*1000000;
// Wait ignoring signals until the state is interesting // Wait ignoring signals until the state is interesting
do { do {
// When a timeout occurs, update the state to reflect that. // When a timeout occurs, update the state to reflect that.
status = pthread_cond_timedwait(&_waitCond, &_waitLock, &timeout); status = pthread_cond_timedwait(&_waitCond, &_waitLock, &timeout);
} while(status == EINTR && !pending(ANYTHING)); } while(status == EINTR && !pending(ANYTHING));
// Akwaken only when a state is pending or when the timeout expired // Akwaken only when a state is pending or when the timeout expired
assert(status == 0 || status == ETIMEDOUT); assert(status == 0 || status == ETIMEDOUT);
if(status == ETIMEDOUT) if(status == ETIMEDOUT)
push(TIMEDOUT); push(TIMEDOUT);
} }
// Get the next available STATE // Get the next available STATE
state = next(); state = next();
_waiting = false; _waiting = false;
pthread_mutex_unlock(&_waitLock); pthread_mutex_unlock(&_waitLock);
// Reaquire the external lock, keep from deadlocking threads calling // Reaquire the external lock, keep from deadlocking threads calling
// notify(), interrupt(), etc. // notify(), interrupt(), etc.
_lock.acquire(); _lock.acquire();
@@ -147,17 +147,17 @@ bool Monitor::interrupt() {
// Serialize access to the state // Serialize access to the state
pthread_mutex_lock(&_waitLock); pthread_mutex_lock(&_waitLock);
bool wasInterruptable = !pending(INTERRUPTED); bool wasInterruptable = !pending(INTERRUPTED);
bool hadWaiter = _waiting; bool hadWaiter = _waiting;
if(wasInterruptable) { if(wasInterruptable) {
// Update the state & wake the waiter if there is one // Update the state & wake the waiter if there is one
push(INTERRUPTED); push(INTERRUPTED);
wasInterruptable = false; wasInterruptable = false;
if(hadWaiter && !masked(Monitor::INTERRUPTED)) if(hadWaiter && !masked(Monitor::INTERRUPTED))
pthread_cond_signal(&_waitCond); pthread_cond_signal(&_waitCond);
else else
@@ -180,7 +180,7 @@ bool Monitor::isInterrupted() {
bool wasInterrupted = pending(INTERRUPTED); bool wasInterrupted = pending(INTERRUPTED);
clear(INTERRUPTED); clear(INTERRUPTED);
pthread_mutex_unlock(&_waitLock); pthread_mutex_unlock(&_waitLock);
return wasInterrupted; return wasInterrupted;
@@ -193,7 +193,7 @@ bool Monitor::isCanceled() {
pthread_mutex_lock(&_waitLock); pthread_mutex_lock(&_waitLock);
bool wasCanceled = examine(CANCELED); bool wasCanceled = examine(CANCELED);
if(pthread_equal(_owner, pthread_self())) if(pthread_equal(_owner, pthread_self()))
clear(INTERRUPTED); clear(INTERRUPTED);
@@ -210,17 +210,17 @@ bool Monitor::cancel() {
bool wasInterrupted = !pending(INTERRUPTED); bool wasInterrupted = !pending(INTERRUPTED);
bool hadWaiter = _waiting; bool hadWaiter = _waiting;
push(CANCELED); push(CANCELED);
if(wasInterrupted) { if(wasInterrupted) {
// Update the state & wake the waiter if there is one // Update the state & wake the waiter if there is one
push(INTERRUPTED); push(INTERRUPTED);
if(hadWaiter && !masked(Monitor::INTERRUPTED)) if(hadWaiter && !masked(Monitor::INTERRUPTED))
pthread_cond_signal(&_waitCond); pthread_cond_signal(&_waitCond);
} }
pthread_mutex_unlock(&_waitLock); pthread_mutex_unlock(&_waitLock);
@@ -235,16 +235,16 @@ bool Monitor::notify() {
pthread_mutex_lock(&_waitLock); pthread_mutex_lock(&_waitLock);
bool wasNotifyable = !pending(INTERRUPTED); bool wasNotifyable = !pending(INTERRUPTED);
if(wasNotifyable) { if(wasNotifyable) {
// Set the flag and wake the waiter if there // Set the flag and wake the waiter if there
// is one // is one
push(SIGNALED); push(SIGNALED);
if(_waiting) if(_waiting)
pthread_cond_signal(&_waitCond); pthread_cond_signal(&_waitCond);
} }
pthread_mutex_unlock(&_waitLock); pthread_mutex_unlock(&_waitLock);
+15 -15
View File
@@ -31,7 +31,7 @@
namespace ZThread { namespace ZThread {
const ThreadOps ThreadOps::INVALID(0); const ThreadOps ThreadOps::INVALID(0);
bool ThreadOps::join(ThreadOps* ops) { bool ThreadOps::join(ThreadOps* ops) {
@@ -57,7 +57,7 @@ bool ThreadOps::yield() {
#if defined(HAVE_SCHED_YIELD) #if defined(HAVE_SCHED_YIELD)
result = sched_yield() == 0; result = sched_yield() == 0;
#endif #endif
return result; return result;
} }
@@ -67,11 +67,11 @@ bool ThreadOps::setPriority(ThreadOps* impl, Priority p) {
assert(impl); assert(impl);
bool result = true; bool result = true;
#if !defined(ZTHREAD_DISABLE_PRIORITY) #if !defined(ZTHREAD_DISABLE_PRIORITY)
struct sched_param param; struct sched_param param;
switch(p) { switch(p) {
case Low: case Low:
param.sched_priority = 0; param.sched_priority = 0;
@@ -83,7 +83,7 @@ bool ThreadOps::setPriority(ThreadOps* impl, Priority p) {
default: default:
param.sched_priority = 5; param.sched_priority = 5;
} }
result = pthread_setschedparam(impl->_tid, SCHED_OTHER, &param) == 0; result = pthread_setschedparam(impl->_tid, SCHED_OTHER, &param) == 0;
#endif #endif
@@ -97,14 +97,14 @@ bool ThreadOps::getPriority(ThreadOps* impl, Priority& p) {
assert(impl); assert(impl);
bool result = true; bool result = true;
#if !defined(ZTHREAD_DISABLE_PRIORITY) #if !defined(ZTHREAD_DISABLE_PRIORITY)
struct sched_param param; struct sched_param param;
int policy = SCHED_OTHER; int policy = SCHED_OTHER;
if(result = (pthread_getschedparam(impl->_tid, &policy, &param) == 0)) { if(result = (pthread_getschedparam(impl->_tid, &policy, &param) == 0)) {
// Convert to one of the PRIORITY values // Convert to one of the PRIORITY values
if(param.sched_priority < 10) if(param.sched_priority < 10)
p = Low; p = Low;
@@ -112,9 +112,9 @@ bool ThreadOps::getPriority(ThreadOps* impl, Priority& p) {
p = Medium; p = Medium;
else else
p = High; p = High;
} }
#endif #endif
return result; return result;
@@ -132,16 +132,16 @@ extern "C" void *_dispatch(void *arg) {
Runnable* task = reinterpret_cast<Runnable*>(arg); Runnable* task = reinterpret_cast<Runnable*>(arg);
assert(task); assert(task);
// Run the task from the correct context // Run the task from the correct context
task->run(); task->run();
// Exit the thread // Exit the thread
pthread_exit((void**)0); pthread_exit((void**)0);
return (void*)0; return (void*)0;
} }
} // namespace ZThread } // namespace ZThread
+10 -10
View File
@@ -34,7 +34,7 @@ typedef struct atomic_count_t {
FastLock lock; FastLock lock;
unsigned long count; unsigned long count;
atomic_count_t() : count(0) {} atomic_count_t() : count(0) {}
} ATOMIC_COUNT; } ATOMIC_COUNT;
@@ -43,7 +43,7 @@ AtomicCount::AtomicCount() {
ATOMIC_COUNT* c = new ATOMIC_COUNT; ATOMIC_COUNT* c = new ATOMIC_COUNT;
_value = reinterpret_cast<void*>(c); _value = reinterpret_cast<void*>(c);
} }
AtomicCount::~AtomicCount() { AtomicCount::~AtomicCount() {
@@ -54,22 +54,22 @@ AtomicCount::~AtomicCount() {
delete c; delete c;
} }
//! Postfix decrement and return the current value //! Postfix decrement and return the current value
size_t AtomicCount::operator--(int) { size_t AtomicCount::operator--(int) {
ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value); ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
Guard<FastLock> g(c->lock); Guard<FastLock> g(c->lock);
return c->count--; return c->count--;
} }
//! Postfix increment and return the current value //! Postfix increment and return the current value
size_t AtomicCount::operator++(int) { size_t AtomicCount::operator++(int) {
ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value); ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
Guard<FastLock> g(c->lock); Guard<FastLock> g(c->lock);
return c->count++; return c->count++;
@@ -79,17 +79,17 @@ size_t AtomicCount::operator++(int) {
size_t AtomicCount::operator--() { size_t AtomicCount::operator--() {
ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value); ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
Guard<FastLock> g(c->lock); Guard<FastLock> g(c->lock);
return --c->count; return --c->count;
} }
//! Prefix increment and return the current value //! Prefix increment and return the current value
size_t AtomicCount::operator++() { size_t AtomicCount::operator++() {
ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value); ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
Guard<FastLock> g(c->lock); Guard<FastLock> g(c->lock);
return ++c->count; return ++c->count;
+6 -6
View File
@@ -32,7 +32,7 @@ namespace ZThread {
AtomicCount::AtomicCount() { AtomicCount::AtomicCount() {
_value = reinterpret_cast<void*>(new LONG(0)); _value = reinterpret_cast<void*>(new LONG(0));
} }
AtomicCount::~AtomicCount() { AtomicCount::~AtomicCount() {
@@ -41,20 +41,20 @@ AtomicCount::~AtomicCount() {
delete reinterpret_cast<LPLONG>(_value); delete reinterpret_cast<LPLONG>(_value);
} }
void AtomicCount::increment() { void AtomicCount::increment() {
::InterlockedIncrement(reinterpret_cast<LPLONG>(_value)); ::InterlockedIncrement(reinterpret_cast<LPLONG>(_value));
} }
bool AtomicCount::decrement() { bool AtomicCount::decrement() {
LONG v = ::InterlockedDecrement(reinterpret_cast<LPLONG>(_value)); LONG v = ::InterlockedDecrement(reinterpret_cast<LPLONG>(_value));
return static_cast<unsigned long>(v) == 0; return static_cast<unsigned long>(v) == 0;
} }
}; };
#endif // __ZTATOMICCOUNTIMPL_H__ #endif // __ZTATOMICCOUNTIMPL_H__
+34 -34
View File
@@ -29,24 +29,24 @@
using namespace ZThread; using namespace ZThread;
Monitor::Monitor() : _owner(0), _waiting(false) { Monitor::Monitor() : _owner(0), _waiting(false) {
_handle = ::CreateEvent(0, TRUE, FALSE, 0); _handle = ::CreateEvent(0, TRUE, FALSE, 0);
if(_handle == NULL) { if(_handle == NULL) {
assert(0); assert(0);
} }
} }
Monitor::~Monitor() { Monitor::~Monitor() {
assert(!_waiting); assert(!_waiting);
::CloseHandle(_handle); ::CloseHandle(_handle);
} }
Monitor::STATE Monitor::wait(unsigned long ms) { Monitor::STATE Monitor::wait(unsigned long ms) {
// Update the owner on first use. The owner will not change, each // Update the owner on first use. The owner will not change, each
// thread waits only on a single Monitor and a Monitor is never // thread waits only on a single Monitor and a Monitor is never
// shared // shared
@@ -54,13 +54,13 @@ Monitor::STATE Monitor::wait(unsigned long ms) {
_owner = ::GetCurrentThreadId(); _owner = ::GetCurrentThreadId();
STATE state; //(INVALID); STATE state; //(INVALID);
// Serialize access to the state of the Monitor // Serialize access to the state of the Monitor
// and test the state to determine if a wait is needed. // and test the state to determine if a wait is needed.
_waitLock.acquire(); _waitLock.acquire();
if(pending(ANYTHING)) { if(pending(ANYTHING)) {
// Return without waiting when possible // Return without waiting when possible
state = next(); state = next();
@@ -68,12 +68,12 @@ Monitor::STATE Monitor::wait(unsigned long ms) {
return state; return state;
} }
// Unlock the external lock if a wait() is probably needed. // Unlock the external lock if a wait() is probably needed.
// Access to the state is still serial. // Access to the state is still serial.
_lock.release(); _lock.release();
// Wait for a transition in the state that is of interest, this // Wait for a transition in the state that is of interest, this
// allows waits to exclude certain flags (e.g. INTERRUPTED) // allows waits to exclude certain flags (e.g. INTERRUPTED)
// for a single wait() w/o actually discarding those flags - // for a single wait() w/o actually discarding those flags -
// they will remain set until a wait interested in those flags // they will remain set until a wait interested in those flags
// occurs. // occurs.
@@ -82,13 +82,13 @@ Monitor::STATE Monitor::wait(unsigned long ms) {
// Wait, ignoring signals // Wait, ignoring signals
_waiting = true; _waiting = true;
// Block until the event is set. // Block until the event is set.
_waitLock.release(); _waitLock.release();
// The event is manual reset so this lack of atmoicity will not // The event is manual reset so this lack of atmoicity will not
// be an issue // be an issue
DWORD dwResult = DWORD dwResult =
::WaitForSingleObject(_handle, ((ms == 0) ? INFINITE : (DWORD)ms)); ::WaitForSingleObject(_handle, ((ms == 0) ? INFINITE : (DWORD)ms));
// Reacquire serialized access to the state // Reacquire serialized access to the state
@@ -99,20 +99,20 @@ Monitor::STATE Monitor::wait(unsigned long ms) {
if(dwResult == WAIT_TIMEOUT) if(dwResult == WAIT_TIMEOUT)
push(TIMEDOUT); push(TIMEDOUT);
// Get the next available STATE // Get the next available STATE
state = next(); state = next();
_waiting = false; _waiting = false;
::ResetEvent(_handle); ::ResetEvent(_handle);
// Acquire the internal lock & release the external lock // Acquire the internal lock & release the external lock
_waitLock.release(); _waitLock.release();
// Reaquire the external lock, keep from deadlocking threads calling // Reaquire the external lock, keep from deadlocking threads calling
// notify(), interrupt(), etc. // notify(), interrupt(), etc.
_lock.acquire(); _lock.acquire();
return state; return state;
} }
@@ -122,12 +122,12 @@ bool Monitor::interrupt() {
// Serialize access to the state // Serialize access to the state
_waitLock.acquire(); _waitLock.acquire();
bool wasInterruptable = !pending(INTERRUPTED); bool wasInterruptable = !pending(INTERRUPTED);
bool hadWaiter = _waiting; bool hadWaiter = _waiting;
if(wasInterruptable) { if(wasInterruptable) {
// Update the state & wake the waiter if there is one // Update the state & wake the waiter if there is one
push(INTERRUPTED); push(INTERRUPTED);
@@ -140,9 +140,9 @@ bool Monitor::interrupt() {
assert(0); assert(0);
} }
} else } else
wasInterruptable = !(_owner == ::GetCurrentThreadId()); wasInterruptable = !(_owner == ::GetCurrentThreadId());
} }
_waitLock.release(); _waitLock.release();
@@ -159,7 +159,7 @@ bool Monitor::isInterrupted() {
bool wasInterrupted = pending(INTERRUPTED); bool wasInterrupted = pending(INTERRUPTED);
clear(INTERRUPTED); clear(INTERRUPTED);
_waitLock.release(); _waitLock.release();
return wasInterrupted; return wasInterrupted;
@@ -173,15 +173,15 @@ bool Monitor::notify() {
_waitLock.acquire(); _waitLock.acquire();
bool wasNotifyable = !pending(INTERRUPTED); bool wasNotifyable = !pending(INTERRUPTED);
if(wasNotifyable) { if(wasNotifyable) {
// Set the flag and wake the waiter if there // Set the flag and wake the waiter if there
// is one // is one
push(SIGNALED); push(SIGNALED);
// If there is a waiter then send the signal. // If there is a waiter then send the signal.
if(_waiting) if(_waiting)
if(::SetEvent(_handle) == FALSE) { if(::SetEvent(_handle) == FALSE) {
assert(0); assert(0);
} }
@@ -202,20 +202,20 @@ bool Monitor::cancel() {
bool wasInterrupted = !pending(INTERRUPTED); bool wasInterrupted = !pending(INTERRUPTED);
bool hadWaiter = _waiting; bool hadWaiter = _waiting;
push(CANCELED); push(CANCELED);
if(wasInterrupted) { if(wasInterrupted) {
// Update the state & wake the waiter if there is one // Update the state & wake the waiter if there is one
push(INTERRUPTED); push(INTERRUPTED);
// If there is a waiter then send the signal. // If there is a waiter then send the signal.
if(hadWaiter && !masked(Monitor::INTERRUPTED)) if(hadWaiter && !masked(Monitor::INTERRUPTED))
if(::SetEvent(_handle) == FALSE) { if(::SetEvent(_handle) == FALSE) {
assert(0); assert(0);
} }
} }
_waitLock.release(); _waitLock.release();
@@ -230,7 +230,7 @@ bool Monitor::isCanceled() {
_waitLock.acquire(); _waitLock.acquire();
bool wasCanceled = examine(CANCELED); bool wasCanceled = examine(CANCELED);
if(_owner == ::GetCurrentThreadId()) if(_owner == ::GetCurrentThreadId())
clear(INTERRUPTED); clear(INTERRUPTED);
+14 -14
View File
@@ -26,7 +26,7 @@
namespace ZThread { namespace ZThread {
const ThreadOps ThreadOps::INVALID(0); const ThreadOps ThreadOps::INVALID(0);
/** /**
* Detect OS at runtime and attempt to locate the SwitchToThread * Detect OS at runtime and attempt to locate the SwitchToThread
@@ -46,10 +46,10 @@ public:
v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if(::GetVersionEx(&v) && (v.dwPlatformId == VER_PLATFORM_WIN32_NT)) { if(::GetVersionEx(&v) && (v.dwPlatformId == VER_PLATFORM_WIN32_NT)) {
// Uses GetModuleHandle() so the reference count on the dll is // Uses GetModuleHandle() so the reference count on the dll is
// not affected. There is a warning about race conditions involving // not affected. There is a warning about race conditions involving
// this function being called as FreeLibrary() completes; however // this function being called as FreeLibrary() completes; however
// nearly all win32 applications load this particular and will keep it // nearly all win32 applications load this particular and will keep it
// in memory until the process exits. // in memory until the process exits.
HINSTANCE hInst = ::GetModuleHandle("Kernel32.dll"); HINSTANCE hInst = ::GetModuleHandle("Kernel32.dll");
@@ -62,10 +62,10 @@ public:
} }
bool operator()() { bool operator()() {
// Attempt to yield using the best function available // Attempt to yield using the best function available
if(!_fnYield || !_fnYield()) if(!_fnYield || !_fnYield())
::Sleep(0); ::Sleep(0);
return true; return true;
@@ -78,8 +78,8 @@ bool ThreadOps::join(ThreadOps* ops) {
assert(ops); assert(ops);
assert(ops->_tid != 0); assert(ops->_tid != 0);
assert(ops->_hThread != NULL); assert(ops->_hThread != NULL);
if(::WaitForSingleObjectEx(ops->_hThread, INFINITE, FALSE) != WAIT_OBJECT_0) if(::WaitForSingleObjectEx(ops->_hThread, INFINITE, FALSE) != WAIT_OBJECT_0)
return false; return false;
::CloseHandle(ops->_hThread); ::CloseHandle(ops->_hThread);
@@ -102,11 +102,11 @@ bool ThreadOps::yield() {
bool ThreadOps::setPriority(ThreadOps* impl, Priority p) { bool ThreadOps::setPriority(ThreadOps* impl, Priority p) {
assert(impl); assert(impl);
#if !defined(ZTHREAD_DISABLE_PRIORITY) #if !defined(ZTHREAD_DISABLE_PRIORITY)
bool result; bool result;
// Convert // Convert
int n; int n;
switch(p) { switch(p) {
@@ -121,7 +121,7 @@ bool ThreadOps::setPriority(ThreadOps* impl, Priority p) {
n = THREAD_PRIORITY_NORMAL; n = THREAD_PRIORITY_NORMAL;
} }
result = (::SetThreadPriority(impl->_hThread, n) != THREAD_PRIORITY_ERROR_RETURN); result = (::SetThreadPriority(impl->_hThread, n) != THREAD_PRIORITY_ERROR_RETURN);
return result; return result;
@@ -137,7 +137,7 @@ bool ThreadOps::getPriority(ThreadOps* impl, Priority& p) {
assert(impl); assert(impl);
bool result = true; bool result = true;
#if !defined(ZTHREAD_DISABLE_PRIORITY) #if !defined(ZTHREAD_DISABLE_PRIORITY)
// Convert to one of the PRIORITY values // Convert to one of the PRIORITY values
@@ -154,7 +154,7 @@ bool ThreadOps::getPriority(ThreadOps* impl, Priority& p) {
default: default:
p = Medium; p = Medium;
} }
#endif #endif
return result; return result;
@@ -191,7 +191,7 @@ unsigned int __stdcall ThreadOps::_dispatch(void *arg) {
#endif #endif
return 0; return 0;
} }
} }
+15 -15
View File
@@ -29,12 +29,12 @@
namespace ZThread { namespace ZThread {
typedef struct atomic_count_t { typedef struct atomic_count_t {
CRITICAL_SECTION cs; CRITICAL_SECTION cs;
size_t count; size_t count;
atomic_count_t() : count(0) {} atomic_count_t() : count(0) {}
} ATOMIC_COUNT; } ATOMIC_COUNT;
AtomicCount::AtomicCount() { AtomicCount::AtomicCount() {
@@ -42,13 +42,13 @@ AtomicCount::AtomicCount() {
ATOMIC_COUNT* c = new ATOMIC_COUNT; ATOMIC_COUNT* c = new ATOMIC_COUNT;
_value = reinterpret_cast<void*>(c); _value = reinterpret_cast<void*>(c);
::InitializeCriticalSection(&c->cs); ::InitializeCriticalSection(&c->cs);
} }
AtomicCount::~AtomicCount() { AtomicCount::~AtomicCount() {
ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value); ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
assert(c->count == 0); assert(c->count == 0);
::DeleteCriticalSection(&c->cs); ::DeleteCriticalSection(&c->cs);
delete c; delete c;
@@ -58,8 +58,8 @@ AtomicCount::~AtomicCount() {
size_t AtomicCount::operator--(int) { size_t AtomicCount::operator--(int) {
ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value); ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
size_t value; size_t value;
::EnterCriticalSection(&c->cs); ::EnterCriticalSection(&c->cs);
value = c->count--; value = c->count--;
::LeaveCriticalSection(&c->cs); ::LeaveCriticalSection(&c->cs);
@@ -67,13 +67,13 @@ size_t AtomicCount::operator--(int) {
return value; return value;
} }
//! Postfix increment and return the current value //! Postfix increment and return the current value
size_t AtomicCount::operator++(int) { size_t AtomicCount::operator++(int) {
ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value); ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
size_t value; size_t value;
::EnterCriticalSection(&c->cs); ::EnterCriticalSection(&c->cs);
value = c->count++; value = c->count++;
::LeaveCriticalSection(&c->cs); ::LeaveCriticalSection(&c->cs);
@@ -86,8 +86,8 @@ size_t AtomicCount::operator++(int) {
size_t AtomicCount::operator--() { size_t AtomicCount::operator--() {
ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value); ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
size_t value; size_t value;
::EnterCriticalSection(&c->cs); ::EnterCriticalSection(&c->cs);
value = --c->count; value = --c->count;
::LeaveCriticalSection(&c->cs); ::LeaveCriticalSection(&c->cs);
@@ -95,13 +95,13 @@ size_t AtomicCount::operator--() {
return value; return value;
} }
//! Prefix increment and return the current value //! Prefix increment and return the current value
size_t AtomicCount::operator++() { size_t AtomicCount::operator++() {
ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value); ATOMIC_COUNT* c = reinterpret_cast<ATOMIC_COUNT*>(_value);
size_t value; size_t value;
::EnterCriticalSection(&c->cs); ::EnterCriticalSection(&c->cs);
value = ++c->count; value = ++c->count;
::LeaveCriticalSection(&c->cs); ::LeaveCriticalSection(&c->cs);
@@ -108,7 +108,7 @@ struct TRINITY_DLL_DECL boss_sapphironAI : public ScriptedAI
m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
m_creature->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING + MOVEMENTFLAG_ONTRANSPORT); m_creature->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING + MOVEMENTFLAG_ONTRANSPORT);
m_creature->GetMotionMaster()->Clear(false); m_creature->GetMotionMaster()->Clear(false);
m_creature->GetMotionMaster()->MoveIdle(); m_creature->GetMotionMaster()->MoveIdle();
m_creature->SetHover(true); m_creature->SetHover(true);
Icebolt_Timer = 4000; Icebolt_Timer = 4000;
Icebolt_Count = 0; Icebolt_Count = 0;
@@ -132,16 +132,16 @@ struct TRINITY_DLL_DECL boss_sapphironAI : public ScriptedAI
}else Icebolt_Timer -= diff; }else Icebolt_Timer -= diff;
if(Icebolt_Count == 5 && IsInFly && FrostBreath_Timer < diff ) if(Icebolt_Count == 5 && IsInFly && FrostBreath_Timer < diff )
{ {
DoScriptText(EMOTE_BREATH, m_creature); DoScriptText(EMOTE_BREATH, m_creature);
DoCast(m_creature->getVictim(),SPELL_FROST_BREATH); DoCast(m_creature->getVictim(),SPELL_FROST_BREATH);
land_Timer = 2000; land_Timer = 2000;
IsInFly = false; IsInFly = false;
FrostBreath_Timer = 6000; FrostBreath_Timer = 6000;
}else FrostBreath_Timer -= diff; }else FrostBreath_Timer -= diff;
if(!IsInFly && land_Timer < diff) if(!IsInFly && land_Timer < diff)
{ {
phase = 1; phase = 1;
m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND); m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING + MOVEMENTFLAG_ONTRANSPORT); m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING + MOVEMENTFLAG_ONTRANSPORT);
@@ -147,7 +147,7 @@ struct TRINITY_DLL_DECL boss_kalecgosAI : public ScriptedAI
TalkSequence = 0; TalkSequence = 0;
isFriendly = false; isFriendly = false;
isEnraged = false; isEnraged = false;
isBanished = false; isBanished = false;
} }
void DamageTaken(Unit *done_by, uint32 &damage) void DamageTaken(Unit *done_by, uint32 &damage)
@@ -191,7 +191,7 @@ struct TRINITY_DLL_DECL boss_kalecgosAI : public ScriptedAI
switch(TalkSequence) switch(TalkSequence)
{ {
case 1: case 1:
m_creature->setFaction(35); m_creature->setFaction(35);
TalkTimer = 1000; TalkTimer = 1000;
break; break;
case 2: case 2:
@@ -276,7 +276,7 @@ struct TRINITY_DLL_DECL boss_sathrovarrAI : public ScriptedAI
CheckTimer = 1000; CheckTimer = 1000;
ResetThreat = 1000; ResetThreat = 1000;
isEnraged = false; isEnraged = false;
isBanished = false; isBanished = false;
} }
void Aggro(Unit* who) void Aggro(Unit* who)
@@ -339,7 +339,7 @@ struct TRINITY_DLL_DECL boss_sathrovarrAI : public ScriptedAI
if(Player* i_pl = i->getSource()) if(Player* i_pl = i->getSource())
if(i_pl->HasAura(AURA_SPECTRAL_REALM,0)) if(i_pl->HasAura(AURA_SPECTRAL_REALM,0))
i_pl->RemoveAurasDueToSpell(AURA_SPECTRAL_REALM); i_pl->RemoveAurasDueToSpell(AURA_SPECTRAL_REALM);
} }
void UpdateAI(const uint32 diff) void UpdateAI(const uint32 diff)
{ {
@@ -471,7 +471,7 @@ struct TRINITY_DLL_DECL boss_kalecAI : public ScriptedAI
void UpdateAI(const uint32 diff) void UpdateAI(const uint32 diff)
{ {
if (!UpdateVictim()) if (!UpdateVictim())
return; return;
if(YellTimer < diff) if(YellTimer < diff)
{ {
@@ -559,7 +559,7 @@ void boss_kalecgosAI::UpdateAI(const uint32 diff)
DoCast(m_creature, SPELL_ENRAGE, true); DoCast(m_creature, SPELL_ENRAGE, true);
isEnraged = true; isEnraged = true;
} }
if(!isBanished && (m_creature->GetHealth()*100)/m_creature->GetMaxHealth() < 1) if(!isBanished && (m_creature->GetHealth()*100)/m_creature->GetMaxHealth() < 1)
{ {
if(Unit *Sath = Unit::GetUnit(*m_creature, SathGUID)) if(Unit *Sath = Unit::GetUnit(*m_creature, SathGUID))
@@ -41,7 +41,7 @@ EndScriptData */
#define SPELL_FEAR 29321 #define SPELL_FEAR 29321
#define SPELL_VOID_BOLT 39329 #define SPELL_VOID_BOLT 39329
#define SPELL_SPOTLIGHT 25824 #define SPELL_SPOTLIGHT 25824
#define CENTER_X 432.909f #define CENTER_X 432.909f
#define CENTER_Y -373.424f #define CENTER_Y -373.424f
#define CENTER_Z 17.9608f #define CENTER_Z 17.9608f
@@ -100,7 +100,7 @@ struct TRINITY_DLL_DECL boss_high_astromancer_solarianAI : public ScriptedAI
float Portals[3][3]; float Portals[3][3];
bool AppearDelay; bool AppearDelay;
bool BlindingLight; bool BlindingLight;
void Reset() void Reset()
{ {
@@ -134,7 +134,7 @@ struct TRINITY_DLL_DECL boss_high_astromancer_solarianAI : public ScriptedAI
void StartEvent() void StartEvent()
{ {
DoScriptText(SAY_AGGRO, m_creature); DoScriptText(SAY_AGGRO, m_creature);
if(pInstance) if(pInstance)
pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, IN_PROGRESS); pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, IN_PROGRESS);
} }
@@ -171,7 +171,7 @@ struct TRINITY_DLL_DECL boss_high_astromancer_solarianAI : public ScriptedAI
{ {
if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0)) if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0))
Summoned->AI()->AttackStart(target); Summoned->AI()->AttackStart(target);
Summons.Summon(Summoned); Summons.Summon(Summoned);
} }
} }
@@ -215,7 +215,7 @@ struct TRINITY_DLL_DECL boss_high_astromancer_solarianAI : public ScriptedAI
} }
AppearDelay_Timer = 2000; AppearDelay_Timer = 2000;
}else AppearDelay_Timer -= diff; }else AppearDelay_Timer -= diff;
} }
if (Phase == 1) if (Phase == 1)
{ {
@@ -236,12 +236,12 @@ struct TRINITY_DLL_DECL boss_high_astromancer_solarianAI : public ScriptedAI
if(!m_creature->HasInArc(2.5f, target)) if(!m_creature->HasInArc(2.5f, target))
target = m_creature->getVictim(); target = m_creature->getVictim();
if(target) if(target)
DoCast(target, SPELL_ARCANE_MISSILES); DoCast(target, SPELL_ARCANE_MISSILES);
} }
ArcaneMissiles_Timer = 3000; ArcaneMissiles_Timer = 3000;
}else ArcaneMissiles_Timer -= diff; }else ArcaneMissiles_Timer -= diff;
if (MarkOfTheSolarian_Timer < diff) if (MarkOfTheSolarian_Timer < diff)
{ {
DoCast(m_creature->getVictim(), MARK_OF_SOLARIAN); DoCast(m_creature->getVictim(), MARK_OF_SOLARIAN);
+1 -1
View File
@@ -5680,7 +5680,7 @@ void Aura::PeriodicTick()
int32 gain = pCaster->ModifyPower(power,gain_amount); int32 gain = pCaster->ModifyPower(power,gain_amount);
m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto()); m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
} }
// Mark of Kaz'rogal // Mark of Kaz'rogal
if(GetId() == 31447 && m_target->GetPower(power) == 0) if(GetId() == 31447 && m_target->GetPower(power) == 0)
{ {
+3 -3
View File
@@ -653,7 +653,7 @@ void Spell::EffectDummy(uint32 i)
if(ihit->effectMask & (1<<i)) if(ihit->effectMask & (1<<i))
{ {
Unit* casttarget = Unit::GetUnit((*unitTarget), ihit->targetGUID); Unit* casttarget = Unit::GetUnit((*unitTarget), ihit->targetGUID);
if(casttarget) if(casttarget)
m_caster->DealDamage(casttarget, damage, NULL, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_ARCANE, spellInfo, false); m_caster->DealDamage(casttarget, damage, NULL, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_ARCANE, spellInfo, false);
} }
} }
@@ -4978,7 +4978,7 @@ void Spell::EffectScriptEffect(uint32 effIndex)
} }
case 48025: // Headless Horseman's Mount case 48025: // Headless Horseman's Mount
{ {
if(!unitTarget) if(!unitTarget)
return; return;
if(unitTarget) if(unitTarget)
@@ -4987,7 +4987,7 @@ void Spell::EffectScriptEffect(uint32 effIndex)
{ {
case 75: unitTarget->CastSpell(unitTarget, 51621, true); break;; case 75: unitTarget->CastSpell(unitTarget, 51621, true); break;;
case 150: unitTarget->CastSpell(unitTarget, 48024, true); break; case 150: unitTarget->CastSpell(unitTarget, 48024, true); break;
case 225: unitTarget->CastSpell(unitTarget, 51617, true); break; case 225: unitTarget->CastSpell(unitTarget, 51617, true); break;
case 300: unitTarget->CastSpell(unitTarget, 48023, true); break; case 300: unitTarget->CastSpell(unitTarget, 48023, true); break;
default: break; default: break;
} }