aboutsummaryrefslogtreecommitdiff
path: root/dep/src/zthread/ThreadImpl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'dep/src/zthread/ThreadImpl.cxx')
-rw-r--r--dep/src/zthread/ThreadImpl.cxx282
1 files changed, 141 insertions, 141 deletions
diff --git a/dep/src/zthread/ThreadImpl.cxx b/dep/src/zthread/ThreadImpl.cxx
index c7c22883b5e..fa2fd9e36c5 100644
--- a/dep/src/zthread/ThreadImpl.cxx
+++ b/dep/src/zthread/ThreadImpl.cxx
@@ -34,88 +34,88 @@ namespace ZThread {
TSS<ThreadImpl*> ThreadImpl::_threadMap;
namespace {
-
+
class Launcher : public Runnable {
-
+
ThreadImpl* x;
ThreadImpl* y;
Task z;
-
+
public:
-
+
Launcher(ThreadImpl* a, ThreadImpl* b, const Task& c) : x(a), y(b), z(c) {}
-
- void run() {
- y->dispatch(x,y,z);
+
+ void run() {
+ y->dispatch(x,y,z);
}
-
+
};
-
+
}
- ThreadImpl::ThreadImpl()
+ ThreadImpl::ThreadImpl()
: _state(State::REFERENCE), _priority(Medium), _autoCancel(false) {
-
+
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) {
-
+
ZTDEBUG("User thread created.\n");
start(task);
}
-
-
+
+
ThreadImpl::~ThreadImpl() {
-
+
_tls.clear();
if(isActive()) {
-
+
ZTDEBUG("You are destroying an executing thread!\n");
abort();
-
+
}
-
+
ZTDEBUG("Thread destroyed.\n");
-
+
}
-
+
Monitor& ThreadImpl::getMonitor() {
return _monitor;
}
-
+
void ThreadImpl::cancel(bool autoCancel) {
- if(!autoCancel || _autoCancel)
- _monitor.cancel();
+ if(!autoCancel || _autoCancel)
+ _monitor.cancel();
}
-
- bool ThreadImpl::interrupt() {
- return _monitor.interrupt();
+
+ bool ThreadImpl::interrupt() {
+ return _monitor.interrupt();
}
-
+
bool ThreadImpl::isInterrupted() {
return _monitor.isInterrupted();
}
-
+
bool ThreadImpl::isCanceled() {
return _monitor.isCanceled();
}
Priority ThreadImpl::getPriority() const {
- return _priority;
+ return _priority;
}
-
-
+
+
bool ThreadImpl::isReference() {
return _state.isReference();
}
-
+
/**
* Join the thread, blocking the caller until it is interrupted or until
* the thread represented by this object exits.
@@ -124,27 +124,27 @@ namespace ZThread {
* joined.
*/
bool ThreadImpl::join(unsigned long timeout) {
-
+
// Serial access to this ThreadImpl's state
Guard<Monitor> g1(_monitor);
-
+
// Make sure a thread is not trying to join() itself.
if(ThreadOps::isCurrent(this))
throw Deadlock_Exception("Cannot join self.");
-
- // Reference threads can't be joined.
+
+ // Reference threads can't be joined.
if(_state.isReference())
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(!_state.isJoined()) {
-
+
// Add the current thread to the joiner list
ThreadImpl* impl = current();
_joiners.push_back(impl);
@@ -153,49 +153,49 @@ namespace ZThread {
{ // Release this ThreadImpl's lock while the joiner sleeps
- _monitor.release();
+ _monitor.release();
Guard<Monitor> g3(impl->getMonitor());
-
+
result = impl->_monitor.wait(timeout);
-
+
_monitor.acquire();
-
+
}
-
+
// Update the joiner list
List::iterator i = std::find(_joiners.begin(), _joiners.end(), impl);
if(i != _joiners.end())
_joiners.erase(i);
-
-
+
+
switch(result) {
-
+
case Monitor::TIMEDOUT:
return false;
-
+
case Monitor::INTERRUPTED:
throw Interrupted_Exception();
-
+
default:
break;
-
+
}
-
+
}
return true;
-
+
}
-
+
/**
* Translate the priority into a pthread value, and update the thread priority.
*
- * This is not available on all platforms, and probably works differently
- * the platforms that do support it. Pthreads does not have very portable
+ * This is not available on all platforms, and probably works differently
+ * the platforms that do support it. Pthreads does not have very portable
* priority support as far I am aware.
*
- * If SCHED_OTHER is not supported priority values are still set but
+ * If SCHED_OTHER is not supported priority values are still set but
* dont not actually in affect anything.
*
* @param prio PRIORITY value
@@ -204,18 +204,18 @@ namespace ZThread {
* @exception InvalidOp_Exception thrown by IDLE, JOINING or JOINED threads.
*/
void ThreadImpl::setPriority(Priority p) {
-
+
Guard<Monitor> g(_monitor);
-
+
// Only set the native priority when the thread is running
if(_state.isRunning())
ThreadOps::setPriority(this, p);
-
+
_priority = p;
-
+
}
-
-
+
+
/**
* Test the state Monitor of this thread to determine if the thread
* is an active thread created by zthreads.
@@ -223,13 +223,13 @@ namespace ZThread {
* @return bool indicating the activity of the thread.
*/
bool ThreadImpl::isActive() {
-
+
Guard<Monitor> g(_monitor);
return _state.isRunning();
-
+
}
-
-
+
+
/**
* Get a reference to an implmenetation that maps to the current thread.
* Accomplished by checking the TLS map. This will always return a valid
@@ -237,98 +237,98 @@ namespace ZThread {
*
* @return ThreadImpl* current implementation that maps to the
* executing thread.
- */
+ */
ThreadImpl* ThreadImpl::current() {
-
+
// Get the ThreadImpl previously mapped onto the executing thread.
ThreadImpl* impl = _threadMap.get();
-
+
// Create a reference thread for any threads that have been 'discovered'
// because they are not created by ZThreads.
- if(impl == 0) {
-
- // Create a ThreadImpl to represent this thread.
+ if(impl == 0) {
+
+ // Create a ThreadImpl to represent this thread.
impl = new ThreadImpl();
impl->_state.setReference();
-
+
ThreadOps::activate(impl);
-
+
// Map a reference thread and insert it into the queue
_threadMap.set(impl);
-
+
ThreadQueue::instance()->insertReferenceThread(impl);
-
+
}
-
+
assert(impl != 0);
return impl;
-
+
}
-
+
/**
* Make current thread sleep for the given number of milliseconds.
* This sleep can be interrupt()ed.
- *
+ *
* @param ms timeout for the sleep.
*
* @post the calling thread is blocked by waiting on the internal condition
* variable. This can be signaled in the monitor of an interrupt
*/
void ThreadImpl::sleep(unsigned long ms) {
-
+
// Make sleep()ing for 0 milliseconds equivalent to a yield.
if(ms == 0) {
-
+
yield();
return;
-
+
}
-
+
// Get the monitor for the current thread
Monitor& monitor = current()->getMonitor();
-
+
// Acquire that threads Monitor with a Guard
Guard<Monitor> g(monitor);
-
+
for(;;) {
-
+
switch(monitor.wait(ms)) {
-
+
case Monitor::INTERRUPTED:
throw Interrupted_Exception();
-
+
default:
return;
-
+
}
-
+
}
-
+
}
-
-
+
+
/**
- * Yield the current timeslice to another thread.
- * If sched_yield() is available it is used.
+ * Yield the current timeslice to another thread.
+ * If sched_yield() is available it is used.
* Otherwise, the state Monitor for this thread is used to simiulate a
- * yield by blocking for 1 millisecond, which should give the
+ * yield by blocking for 1 millisecond, which should give the
* scheduler a chance to schedule another thread.
*/
void ThreadImpl::yield() {
-
- // Try to yield with the native operation. If it fails, then
+
+ // Try to yield with the native operation. If it fails, then
// simulate with a short wait() on the monitor.
if(!ThreadOps::yield()) {
-
+
// Get the monitor for the current thread
Monitor& monitor = current()->getMonitor();
-
+
// Attempt a wait().
- Guard<Monitor> g(monitor);
+ Guard<Monitor> g(monitor);
monitor.wait(1);
-
+
}
-
+
}
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.
if(!_state.isIdle())
throw InvalidOp_Exception("Thread is not idle.");
-
+
_state.setRunning();
-
+
// Spawn a new thread, blocking the parent (current) thread until
// the child starts.
@@ -353,14 +353,14 @@ namespace ZThread {
if(!spawn(&launch)) {
// Return to the idle state & report the error if it doesn't work out.
- _state.setIdle();
- throw Synchronization_Exception();
+ _state.setIdle();
+ throw Synchronization_Exception();
}
// Wait, uninterruptably, for the child's signal. The parent thread
- // still can be interrupted and killed; it just won't take effect
+ // still can be interrupted and killed; it just won't take effect
// until the child has started.
Guard<Monitor, DeferredInterruptionScope> g3(parent->_monitor);
@@ -368,7 +368,7 @@ namespace ZThread {
if(parent->_monitor.wait() != Monitor::SIGNALED) {
assert(0);
}
-
+
}
@@ -378,23 +378,23 @@ namespace ZThread {
// Map the implementation object onto the running thread.
_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)
impl->addReference();
// Update the priority of the thread
- if(parent->_state.isReference())
- ThreadOps::setPriority(impl,
+ if(parent->_state.isReference())
+ ThreadOps::setPriority(impl,
parent->_state.isReference() ? impl->_priority : parent->_priority);
// Inherit ThreadLocal values from the parent
typedef ThreadLocalMap::const_iterator It;
- for(It i = parent->getThreadLocalMap().begin(); i != parent->getThreadLocalMap().end(); ++i)
+ for(It i = parent->getThreadLocalMap().begin(); i != parent->getThreadLocalMap().end(); ++i)
if( (i->second)->isInheritable() )
impl->getThreadLocalMap()[ i->first ] = (i->second)->clone();
-
- // Insert a user-thread mapping
+
+ // Insert a user-thread mapping
ThreadQueue::instance()->insertUserThread(impl);
// Wake the parent once the thread is setup
parent->_monitor.notify();
@@ -403,65 +403,65 @@ namespace ZThread {
// not catch exceptions, let program terminate
//try {
-
+
task->run();
//} catch(...) {
// Result of running a task that threw an exception.
// ZTDEBUG("The task has thrown an unhandled exception\n");
- //assert(0); // UQ1: Go to debugger...
-
+ //assert(0); // UQ1: Go to debugger...
+
//}
- ZTDEBUG("Thread joining...\n");
-
+ ZTDEBUG("Thread joining...\n");
+
{ // Update the state of the thread
-
+
Guard<Monitor> g(impl->_monitor);
impl->_state.setJoined();
-
+
// Wake the joiners that will be easy to join first
for(List::iterator i = impl->_joiners.begin(); i != impl->_joiners.end();) {
-
+
ThreadImpl* joiner = *i;
Monitor& m = joiner->getMonitor();
if(m.tryAcquire()) {
-
+
m.notify();
- m.release();
-
+ m.release();
+
i = impl->_joiners.erase(i);
} else
++i;
- }
+ }
// Wake the joiners that might take a while next
for(List::iterator i = impl->_joiners.begin(); i != impl->_joiners.end(); ++i) {
-
+
ThreadImpl* joiner = *i;
Monitor& m = joiner->getMonitor();
m.acquire();
m.notify();
- m.release();
-
+ 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);
// Cleanup ThreadLocal values
impl->getThreadLocalMap().clear();
- // Update the reference count allowing it to be destroyed
+ // Update the reference count allowing it to be destroyed
impl->delReference();
}