Threading voodoo: allow multiple concurrent calls to set_state().
This patch prepares AIStateMachine for the use of AITimer together with calls to set_state() from other threads. The extra problem in this case is that the main-thread CAN start running the state machine again (when the timer times out), while before it was assumed to be idle until a thread called set_state. This also takes into account that a thread might call set_state() and then AGAIN call set_state() before the main thread gets the chance to call idle() inbetween.
This commit is contained in:
@@ -310,11 +310,13 @@ void LLThread::wakeLocked()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SHOW_ASSERT
|
||||
// This allows the use of llassert(is_main_thread()) to assure the current thread is the main thread.
|
||||
static apr_os_thread_t main_thread_id;
|
||||
LL_COMMON_API bool is_main_thread(void) { return apr_os_thread_equal(main_thread_id, apr_os_thread_current()); }
|
||||
#endif
|
||||
//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;
|
||||
@@ -346,10 +348,8 @@ void LLThreadLocalData::init(void)
|
||||
// Create the thread-local data for the main thread (this function is called by the main thread).
|
||||
LLThreadLocalData::create(NULL);
|
||||
|
||||
#ifdef SHOW_ASSERT
|
||||
// This function is called by the main thread.
|
||||
main_thread_id = apr_os_thread_current();
|
||||
#endif
|
||||
LLThread::set_main_thread_id();
|
||||
}
|
||||
|
||||
// This is called once for every thread when the thread is destructed.
|
||||
|
||||
@@ -40,13 +40,6 @@
|
||||
#include "llaprpool.h"
|
||||
#include "llatomic.h"
|
||||
|
||||
#ifdef SHOW_ASSERT
|
||||
extern LL_COMMON_API bool is_main_thread(void);
|
||||
#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)
|
||||
#else
|
||||
#define ASSERT_SINGLE_THREAD do { } while(0)
|
||||
#endif
|
||||
|
||||
class LLThread;
|
||||
class LLMutex;
|
||||
class LLCondition;
|
||||
@@ -89,6 +82,7 @@ private:
|
||||
class LL_COMMON_API LLThread
|
||||
{
|
||||
private:
|
||||
static apr_os_thread_t sMainThreadID;
|
||||
static U32 sIDIter;
|
||||
static LLAtomicS32 sCount;
|
||||
static LLAtomicS32 sRunning;
|
||||
@@ -112,6 +106,7 @@ public:
|
||||
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.
|
||||
@@ -135,6 +130,9 @@ 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:
|
||||
@@ -178,6 +176,13 @@ protected:
|
||||
// mRunCondition->unlock();
|
||||
};
|
||||
|
||||
#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)
|
||||
#else
|
||||
#define ASSERT_SINGLE_THREAD do { } while(0)
|
||||
#endif
|
||||
|
||||
//============================================================================
|
||||
|
||||
#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
|
||||
|
||||
Reference in New Issue
Block a user