diff --git a/indra/cwdebug/debug.h b/indra/cwdebug/debug.h index 4161e18f7..b704c811d 100644 --- a/indra/cwdebug/debug.h +++ b/indra/cwdebug/debug.h @@ -49,6 +49,7 @@ #else // LL_COMMON_LINK_SHARED #error LL_COMMON_LINK_SHARED not defined #endif // LL_COMMON_LINK_SHARED +#include "aithreadid.h" // If CWDEBUG is not defined, but DEBUG_CURLIO is, then replace // some of the cwd macro's with something that generates viewer @@ -104,23 +105,23 @@ struct fake_channel { void on() const { } void off() const { } }; -extern CWD_API fake_channel const warning; -extern CWD_API fake_channel const curl; -extern CWD_API fake_channel const curlio; -extern CWD_API fake_channel const statemachine; -extern CWD_API fake_channel const notice; +extern LL_COMMON_API fake_channel const warning; +extern LL_COMMON_API fake_channel const curl; +extern LL_COMMON_API fake_channel const curlio; +extern LL_COMMON_API fake_channel const statemachine; +extern LL_COMMON_API fake_channel const notice; } // namespace dc } // namespace debug #define Debug(x) do { using namespace debug; x; } while(0) -#define Dout(a, b) do { using namespace debug; if ((a).mOn) { llinfos_nf << (a).mLabel << ": " << Indent::print << b << llendl; } } while(0) +#define Dout(a, b) do { using namespace debug; if ((a).mOn) { llinfos_nf << AIThreadID::DoutPrint << (a).mLabel << ": " << Indent::print << b << llendl; } } while(0) #define DoutEntering(a, b) \ int __slviewer_debug_indentation = 2; \ { \ using namespace debug; \ if ((a).mOn) \ - llinfos_nf << (a).mLabel << ": " << Indent::print << "Entering " << b << llendl; \ + llinfos_nf << AIThreadID::DoutPrint << (a).mLabel << ": " << Indent::print << "Entering " << b << llendl; \ else \ __slviewer_debug_indentation = 0; \ } \ diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 4be690734..cf1e564ae 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -15,8 +15,9 @@ include_directories( ) set(llcommon_SOURCE_FILES - aiframetimer.cpp - imageids.cpp + aiframetimer.cpp + aithreadid.cpp + imageids.cpp indra_constants.cpp llallocator.cpp llallocator_heap_profile.cpp @@ -24,7 +25,7 @@ set(llcommon_SOURCE_FILES llapr.cpp llaprpool.cpp llassettype.cpp - llavatarname.cpp + llavatarname.cpp llbase32.cpp llbase64.cpp llcommon.cpp @@ -103,6 +104,7 @@ set(llcommon_HEADER_FILES CMakeLists.txt aiframetimer.h + aithreadid.h aithreadsafe.h bitpack.h ctype_workaround.h diff --git a/indra/llcommon/aithreadid.cpp b/indra/llcommon/aithreadid.cpp new file mode 100644 index 000000000..dfb4a2660 --- /dev/null +++ b/indra/llcommon/aithreadid.cpp @@ -0,0 +1,70 @@ +/** + * @file aithreadid.cpp + * + * Copyright (c) 2012, Aleric Inglewood. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution. + * + * CHANGELOG + * and additional copyright holders. + * + * 08/08/2012 + * - Initial version, written by Aleric Inglewood @ SL + */ + +#include "sys.h" +#include +#include +#include "aithreadid.h" + +AIThreadID const AIThreadID::sNone(AIThreadID::none); +apr_os_thread_t AIThreadID::sMainThreadID; +#ifndef LL_DARWIN +apr_os_thread_t ll_thread_local AIThreadID::lCurrentThread = AIThreadID::undefinedID; +#endif + +void AIThreadID::set_main_thread_id(void) +{ + sMainThreadID = apr_os_thread_current(); +} + +void AIThreadID::set_current_thread_id(void) +{ +#ifndef LL_DARWIN + lCurrentThread = apr_os_thread_current(); +#endif +} + +std::ostream& operator<<(std::ostream& os, AIThreadID const& id) +{ + return os << id.mID; +} + +std::ostream& operator<<(std::ostream& os, AIThreadID::dout_print_t) +{ + if (!AIThreadID::in_main_thread()) + { +#ifdef LL_DARWIN + os << std::hex << (size_t)apr_os_thread_current() << std::dec << ' '; +#else + os << std::hex << (size_t)AIThreadID::lCurrentThread << std::dec << ' '; +#endif + } + return os; +} + diff --git a/indra/llcommon/aithreadid.h b/indra/llcommon/aithreadid.h new file mode 100644 index 000000000..c565b5913 --- /dev/null +++ b/indra/llcommon/aithreadid.h @@ -0,0 +1,91 @@ +/** + * @file aithreadid.h + * @brief Declaration of AIThreadID. + * + * Copyright (c) 2012, Aleric Inglewood. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution. + * + * CHANGELOG + * and additional copyright holders. + * + * 08/08/2012 + * Initial version, written by Aleric Inglewood @ SL + */ + +#ifndef AI_THREAD_ID +#define AI_THREAD_ID + +#include // apr_os_thread_t, apr_os_thread_current(), apr_os_thread_equal(). +#include // std::ostream. +#include "llpreprocessor.h" // LL_COMMON_API +#include "llerror.h" + +#if LL_WINDOWS +#define ll_thread_local __declspec(thread) +#else +#define ll_thread_local __thread +#endif + +// Lightweight wrapper around apr_os_thread_t. +// This class introduces no extra assembly code after optimization; it's only intend is to provide type-safety. +class LL_COMMON_API AIThreadID +{ +private: + apr_os_thread_t mID; + static apr_os_thread_t sMainThreadID; + static apr_os_thread_t const undefinedID = (apr_os_thread_t)-1; +#ifndef LL_DARWIN + static ll_thread_local apr_os_thread_t lCurrentThread; +#endif +public: + static AIThreadID const sNone; + enum undefined_thread_t { none }; + enum dout_print_t { DoutPrint }; + +public: + AIThreadID(void) : mID(apr_os_thread_current()) { } + explicit AIThreadID(undefined_thread_t) : mID(undefinedID) { } // Used for sNone. + AIThreadID(AIThreadID const& id) : mID(id.mID) { } + AIThreadID& operator=(AIThreadID const& id) { mID = id.mID; return *this; } + bool is_main_thread(void) const { return apr_os_thread_equal(mID, sMainThreadID); } + bool is_no_thread(void) const { return apr_os_thread_equal(mID, sNone.mID); } + friend LL_COMMON_API bool operator==(AIThreadID const& id1, AIThreadID const& id2) { return apr_os_thread_equal(id1.mID, id2.mID); } + friend LL_COMMON_API bool operator!=(AIThreadID const& id1, AIThreadID const& id2) { return !apr_os_thread_equal(id1.mID, id2.mID); } + friend LL_COMMON_API std::ostream& operator<<(std::ostream& os, AIThreadID const& id); + friend LL_COMMON_API std::ostream& operator<<(std::ostream& os, dout_print_t); + static void set_main_thread_id(void); // Called once to set sMainThreadID. + static void set_current_thread_id(void); // Called once for every thread to set lCurrentThread. +#ifdef LL_DARWIN + void reset(void) { mID = apr_os_thread_current(); } + bool equals_current_thread(void) const { return apr_os_thread_equal(mID, apr_os_thread_current()); } + static bool in_main_thread(void) { return apr_os_thread_equal(apr_os_thread_current(), sMainThreadID); } +#else + void reset(void) { mID = lCurrentThread; } + bool equals_current_thread(void) const { return apr_os_thread_equal(mID, lCurrentThread); } + static bool in_main_thread(void) { return apr_os_thread_equal(lCurrentThread, sMainThreadID); } +#endif +}; + +// Legacy function. +inline bool is_main_thread(void) +{ + return AIThreadID::in_main_thread(); +} + +#endif // AI_THREAD_ID diff --git a/indra/llcommon/aithreadsafe.h b/indra/llcommon/aithreadsafe.h index b7d0045cb..02bfa8cd7 100644 --- a/indra/llcommon/aithreadsafe.h +++ b/indra/llcommon/aithreadsafe.h @@ -673,18 +673,18 @@ protected: #ifdef LL_DEBUG mutable bool mAccessed; - mutable apr_os_thread_t mTheadID; + mutable AIThreadID mTheadID; void accessed(void) const { if (!mAccessed) { mAccessed = true; - mTheadID = apr_os_thread_current(); + mTheadID.reset(); } else { - llassert_always(apr_os_thread_equal(mTheadID, apr_os_thread_current())); + llassert_always(mTheadID.equals_current_thread()); } } #endif diff --git a/indra/llcommon/llaprpool.cpp b/indra/llcommon/llaprpool.cpp index 3559ff430..de5761157 100644 --- a/indra/llcommon/llaprpool.cpp +++ b/indra/llcommon/llaprpool.cpp @@ -60,10 +60,10 @@ void LLAPRPool::create(LLAPRPool& parent) // // In other words, it's safe for any thread to create a (sub)pool, independent of who // owns the parent pool. - mOwner = apr_os_thread_current(); + mOwner.reset(); #else mOwner = mParent->mOwner; - llassert(apr_os_thread_equal(mOwner, apr_os_thread_current())); + llassert(mOwner.equals_current_thread()); #endif apr_status_t const apr_pool_create_status = apr_pool_create(&mPool, mParent->mPool); llassert_always(apr_pool_create_status == APR_SUCCESS); @@ -83,7 +83,7 @@ void LLAPRPool::destroy(void) // of course. Otherwise, if we are a subpool, only the thread that owns // the parent may destruct us, since that is the pool that is still alive, // possibly being used by others and being altered here. - llassert(!mParent || apr_os_thread_equal(mParent->mOwner, apr_os_thread_current())); + llassert(!mParent || mParent->mOwner.equals_current_thread()); #endif apr_pool_t* pool = mPool; mPool = NULL; // Mark that we are BEING destructed. diff --git a/indra/llcommon/llaprpool.h b/indra/llcommon/llaprpool.h index dc123e942..4c9f36893 100644 --- a/indra/llcommon/llaprpool.h +++ b/indra/llcommon/llaprpool.h @@ -62,22 +62,22 @@ class LL_COMMON_API LLAPRPool protected: apr_pool_t* mPool; //!< Pointer to the underlaying pool. NULL if not initialized. LLAPRPool* mParent; //!< Pointer to the parent pool, if any. Only valid when mPool is non-zero. - apr_os_thread_t mOwner; //!< The thread that owns this memory pool. Only valid when mPool is non-zero. + AIThreadID mOwner; //!< The thread that owns this memory pool. Only valid when mPool is non-zero. public: //! Construct an uninitialized (destructed) pool. - LLAPRPool(void) : mPool(NULL) { } + LLAPRPool(void) : mPool(NULL), mOwner(AIThreadID::none) { } //! Construct a subpool from an existing pool. // This is not a copy-constructor, this class doesn't have one! - LLAPRPool(LLAPRPool& parent) : mPool(NULL) { create(parent); } + LLAPRPool(LLAPRPool& parent) : mPool(NULL), mOwner(AIThreadID::none) { create(parent); } //! Destruct the memory pool (free all of it's subpools and allocated memory). ~LLAPRPool() { destroy(); } protected: // Create a pool that is allocated from the Operating System. Only used by LLAPRRootPool. - LLAPRPool(int) : mPool(NULL), mParent(NULL), mOwner(apr_os_thread_current()) + LLAPRPool(int) : mPool(NULL), mParent(NULL) { apr_status_t const apr_pool_create_status = apr_pool_create(&mPool, NULL); llassert_always(apr_pool_create_status == APR_SUCCESS); @@ -104,7 +104,7 @@ public: apr_pool_t* operator()(void) const { llassert(mPool); - llassert(apr_os_thread_equal(mOwner, apr_os_thread_current())); + llassert(mOwner.equals_current_thread()); return mPool; } @@ -112,7 +112,7 @@ public: void clear(void) { llassert(mPool); - llassert(apr_os_thread_equal(mOwner, apr_os_thread_current())); + llassert(mOwner.equals_current_thread()); apr_pool_clear(mPool); } @@ -124,13 +124,13 @@ public: void* palloc(size_t size) { llassert(mPool); - llassert(apr_os_thread_equal(mOwner, apr_os_thread_current())); + llassert(mOwner.equals_current_thread()); return apr_palloc(mPool, size); } void* pcalloc(size_t size) { llassert(mPool); - llassert(apr_os_thread_equal(mOwner, apr_os_thread_current())); + llassert(mOwner.equals_current_thread()); return apr_pcalloc(mPool, size); } #endif diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index d0279f866..c4865e947 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -308,8 +308,4 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; Such computation is done iff the message will be logged. */ -#ifdef SHOW_ASSERT -extern LL_COMMON_API bool is_main_thread(); -#endif - #endif // LL_LLERROR_H diff --git a/indra/llcommon/llframetimer.h b/indra/llcommon/llframetimer.h index bae3e5615..2bb1943c8 100644 --- a/indra/llcommon/llframetimer.h +++ b/indra/llcommon/llframetimer.h @@ -44,6 +44,9 @@ #include "lltimer.h" #include "timing.h" #include +#ifdef SHOW_ASSERT +#include "aithreadid.h" // is_main_thread() +#endif class LL_COMMON_API LLFrameTimer { diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index dd0efb422..c8d0be2f4 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -67,18 +67,12 @@ // //---------------------------------------------------------------------------- -#if !LL_DARWIN -U32 ll_thread_local local_thread_ID = 0; -#endif - -U32 LLThread::sIDIter = 0; LLAtomicS32 LLThread::sCount = 0; LLAtomicS32 LLThread::sRunning = 0; LL_COMMON_API void assert_main_thread() { - static U32 s_thread_id = LLThread::currentID(); - if (LLThread::currentID() != s_thread_id) + if (!AIThreadID::in_main_thread()) { llerrs << "Illegal execution outside main thread." << llendl; } @@ -95,9 +89,8 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap LLThread *threadp = (LLThread *)datap; -#if !LL_DARWIN - local_thread_ID = threadp->mID; -#endif + // Initialize thread-local cache of current thread ID (if supported). + AIThreadID::set_current_thread_id(); // Create a thread local data. LLThreadLocalData::create(threadp); @@ -137,7 +130,6 @@ LLThread::LLThread(std::string const& name) : mStatus(STOPPED), mThreadLocalData(NULL) { - mID = ++sIDIter; sCount++; llassert(sCount <= 50); mRunCondition = new LLCondition; @@ -281,12 +273,6 @@ void LLThread::setQuitting() wake(); } -// static -U32 LLThread::currentID() -{ - return (U32)apr_os_thread_current(); -} - // static void LLThread::yield() { @@ -315,14 +301,6 @@ void LLThread::wakeLocked() } } -//static -apr_os_thread_t LLThread::sMainThreadID; - -void LLThread::set_main_thread_id(void) -{ - sMainThreadID = apr_os_thread_current(); -} - // The thread private handle to access the LLThreadLocalData instance. apr_threadkey_t* LLThreadLocalData::sThreadLocalDataKey; @@ -345,6 +323,10 @@ void LLThreadLocalData::init(void) return; } + // This function is called by the main thread (these values are also needed in the next line). + AIThreadID::set_main_thread_id(); + AIThreadID::set_current_thread_id(); + apr_status_t status = apr_threadkey_private_create(&sThreadLocalDataKey, &LLThreadLocalData::destroy, LLAPRRootPool::get()()); ll_apr_assert_status(status); // Or out of memory, or system-imposed limit on the // total number of keys per process {PTHREAD_KEYS_MAX} @@ -352,9 +334,6 @@ void LLThreadLocalData::init(void) // Create the thread-local data for the main thread (this function is called by the main thread). LLThreadLocalData::create(NULL); - - // This function is called by the main thread. - LLThread::set_main_thread_id(); } // This is called once for every thread when the thread is destructed. @@ -421,27 +400,19 @@ void LLCondition::broadcast() //============================================================================ LLMutexBase::LLMutexBase() : - mLockingThread(NO_THREAD), + mLockingThread(AIThreadID::sNone), mCount(0) { } bool LLMutexBase::isSelfLocked() const { -#if LL_DARWIN - return mLockingThread == LLThread::currentID(); -#else - return mLockingThread == local_thread_ID; -#endif + return mLockingThread.equals_current_thread(); } void LLMutexBase::lock() { -#if LL_DARWIN - if (mLockingThread == LLThread::currentID()) -#else - if (mLockingThread == local_thread_ID) -#endif + if (mLockingThread.equals_current_thread()) { //redundant lock mCount++; return; @@ -449,11 +420,33 @@ void LLMutexBase::lock() apr_thread_mutex_lock(mAPRMutexp); -#if LL_DARWIN - mLockingThread = LLThread::currentID(); -#else - mLockingThread = local_thread_ID; -#endif + mLockingThread.reset(); +} + +bool LLMutexBase::tryLock() +{ + if (mLockingThread.equals_current_thread()) + { //redundant lock + mCount++; + return true; + } + bool success = !APR_STATUS_IS_EBUSY(apr_thread_mutex_trylock(mAPRMutexp)); + if (success) + { + mLockingThread.reset(); + } + return success; +} + +// non-blocking, but does do a lock/unlock so not free +bool LLMutexBase::isLocked() const +{ + if (mLockingThread.equals_current_thread()) + return false; // A call to lock() won't block. + if (APR_STATUS_IS_EBUSY(apr_thread_mutex_trylock(mAPRMutexp))) + return true; + apr_thread_mutex_unlock(mAPRMutexp); + return false; } void LLMutexBase::unlock() @@ -463,7 +456,7 @@ void LLMutexBase::unlock() mCount--; return; } - mLockingThread = NO_THREAD; + mLockingThread = AIThreadID::sNone; apr_thread_mutex_unlock(mAPRMutexp); } diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index ef4303a02..549a090ec 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -45,17 +45,12 @@ #include "apr_thread_cond.h" #include "llaprpool.h" #include "llatomic.h" +#include "aithreadid.h" class LLThread; class LLMutex; class LLCondition; -#if LL_WINDOWS -#define ll_thread_local __declspec(thread) -#else -#define ll_thread_local __thread -#endif - class LL_COMMON_API LLThreadLocalDataMember { public: @@ -85,10 +80,12 @@ private: ~LLThreadLocalData(); }; +// Print to llerrs if the current thread is not the main thread. +LL_COMMON_API void assert_main_thread(); + class LL_COMMON_API LLThread { private: - static apr_os_thread_t sMainThreadID; static U32 sIDIter; static LLAtomicS32 sCount; static LLAtomicS32 sRunning; @@ -108,11 +105,9 @@ public: bool isQuitting() const { return (QUITTING == mStatus); } bool isStopped() const { return (STOPPED == mStatus); } - static U32 currentID(); // Return ID of current thread static S32 getCount() { return sCount; } static S32 getRunning() { return sRunning; } static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure. - static bool is_main_thread(void) { return apr_os_thread_equal(LLThread::sMainThreadID, apr_os_thread_current()); } public: // PAUSE / RESUME functionality. See source code for important usage notes. @@ -136,11 +131,6 @@ public: // Return thread-local data for the current thread. static LLThreadLocalData& tldata(void) { return LLThreadLocalData::tldata(); } - // Called once, from LLThreadLocalData::init(). - static void set_main_thread_id(void); - - U32 getID() const { return mID; } - private: bool mPaused; @@ -153,7 +143,6 @@ protected: apr_thread_t *mAPRThreadp; volatile EThreadStatus mStatus; - U32 mID; friend void LLThreadLocalData::create(LLThread* threadp); LLThreadLocalData* mThreadLocalData; @@ -183,8 +172,7 @@ protected: }; #ifdef SHOW_ASSERT -LL_COMMON_API inline bool is_main_thread(void) { return LLThread::is_main_thread(); } -#define ASSERT_SINGLE_THREAD do { static apr_os_thread_t first_thread_id = apr_os_thread_current(); llassert(apr_os_thread_equal(first_thread_id, apr_os_thread_current())); } while(0) +#define ASSERT_SINGLE_THREAD do { static AIThreadID first_thread_id; llassert(first_thread_id.equals_current_thread()); } while(0) #else #define ASSERT_SINGLE_THREAD do { } while(0) #endif @@ -204,32 +192,24 @@ LL_COMMON_API inline bool is_main_thread(void) { return LLThread::is_main_thread class LL_COMMON_API LLMutexBase { public: - typedef enum - { - NO_THREAD = 0xFFFFFFFF - } e_locking_thread; - LLMutexBase() ; void lock(); // blocks void unlock(); // Returns true if lock was obtained successfully. - bool tryLock() { return !APR_STATUS_IS_EBUSY(apr_thread_mutex_trylock(mAPRMutexp)); } + bool tryLock(); - // non-blocking, but does do a lock/unlock so not free - bool isLocked() { bool is_not_locked = tryLock(); if (is_not_locked) unlock(); return !is_not_locked; } + // Returns true if a call to lock() would block (returns false if self-locked()). + bool isLocked() const; // Returns true if locked by this thread. bool isSelfLocked() const; - // get ID of locking thread - U32 lockingThread() const { return mLockingThread; } - protected: // mAPRMutexp is initialized and uninitialized in the derived class. apr_thread_mutex_t* mAPRMutexp; mutable U32 mCount; - mutable U32 mLockingThread; + mutable AIThreadID mLockingThread; private: // Disallow copy construction and assignment. diff --git a/indra/newview/statemachine/aistatemachine.cpp b/indra/newview/statemachine/aistatemachine.cpp index 675317cb1..f008a4873 100644 --- a/indra/newview/statemachine/aistatemachine.cpp +++ b/indra/newview/statemachine/aistatemachine.cpp @@ -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) diff --git a/indra/newview/statemachine/aistatemachine.h b/indra/newview/statemachine/aistatemachine.h index 13da6fd3d..55028232b 100644 --- a/indra/newview/statemachine/aistatemachine.h +++ b/indra/newview/statemachine/aistatemachine.h @@ -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: