Add AIThreadID - Cleanup of apr_os_thread* related code.

Apart from just really cleaning things up and moving
everything into one class regarding thread IDs (ie,
is_main_thread(), comparing ID's etc), this also
fixes an obscure bug where LL was casting thread ID's
to U32 and then compared those to find out if it
the same thread. It's theoretically possible that
such fails on a 64bit OS.

By generalizing the interface, I adopted the use
of a thread-local cache for the current thread ID
as used by LLMutex et al, so now all code benefits
from that. The idea was even extended to now also
be used for is_main_thread() tests and even resetting
a thread ID to the ID of the current thread.
This commit is contained in:
Aleric Inglewood
2012-08-09 06:30:31 +02:00
parent f94f458922
commit 37c8ea54eb
13 changed files with 246 additions and 110 deletions

View File

@@ -206,7 +206,7 @@ void AIStateMachine::locked_cont(void)
// Atomic test mActive and change mIdle.
mIdleActive.lock();
#ifdef SHOW_ASSERT
mContThread = apr_os_thread_current();
mContThread.reset();
#endif
mIdle = false;
bool not_active = mActive == as_idle;
@@ -253,7 +253,7 @@ void AIStateMachine::set_state(state_type state)
mSetStateLock.lock();
// Do not call set_state() unless running.
llassert(mState == bs_run || !LLThread::is_main_thread());
llassert(mState == bs_run || !is_main_thread());
// If this function is called from another thread than the main thread, then we have to ignore
// it if we're not idle and the state is less than the current state. The main thread must
@@ -279,12 +279,12 @@ void AIStateMachine::set_state(state_type state)
// state is less than the current state, ignore it.
// Also, if abort() or finish() was called, then we should just ignore it.
if (mState != bs_run ||
(!mIdle && state <= mRunState && !LLThread::is_main_thread()))
(!mIdle && state <= mRunState && !AIThreadID::in_main_thread()))
{
#ifdef SHOW_ASSERT
// It's a bit weird if the same thread does two calls on a row where the second call
// has a smaller value: warn about that.
if (mState == bs_run && mContThread == apr_os_thread_current())
if (mState == bs_run && mContThread.equals_current_thread())
{
llwarns << "Ignoring call to set_state(" << state_str(state) <<
") by non-main thread before main-thread could react on previous call, "
@@ -296,7 +296,7 @@ void AIStateMachine::set_state(state_type state)
}
// Do not call idle() when set_state is called from another thread; use idle(state_type) instead.
llassert(!mCalledThreadUnsafeIdle || LLThread::is_main_thread());
llassert(!mCalledThreadUnsafeIdle || is_main_thread());
// Change mRunState to the requested value.
if (mRunState != state)

View File

@@ -208,7 +208,7 @@ class AIStateMachine {
S64 mSleep; //!< Non-zero while the state machine is sleeping.
LLMutex mIdleActive; //!< Used for atomic operations on the pair mIdle / mActive.
#ifdef SHOW_ASSERT
apr_os_thread_t mContThread; //!< Thread that last called locked_cont().
AIThreadID mContThread; //!< Thread that last called locked_cont().
bool mCalledThreadUnsafeIdle; //!< Set to true when idle() is called.
#endif
@@ -242,7 +242,7 @@ class AIStateMachine {
//! Create a non-running state machine.
AIStateMachine(void) : mState(bs_initialize), mIdle(true), mAborted(true), mActive(as_idle), mSleep(0), mParent(NULL), mCallback(NULL)
#ifdef SHOW_ASSERT
, mContThread(0), mCalledThreadUnsafeIdle(false)
, mContThread(AIThreadID::none), mCalledThreadUnsafeIdle(false)
#endif
{ updateSettings(); }
@@ -269,7 +269,7 @@ class AIStateMachine {
mSetStateLock.lock();
// Ignore calls to cont() if the statemachine isn't idle. See comments in set_state().
// Calling cont() twice or after calling set_state(), without first calling idle(), is an error.
if (mState != bs_run || !mIdle) { llassert(mState != bs_run || mContThread != apr_os_thread_current()); mSetStateLock.unlock(); return; }
if (mState != bs_run || !mIdle) { llassert(mState != bs_run || !mContThread.equals_current_thread()); mSetStateLock.unlock(); return; }
locked_cont();
}
private: