예제 #1
0
void
ArchMultithreadPosix::refThread(ArchThreadImpl* thread)
{
	assert(thread != NULL);
	assert(findNoRef(thread->m_thread) != NULL);
	++thread->m_refCount;
}
HANDLE
ArchMultithreadWindows::getCancelEventForCurrentThread()
{
    lockMutex(m_threadMutex);
    ArchThreadImpl* thread = findNoRef(GetCurrentThreadId());
    unlockMutex(m_threadMutex);
    return thread->m_cancel;
}
void
ArchMultithreadWindows::setNetworkDataForCurrentThread(void* data)
{
    lockMutex(m_threadMutex);
    ArchThreadImpl* thread = findNoRef(GetCurrentThreadId());
    thread->m_networkData = data;
    unlockMutex(m_threadMutex);
}
ArchThreadImpl*
ArchMultithreadWindows::find(DWORD id)
{
    ArchThreadImpl* impl = findNoRef(id);
    if (impl != NULL) {
        refThread(impl);
    }
    return impl;
}
예제 #5
0
ArchThreadImpl*
ArchMultithreadPosix::find(pthread_t thread)
{
	ArchThreadImpl* impl = findNoRef(thread);
	if (impl != NULL) {
		refThread(impl);
	}
	return impl;
}
예제 #6
0
bool
ArchMultithreadPosix::wait(ArchThread target, double timeout)
{
	assert(target != NULL);

	lockMutex(m_threadMutex);

	// find current thread
	ArchThreadImpl* self = findNoRef(pthread_self());

	// ignore wait if trying to wait on ourself
	if (target == self) {
		unlockMutex(m_threadMutex);
		return false;
	}

	// ref the target so it can't go away while we're watching it
	refThread(target);

	unlockMutex(m_threadMutex);

	try {
		// do first test regardless of timeout
		testCancelThreadImpl(self);
		if (isExitedThread(target)) {
			closeThread(target);
			return true;
		}

		// wait and repeat test if there's a timeout
		if (timeout != 0.0) {
			const double start = ARCH->time();
			do {
				// wait a little
				ARCH->sleep(0.05);

				// repeat test
				testCancelThreadImpl(self);
				if (isExitedThread(target)) {
					closeThread(target);
					return true;
				}

				// repeat wait and test until timed out
			} while (timeout < 0.0 || (ARCH->time() - start) <= timeout);
		}

		closeThread(target);
		return false;
	}
	catch (...) {
		closeThread(target);
		throw;
	}
}
void
ArchMultithreadWindows::testCancelThread()
{
    // find current thread
    lockMutex(m_threadMutex);
    ArchThreadImpl* thread = findNoRef(GetCurrentThreadId());
    unlockMutex(m_threadMutex);

    // test cancel on thread
    testCancelThreadImpl(thread);
}
예제 #8
0
void
ArchMultithreadPosix::testCancelThread()
{
	// find current thread
	lockMutex(m_threadMutex);
	ArchThreadImpl* thread = findNoRef(pthread_self());
	unlockMutex(m_threadMutex);

	// test cancel on thread
	testCancelThreadImpl(thread);
}
예제 #9
0
void
ArchMultithreadPosix::insert(ArchThreadImpl* thread)
{
	assert(thread != NULL);

	// thread shouldn't already be on the list
	assert(findNoRef(thread->m_thread) == NULL);

	// set thread id.  note that we don't worry about m_nextID
	// wrapping back to 0 and duplicating thread ID's since the
	// likelihood of synergy running that long is vanishingly
	// small.
	thread->m_id = ++m_nextID;

	// append to list
	m_threadList.push_back(thread);
}
예제 #10
0
void
ArchMultithreadPosix::closeThread(ArchThread thread)
{
	assert(thread != NULL);

	// decrement ref count and clean up thread if no more references
	if (--thread->m_refCount == 0) {
		// detach from thread (unless it's the main thread)
		if (thread->m_func != NULL) {
			pthread_detach(thread->m_thread);
		}

		// remove thread from list
		lockMutex(m_threadMutex);
		assert(findNoRef(thread->m_thread) == thread);
		erase(thread);
		unlockMutex(m_threadMutex);

		// done with thread
		delete thread;
	}
}
bool
ArchMultithreadWindows::wait(ArchThread target, double timeout)
{
    assert(target != NULL);

    lockMutex(m_threadMutex);

    // find current thread
    ArchThreadImpl* self = findNoRef(GetCurrentThreadId());

    // ignore wait if trying to wait on ourself
    if (target == self) {
        unlockMutex(m_threadMutex);
        return false;
    }

    // ref the target so it can't go away while we're watching it
    refThread(target);

    unlockMutex(m_threadMutex);

    // convert timeout
    DWORD t;
    if (timeout < 0.0) {
        t = INFINITE;
    }
    else {
        t = (DWORD)(1000.0 * timeout);
    }

    // wait for this thread to be cancelled or woken up or for the
    // target thread to terminate.
    HANDLE handles[2];
    handles[0] = target->m_exit;
    handles[1] = self->m_cancel;
    DWORD result = WaitForMultipleObjects(2, handles, FALSE, t);

    // cancel takes priority
    if (result != WAIT_OBJECT_0 + 1 &&
        WaitForSingleObject(handles[1], 0) == WAIT_OBJECT_0) {
        result = WAIT_OBJECT_0 + 1;
    }

    // release target
    closeThread(target);

    // handle result
    switch (result) {
    case WAIT_OBJECT_0 + 0:
        // target thread terminated
        return true;

    case WAIT_OBJECT_0 + 1:
        // this thread was cancelled.  does not return.
        testCancelThreadImpl(self);

    default:
        // timeout or error
        return false;
    }
}