Merge remote-tracking branch 'aleric/V2MultiWear' into AltCompilers

This commit is contained in:
Drake Arconis
2012-07-02 21:08:04 +00:00
29 changed files with 523 additions and 1812 deletions

View File

@@ -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"

View File

@@ -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

View File

@@ -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);

View File

@@ -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();
}

View File

@@ -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)

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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.