Merge remote-tracking branch 'aleric/V2MultiWear' into AltCompilers
This commit is contained in:
@@ -38,6 +38,7 @@
|
||||
#endif
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llaprpool.h"
|
||||
|
||||
extern "C" {
|
||||
#include <dbus/dbus-glib.h>
|
||||
@@ -55,8 +56,8 @@ extern "C" {
|
||||
#undef LL_DBUS_SYM
|
||||
|
||||
static bool sSymsGrabbed = false;
|
||||
static apr_pool_t *sSymDBUSDSOMemoryPool = NULL;
|
||||
static apr_dso_handle_t *sSymDBUSDSOHandleG = NULL;
|
||||
static LLAPRPool sSymDBUSDSOMemoryPool; // Used for sSymDBUSDSOHandleG (and what it is pointing at?)
|
||||
static apr_dso_handle_t* sSymDBUSDSOHandleG = NULL;
|
||||
|
||||
bool grab_dbus_syms(std::string dbus_dso_name)
|
||||
{
|
||||
@@ -74,18 +75,18 @@ bool grab_dbus_syms(std::string dbus_dso_name)
|
||||
#define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##DBUSSYM, sSymDBUSDSOHandle, #DBUSSYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #DBUSSYM); if (REQUIRED) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #DBUSSYM, (void*)ll##DBUSSYM);}while(0)
|
||||
|
||||
//attempt to load the shared library
|
||||
apr_pool_create(&sSymDBUSDSOMemoryPool, NULL);
|
||||
sSymDBUSDSOMemoryPool.create();
|
||||
|
||||
#ifdef LL_STANDALONE
|
||||
void *dso_handle = dlopen(dbus_dso_name.c_str(), RTLD_NOW | RTLD_GLOBAL);
|
||||
rv = (!dso_handle)?APR_EDSOOPEN:apr_os_dso_handle_put(&sSymDBUSDSOHandle,
|
||||
dso_handle, sSymDBUSDSOMemoryPool);
|
||||
dso_handle, sSymDBUSDSOMemoryPool());
|
||||
|
||||
if ( APR_SUCCESS == rv )
|
||||
#else
|
||||
if ( APR_SUCCESS == (rv = apr_dso_load(&sSymDBUSDSOHandle,
|
||||
dbus_dso_name.c_str(),
|
||||
sSymDBUSDSOMemoryPool) ))
|
||||
sSymDBUSDSOMemoryPool()) ))
|
||||
#endif
|
||||
{
|
||||
INFOMSG("Found DSO: %s", dbus_dso_name.c_str());
|
||||
@@ -113,6 +114,10 @@ bool grab_dbus_syms(std::string dbus_dso_name)
|
||||
#undef LL_DBUS_SYM
|
||||
|
||||
sSymsGrabbed = rtn;
|
||||
if (!sSymsGrabbed)
|
||||
{
|
||||
sSymDBUSDSOMemoryPool.destroy();
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
@@ -127,13 +132,9 @@ void ungrab_dbus_syms()
|
||||
apr_dso_unload(sSymDBUSDSOHandleG);
|
||||
sSymDBUSDSOHandleG = NULL;
|
||||
}
|
||||
|
||||
if ( sSymDBUSDSOMemoryPool )
|
||||
{
|
||||
apr_pool_destroy(sSymDBUSDSOMemoryPool);
|
||||
sSymDBUSDSOMemoryPool = NULL;
|
||||
}
|
||||
|
||||
|
||||
sSymDBUSDSOMemoryPool.destroy();
|
||||
|
||||
// NULL-out all of the symbols we'd grabbed
|
||||
#define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) do{ll##DBUSSYM = NULL;}while(0)
|
||||
#include "llappviewerlinux_api_dbus_syms_raw.inc"
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
BOOL gHackGodmode = FALSE;
|
||||
#endif
|
||||
|
||||
AITHREADSAFE(settings_map_type, gSettings,);
|
||||
AIThreadSafeDC<settings_map_type> gSettings;
|
||||
LLControlGroup gSavedSettings("Global"); // saved at end of session
|
||||
LLControlGroup gSavedPerAccountSettings("PerAccount"); // saved at end of session
|
||||
LLControlGroup gColors("Colors"); // saved at end of session
|
||||
|
||||
@@ -51,7 +51,7 @@ extern BOOL gHackGodmode;
|
||||
void settings_setup_listeners();
|
||||
|
||||
typedef std::map<std::string, LLControlGroup*> settings_map_type;
|
||||
extern AIThreadSafe<settings_map_type> gSettings;
|
||||
extern AIThreadSafeDC<settings_map_type> gSettings;
|
||||
|
||||
// for the graphics settings
|
||||
void create_graphics_group(LLControlGroup& group);
|
||||
|
||||
@@ -64,22 +64,8 @@ inline void AIRegisteredStateMachines::trigger(void)
|
||||
}
|
||||
|
||||
// A list (array) with all AIRegisteredStateMachines maps, one for each event type.
|
||||
struct AIRegisteredStateMachinesList {
|
||||
AIThreadSafeSimple<AIRegisteredStateMachines> mRegisteredStateMachinesList[AIEvent::number_of_events];
|
||||
AIRegisteredStateMachinesList(void);
|
||||
AIThreadSafeSimple<AIRegisteredStateMachines>& operator[](AIEvent::AIEvents event) { return mRegisteredStateMachinesList[event]; }
|
||||
};
|
||||
|
||||
AIRegisteredStateMachinesList::AIRegisteredStateMachinesList(void)
|
||||
{
|
||||
for (int event = 0; event < AIEvent::number_of_events; ++event)
|
||||
{
|
||||
new (&mRegisteredStateMachinesList[event]) AIRegisteredStateMachines;
|
||||
}
|
||||
}
|
||||
|
||||
// Instantiate the list with all AIRegisteredStateMachines maps.
|
||||
static AIRegisteredStateMachinesList registered_statemachines_list;
|
||||
static AIThreadSafeSimpleDC<AIRegisteredStateMachines> registered_statemachines_list[AIEvent::number_of_events];
|
||||
typedef AIAccess<AIRegisteredStateMachines> registered_statemachines_wat;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// External API starts here.
|
||||
@@ -91,7 +77,7 @@ static AIRegisteredStateMachinesList registered_statemachines_list;
|
||||
void AIEvent::Register(AIEvents event, AIStateMachine* statemachine, bool one_shot)
|
||||
{
|
||||
statemachine->idle();
|
||||
AIAccess<AIRegisteredStateMachines> registered_statemachines_w(registered_statemachines_list[event]);
|
||||
registered_statemachines_wat registered_statemachines_w(registered_statemachines_list[event]);
|
||||
registered_statemachines_w->Register(statemachine, one_shot);
|
||||
}
|
||||
|
||||
@@ -99,7 +85,7 @@ void AIEvent::Register(AIEvents event, AIStateMachine* statemachine, bool one_sh
|
||||
// static
|
||||
void AIEvent::Unregister(AIEvents event, AIStateMachine* statemachine)
|
||||
{
|
||||
AIAccess<AIRegisteredStateMachines> registered_statemachines_w(registered_statemachines_list[event]);
|
||||
registered_statemachines_wat registered_statemachines_w(registered_statemachines_list[event]);
|
||||
registered_statemachines_w->Unregister(statemachine);
|
||||
}
|
||||
|
||||
@@ -107,7 +93,7 @@ void AIEvent::Unregister(AIEvents event, AIStateMachine* statemachine)
|
||||
// static
|
||||
void AIEvent::trigger(AIEvents event)
|
||||
{
|
||||
AIAccess<AIRegisteredStateMachines> registered_statemachines_w(registered_statemachines_list[event]);
|
||||
registered_statemachines_wat registered_statemachines_w(registered_statemachines_list[event]);
|
||||
registered_statemachines_w->trigger();
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ AIFilePicker::AIFilePicker(void) : mPluginManager(NULL), mAutoKill(false), mCanc
|
||||
}
|
||||
|
||||
// static
|
||||
AITHREADSAFESIMPLE(AIFilePicker::context_map_type, AIFilePicker::sContextMap, );
|
||||
AIThreadSafeSimpleDC<AIFilePicker::context_map_type> AIFilePicker::sContextMap;
|
||||
|
||||
// static
|
||||
void AIFilePicker::store_folder(std::string const& context, std::string const& folder)
|
||||
|
||||
@@ -185,7 +185,7 @@ public:
|
||||
private:
|
||||
LLPointer<LLViewerPluginManager> mPluginManager; //!< Pointer to the plugin manager.
|
||||
typedef std::map<std::string, std::string> context_map_type; //!< Type of mContextMap.
|
||||
static AIThreadSafeSimple<context_map_type> sContextMap; //!< Map context (ie, "snapshot" or "image") to last used folder.
|
||||
static AIThreadSafeSimpleDC<context_map_type> sContextMap; //!< Map context (ie, "snapshot" or "image") to last used folder.
|
||||
std::string mContext; //!< Some key to indicate the context (remembers the folder per key).
|
||||
bool mAutoKill; //!< True if the default behavior is to delete itself after being finished.
|
||||
|
||||
|
||||
@@ -65,18 +65,18 @@ namespace {
|
||||
};
|
||||
|
||||
typedef std::vector<QueueElement> active_statemachines_type;
|
||||
static active_statemachines_type active_statemachines;
|
||||
active_statemachines_type active_statemachines;
|
||||
typedef std::vector<AIStateMachine*> continued_statemachines_type;
|
||||
struct cscm_type
|
||||
{
|
||||
continued_statemachines_type continued_statemachines;
|
||||
bool calling_mainloop;
|
||||
};
|
||||
static AITHREADSAFE(cscm_type, continued_statemachines_and_calling_mainloop, );
|
||||
AIThreadSafeDC<cscm_type> continued_statemachines_and_calling_mainloop;
|
||||
}
|
||||
|
||||
// static
|
||||
AITHREADSAFESIMPLE(U64, AIStateMachine::sMaxCount, );
|
||||
AIThreadSafeSimpleDC<U64> AIStateMachine::sMaxCount;
|
||||
|
||||
void AIStateMachine::updateSettings(void)
|
||||
{
|
||||
@@ -157,14 +157,33 @@ void AIStateMachine::idle(void)
|
||||
mSleep = 0;
|
||||
}
|
||||
|
||||
// About thread safeness:
|
||||
//
|
||||
// The main thread initializes a statemachine and calls run, so a statemachine
|
||||
// runs in the main thread. However, it is allowed that a state calls idle()
|
||||
// and then allows one and only one other thread to call cont() upon some
|
||||
// event (only once, of course, as idle() has to be called before cont()
|
||||
// can be called again-- and another thread is not allowed to call idle()).
|
||||
// Instead of cont(), the other thread may also call set_state().
|
||||
|
||||
void AIStateMachine::cont(void)
|
||||
{
|
||||
DoutEntering(dc::statemachine, "AIStateMachine::cont() [" << (void*)this << "]");
|
||||
llassert(mIdle);
|
||||
// Atomic test mActive and change mIdle.
|
||||
mIdleActive.lock();
|
||||
mIdle = false;
|
||||
if (mActive == as_idle)
|
||||
bool not_active = mActive == as_idle;
|
||||
mIdleActive.unlock();
|
||||
if (not_active)
|
||||
{
|
||||
AIWriteAccess<cscm_type> cscm_w(continued_statemachines_and_calling_mainloop);
|
||||
// We only get here when the statemachine was idle (set by the main thread),
|
||||
// see first assertion. Hence, the main thread is not changing this, as the
|
||||
// statemachine is not running. Thus, mActive can have changed when a THIRD
|
||||
// thread called cont(), which is not allowed: if two threads can call cont()
|
||||
// at any moment then the first assertion can't hold.
|
||||
llassert_always(mActive == as_idle);
|
||||
cscm_w->continued_statemachines.push_back(this);
|
||||
if (!cscm_w->calling_mainloop)
|
||||
{
|
||||
@@ -173,6 +192,7 @@ void AIStateMachine::cont(void)
|
||||
gIdleCallbacks.addFunction(&AIStateMachine::mainloop);
|
||||
}
|
||||
mActive = as_queued;
|
||||
llassert_always(!mIdle); // It should never happen that one thread calls cont() while another calls idle() concurrently.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +223,7 @@ void AIStateMachine::finish(void)
|
||||
{
|
||||
DoutEntering(dc::statemachine, "AIStateMachine::finish() [" << (void*)this << "]");
|
||||
llassert(mState == bs_run || mState == bs_abort);
|
||||
// It is possible that mIdle is false when abort or finish was called from
|
||||
// It is possible that mIdle is true when abort or finish was called from
|
||||
// outside multiplex_impl. However, that only may be done by the main thread.
|
||||
llassert(!mIdle || is_main_thread());
|
||||
if (!mIdle)
|
||||
@@ -363,6 +383,9 @@ void AIStateMachine::mainloop(void*)
|
||||
if (!statemachine.mIdle)
|
||||
{
|
||||
U64 start = LLFastTimer::getCPUClockCount64();
|
||||
// This might call idle() and then pass the statemachine to another thread who then may call cont().
|
||||
// Hence, after this isn't not sure what mIdle is, and it can change from true to false at any moment,
|
||||
// if it is true after this function returns.
|
||||
iter->statemachine().multiplex(start);
|
||||
U64 delta = LLFastTimer::getCPUClockCount64() - start;
|
||||
iter->add(delta);
|
||||
@@ -382,10 +405,23 @@ void AIStateMachine::mainloop(void*)
|
||||
while (iter != active_statemachines.end())
|
||||
{
|
||||
AIStateMachine& statemachine(iter->statemachine());
|
||||
if (statemachine.mIdle)
|
||||
// Atomic test mIdle and change mActive.
|
||||
bool locked = statemachine.mIdleActive.tryLock();
|
||||
// If the lock failed, then another thread is in the middle of calling cont(),
|
||||
// thus mIdle will end up false. So, there is no reason to block here; just
|
||||
// treat mIdle as false already.
|
||||
if (locked && statemachine.mIdle)
|
||||
{
|
||||
Dout(dc::statemachine, "Erasing " << (void*)&statemachine << " from active_statemachines");
|
||||
// Without the lock, it would be possible that another thread called cont() right here,
|
||||
// changing mIdle to false again but NOT adding the statemachine to continued_statemachines,
|
||||
// thinking it is in active_statemachines (and it is), while immediately below it is
|
||||
// erased from active_statemachines.
|
||||
statemachine.mActive = as_idle;
|
||||
// Now, calling cont() is ok -- as that will cause the statemachine to be added to
|
||||
// continued_statemachines, so it's fine in that case-- even necessary-- to remove it from
|
||||
// active_statemachines regardless, and we can release the lock here.
|
||||
statemachine.mIdleActive.unlock();
|
||||
Dout(dc::statemachine, "Erasing " << (void*)&statemachine << " from active_statemachines");
|
||||
iter = active_statemachines.erase(iter);
|
||||
if (statemachine.mState == bs_killed)
|
||||
{
|
||||
@@ -395,6 +431,11 @@ void AIStateMachine::mainloop(void*)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (locked)
|
||||
{
|
||||
statemachine.mIdleActive.unlock();
|
||||
}
|
||||
llassert(statemachine.mActive == as_active); // It should not be possible that another thread called cont() and changed this when we are we are not idle.
|
||||
llassert(statemachine.mState == bs_run || statemachine.mState == bs_initialize);
|
||||
++iter;
|
||||
}
|
||||
|
||||
@@ -206,6 +206,7 @@ class AIStateMachine {
|
||||
bool mAborted; //!< True after calling abort() and before calling run().
|
||||
active_type mActive; //!< Whether statemachine is idle, queued to be added to the active list, or already on the active list.
|
||||
S64 mSleep; //!< Non-zero while the state machine is sleeping.
|
||||
LLMutex mIdleActive; //!< Used for atomic operations on the pair mIdle / mActive.
|
||||
|
||||
// Callback facilities.
|
||||
// From within an other state machine:
|
||||
@@ -224,7 +225,7 @@ class AIStateMachine {
|
||||
};
|
||||
callback_type* mCallback; //!< Pointer to signal/connection, or NULL when not connected.
|
||||
|
||||
static AIThreadSafeSimple<U64> sMaxCount; //!< Number of cpu clocks below which we start a new state machine within the same frame.
|
||||
static AIThreadSafeSimpleDC<U64> sMaxCount; //!< Number of cpu clocks below which we start a new state machine within the same frame.
|
||||
|
||||
protected:
|
||||
//! State of the derived class. Only valid if mState == bs_run. Call set_state to change.
|
||||
|
||||
Reference in New Issue
Block a user