Merge 6.2.2
commit
65cb4b6d20
1
.hgtags
1
.hgtags
|
|
@ -547,3 +547,4 @@ ac3b1332ad4f55b7182a8cbcc1254535a0069f75 5.1.7-release
|
|||
a3143db58a0f6b005232bf9018e7fef17ff9ec90 6.1.0-release
|
||||
50f0ece62ddb5a244ecb6d00ef5a89d80ad50efa 6.1.1-release
|
||||
82a89165e5929a6c3073d6cd60a543cb395f147b 6.2.0-release
|
||||
706bdc7e25c6e6b8fb56f4a13fcce2936e70a79c 6.2.1-release
|
||||
|
|
|
|||
|
|
@ -374,6 +374,7 @@ Cinder Roxley
|
|||
STORM-2116
|
||||
STORM-2127
|
||||
STORM-2144
|
||||
SL-3404
|
||||
Clara Young
|
||||
Coaldust Numbers
|
||||
VWR-1095
|
||||
|
|
@ -779,6 +780,7 @@ Jonathan Yap
|
|||
STORM-2100
|
||||
STORM-2104
|
||||
STORM-2142
|
||||
SL-10089
|
||||
Kadah Coba
|
||||
STORM-1060
|
||||
STORM-1843
|
||||
|
|
@ -1069,6 +1071,8 @@ Nicky Dasmijn
|
|||
STORM-2010
|
||||
STORM-2082
|
||||
MAINT-6665
|
||||
SL-10291
|
||||
SL-10293
|
||||
Nicky Perian
|
||||
OPEN-1
|
||||
STORM-1087
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ set(llcommon_SOURCE_FILES
|
|||
llapp.cpp
|
||||
llapr.cpp
|
||||
llassettype.cpp
|
||||
llatomic.cpp
|
||||
llbase32.cpp
|
||||
llbase64.cpp
|
||||
llbitpack.cpp
|
||||
|
|
@ -135,6 +136,7 @@ set(llcommon_HEADER_FILES
|
|||
llapp.h
|
||||
llapr.h
|
||||
llassettype.h
|
||||
llatomic.h
|
||||
llbase32.h
|
||||
llbase64.h
|
||||
llbitpack.h
|
||||
|
|
|
|||
|
|
@ -153,7 +153,6 @@ const U8 SIM_ACCESS_DOWN = 254;
|
|||
const U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT;
|
||||
|
||||
// attachment constants
|
||||
const S32 MAX_AGENT_ATTACHMENTS = 38;
|
||||
const U8 ATTACHMENT_ADD = 0x80;
|
||||
|
||||
// god levels
|
||||
|
|
|
|||
|
|
@ -30,9 +30,8 @@
|
|||
#include <map>
|
||||
#include "llrun.h"
|
||||
#include "llsd.h"
|
||||
#include <atomic>
|
||||
// Forward declarations
|
||||
template <typename Type> class LLAtomic32;
|
||||
typedef LLAtomic32<U32> LLAtomicU32;
|
||||
class LLErrorThread;
|
||||
class LLLiveFile;
|
||||
#if LL_LINUX
|
||||
|
|
|
|||
|
|
@ -28,13 +28,12 @@
|
|||
|
||||
#include "linden_common.h"
|
||||
#include "llapr.h"
|
||||
#include "llmutex.h"
|
||||
#include "apr_dso.h"
|
||||
#include "llthreadlocalstorage.h"
|
||||
|
||||
apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool
|
||||
LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool.
|
||||
apr_thread_mutex_t *gLogMutexp = NULL;
|
||||
apr_thread_mutex_t *gCallStacksLogMutexp = NULL;
|
||||
|
||||
const S32 FULL_VOLATILE_APR_POOL = 1024 ; //number of references to LLVolatileAPRPool
|
||||
|
||||
|
|
@ -48,10 +47,6 @@ void ll_init_apr()
|
|||
if (!gAPRPoolp)
|
||||
{
|
||||
apr_pool_create(&gAPRPoolp, NULL);
|
||||
|
||||
// Initialize the logging mutex
|
||||
apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
|
||||
apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
|
||||
}
|
||||
|
||||
if(!LLAPRFile::sAPRFilePoolp)
|
||||
|
|
@ -75,23 +70,6 @@ void ll_cleanup_apr()
|
|||
|
||||
LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL;
|
||||
|
||||
if (gLogMutexp)
|
||||
{
|
||||
// Clean up the logging mutex
|
||||
|
||||
// All other threads NEED to be done before we clean up APR, so this is okay.
|
||||
apr_thread_mutex_destroy(gLogMutexp);
|
||||
gLogMutexp = NULL;
|
||||
}
|
||||
if (gCallStacksLogMutexp)
|
||||
{
|
||||
// Clean up the logging mutex
|
||||
|
||||
// All other threads NEED to be done before we clean up APR, so this is okay.
|
||||
apr_thread_mutex_destroy(gCallStacksLogMutexp);
|
||||
gCallStacksLogMutexp = NULL;
|
||||
}
|
||||
|
||||
LLThreadLocalPointerBase::destroyAllThreadLocalStorage();
|
||||
|
||||
if (gAPRPoolp)
|
||||
|
|
@ -168,26 +146,19 @@ apr_pool_t* LLAPRPool::getAPRPool()
|
|||
LLVolatileAPRPool::LLVolatileAPRPool(BOOL is_local, apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
|
||||
: LLAPRPool(parent, size, releasePoolFlag),
|
||||
mNumActiveRef(0),
|
||||
mNumTotalRef(0),
|
||||
mMutexPool(NULL),
|
||||
mMutexp(NULL)
|
||||
mNumTotalRef(0)
|
||||
{
|
||||
//create mutex
|
||||
if(!is_local) //not a local apr_pool, that is: shared by multiple threads.
|
||||
{
|
||||
apr_pool_create(&mMutexPool, NULL); // Create a pool for mutex
|
||||
apr_thread_mutex_create(&mMutexp, APR_THREAD_MUTEX_UNNESTED, mMutexPool);
|
||||
mMutexp.reset(new std::mutex());
|
||||
}
|
||||
}
|
||||
|
||||
LLVolatileAPRPool::~LLVolatileAPRPool()
|
||||
{
|
||||
//delete mutex
|
||||
if(mMutexp)
|
||||
{
|
||||
apr_thread_mutex_destroy(mMutexp);
|
||||
apr_pool_destroy(mMutexPool);
|
||||
}
|
||||
mMutexp.reset();
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -201,7 +172,7 @@ apr_pool_t* LLVolatileAPRPool::getAPRPool()
|
|||
|
||||
apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool()
|
||||
{
|
||||
LLScopedLock lock(mMutexp) ;
|
||||
LLScopedLock lock(mMutexp.get()) ;
|
||||
|
||||
mNumTotalRef++ ;
|
||||
mNumActiveRef++ ;
|
||||
|
|
@ -216,7 +187,7 @@ apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool()
|
|||
|
||||
void LLVolatileAPRPool::clearVolatileAPRPool()
|
||||
{
|
||||
LLScopedLock lock(mMutexp) ;
|
||||
LLScopedLock lock(mMutexp.get());
|
||||
|
||||
if(mNumActiveRef > 0)
|
||||
{
|
||||
|
|
@ -250,44 +221,6 @@ BOOL LLVolatileAPRPool::isFull()
|
|||
{
|
||||
return mNumTotalRef > FULL_VOLATILE_APR_POOL ;
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// LLScopedLock
|
||||
//
|
||||
LLScopedLock::LLScopedLock(apr_thread_mutex_t* mutex) : mMutex(mutex)
|
||||
{
|
||||
if(mutex)
|
||||
{
|
||||
if(ll_apr_warn_status(apr_thread_mutex_lock(mMutex)))
|
||||
{
|
||||
mLocked = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
mLocked = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mLocked = false;
|
||||
}
|
||||
}
|
||||
|
||||
LLScopedLock::~LLScopedLock()
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
|
||||
void LLScopedLock::unlock()
|
||||
{
|
||||
if(mLocked)
|
||||
{
|
||||
if(!ll_apr_warn_status(apr_thread_mutex_unlock(mMutex)))
|
||||
{
|
||||
mLocked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -36,15 +36,22 @@
|
|||
#include <boost/noncopyable.hpp>
|
||||
#include "llwin32headerslean.h"
|
||||
#include "apr_thread_proc.h"
|
||||
#include "apr_thread_mutex.h"
|
||||
#include "apr_getopt.h"
|
||||
#include "apr_signal.h"
|
||||
#include "apr_atomic.h"
|
||||
|
||||
#include "llstring.h"
|
||||
|
||||
extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp;
|
||||
extern apr_thread_mutex_t* gCallStacksLogMutexp;
|
||||
#if LL_WINDOWS
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable:4265)
|
||||
#endif
|
||||
// warning C4265: 'std::_Pad' : class has virtual functions, but destructor is not virtual
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#if LL_WINDOWS
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
struct apr_dso_handle_t;
|
||||
/**
|
||||
|
|
@ -120,77 +127,9 @@ private:
|
|||
S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool.
|
||||
S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating.
|
||||
|
||||
apr_thread_mutex_t *mMutexp;
|
||||
apr_pool_t *mMutexPool;
|
||||
std::unique_ptr<std::mutex> mMutexp;
|
||||
} ;
|
||||
|
||||
/**
|
||||
* @class LLScopedLock
|
||||
* @brief Small class to help lock and unlock mutexes.
|
||||
*
|
||||
* This class is used to have a stack level lock once you already have
|
||||
* an apr mutex handy. The constructor handles the lock, and the
|
||||
* destructor handles the unlock. Instances of this class are
|
||||
* <b>not</b> thread safe.
|
||||
*/
|
||||
class LL_COMMON_API LLScopedLock : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor which accepts a mutex, and locks it.
|
||||
*
|
||||
* @param mutex An allocated APR mutex. If you pass in NULL,
|
||||
* this wrapper will not lock.
|
||||
*/
|
||||
LLScopedLock(apr_thread_mutex_t* mutex);
|
||||
|
||||
/**
|
||||
* @brief Destructor which unlocks the mutex if still locked.
|
||||
*/
|
||||
~LLScopedLock();
|
||||
|
||||
/**
|
||||
* @brief Check lock.
|
||||
*/
|
||||
bool isLocked() const { return mLocked; }
|
||||
|
||||
/**
|
||||
* @brief This method unlocks the mutex.
|
||||
*/
|
||||
void unlock();
|
||||
|
||||
protected:
|
||||
bool mLocked;
|
||||
apr_thread_mutex_t* mMutex;
|
||||
};
|
||||
|
||||
template <typename Type> class LLAtomic32
|
||||
{
|
||||
public:
|
||||
LLAtomic32<Type>() {};
|
||||
LLAtomic32<Type>(Type x) {apr_atomic_set32(&mData, apr_uint32_t(x)); };
|
||||
~LLAtomic32<Type>() {};
|
||||
|
||||
operator const Type() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); }
|
||||
|
||||
Type CurrentValue() const { apr_uint32_t data = apr_atomic_read32(const_cast< volatile apr_uint32_t* >(&mData)); return Type(data); }
|
||||
|
||||
Type operator =(const Type& x) { apr_atomic_set32(&mData, apr_uint32_t(x)); return Type(mData); }
|
||||
void operator -=(Type x) { apr_atomic_sub32(&mData, apr_uint32_t(x)); }
|
||||
void operator +=(Type x) { apr_atomic_add32(&mData, apr_uint32_t(x)); }
|
||||
Type operator ++(int) { return apr_atomic_inc32(&mData); } // Type++
|
||||
Type operator --(int) { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise)
|
||||
|
||||
Type operator ++() { return apr_atomic_inc32(&mData); } // Type++
|
||||
Type operator --() { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise)
|
||||
|
||||
private:
|
||||
volatile apr_uint32_t mData;
|
||||
};
|
||||
|
||||
typedef LLAtomic32<U32> LLAtomicU32;
|
||||
typedef LLAtomic32<S32> LLAtomicS32;
|
||||
|
||||
// File IO convenience functions.
|
||||
// Returns NULL if the file fails to open, sets *sizep to file size if not NULL
|
||||
// abbreviated flags
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* @file llatomic.cpp
|
||||
*
|
||||
* $LicenseInfo:firstyear=2018&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2018, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llatomic.h"
|
||||
|
||||
//============================================================================
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* @file llatomic.h
|
||||
* @brief Base classes for atomic.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2018&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2018, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLATOMIC_H
|
||||
#define LL_LLATOMIC_H
|
||||
|
||||
#include "stdtypes.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
template <typename Type, typename AtomicType = std::atomic< Type > > class LLAtomicBase
|
||||
{
|
||||
public:
|
||||
LLAtomicBase() {};
|
||||
LLAtomicBase(Type x) { mData.store(x); }
|
||||
~LLAtomicBase() {};
|
||||
|
||||
operator const Type() { return mData; }
|
||||
|
||||
Type CurrentValue() const { return mData; }
|
||||
|
||||
Type operator =(const Type& x) { mData.store(x); return mData; }
|
||||
void operator -=(Type x) { mData -= x; }
|
||||
void operator +=(Type x) { mData += x; }
|
||||
Type operator ++(int) { return mData++; }
|
||||
Type operator --(int) { return mData--; }
|
||||
|
||||
Type operator ++() { return ++mData; }
|
||||
Type operator --() { return --mData; }
|
||||
|
||||
private:
|
||||
AtomicType mData;
|
||||
};
|
||||
|
||||
// Typedefs for specialized versions. Using std::atomic_(u)int32_t to get the optimzed implementation.
|
||||
#ifdef LL_WINDOWS
|
||||
typedef LLAtomicBase<U32, std::atomic_uint32_t> LLAtomicU32;
|
||||
typedef LLAtomicBase<S32, std::atomic_int32_t> LLAtomicS32;
|
||||
#else
|
||||
typedef LLAtomicBase<U32, std::atomic_uint> LLAtomicU32;
|
||||
typedef LLAtomicBase<S32, std::atomic_int> LLAtomicS32;
|
||||
#endif
|
||||
|
||||
typedef LLAtomicBase<bool, std::atomic_bool> LLAtomicBool;
|
||||
|
||||
#endif // LL_LLATOMIC_H
|
||||
|
|
@ -390,15 +390,22 @@ namespace
|
|||
|
||||
{
|
||||
llifstream file(filename().c_str());
|
||||
if (file.is_open())
|
||||
if (!file.is_open())
|
||||
{
|
||||
LLSDSerialize::fromXML(configuration, file);
|
||||
LL_WARNS() << filename() << " failed to open file; not changing configuration" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (configuration.isUndefined())
|
||||
if (LLSDSerialize::fromXML(configuration, file) == LLSDParser::PARSE_FAILURE)
|
||||
{
|
||||
LL_WARNS() << filename() << " missing, ill-formed,"
|
||||
" or simply undefined; not changing configuration"
|
||||
LL_WARNS() << filename() << " parcing error; not changing configuration" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (configuration.isUndefined() || !configuration.isMap() || configuration.emptyMap())
|
||||
{
|
||||
LL_WARNS() << filename() << " missing, ill-formed, or simply undefined"
|
||||
" content; not changing configuration"
|
||||
<< LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
|
@ -860,19 +867,24 @@ namespace LLError
|
|||
setEnabledLogTypesMask(config["enabled-log-types-mask"].asInteger());
|
||||
}
|
||||
|
||||
LLSD sets = config["settings"];
|
||||
LLSD::array_const_iterator a, end;
|
||||
for (a = sets.beginArray(), end = sets.endArray(); a != end; ++a)
|
||||
{
|
||||
const LLSD& entry = *a;
|
||||
|
||||
ELevel level = decodeLevel(entry["level"]);
|
||||
|
||||
setLevels(s->mFunctionLevelMap, entry["functions"], level);
|
||||
setLevels(s->mClassLevelMap, entry["classes"], level);
|
||||
setLevels(s->mFileLevelMap, entry["files"], level);
|
||||
setLevels(s->mTagLevelMap, entry["tags"], level);
|
||||
}
|
||||
if (config.has("settings") && config["settings"].isArray())
|
||||
{
|
||||
LLSD sets = config["settings"];
|
||||
LLSD::array_const_iterator a, end;
|
||||
for (a = sets.beginArray(), end = sets.endArray(); a != end; ++a)
|
||||
{
|
||||
const LLSD& entry = *a;
|
||||
if (entry.isMap() && !entry.emptyMap())
|
||||
{
|
||||
ELevel level = decodeLevel(entry["level"]);
|
||||
|
||||
setLevels(s->mFunctionLevelMap, entry["functions"], level);
|
||||
setLevels(s->mClassLevelMap, entry["classes"], level);
|
||||
setLevels(s->mFileLevelMap, entry["files"], level);
|
||||
setLevels(s->mTagLevelMap, entry["tags"], level);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1136,6 +1148,9 @@ namespace
|
|||
}
|
||||
|
||||
namespace {
|
||||
LLMutex gLogMutex;
|
||||
LLMutex gCallStacksLogMutex;
|
||||
|
||||
bool checkLevelMap(const LevelMap& map, const std::string& key,
|
||||
LLError::ELevel& level)
|
||||
{
|
||||
|
|
@ -1175,56 +1190,6 @@ namespace {
|
|||
}
|
||||
return found_level;
|
||||
}
|
||||
|
||||
class LogLock
|
||||
{
|
||||
public:
|
||||
LogLock();
|
||||
~LogLock();
|
||||
bool ok() const { return mOK; }
|
||||
private:
|
||||
bool mLocked;
|
||||
bool mOK;
|
||||
};
|
||||
|
||||
LogLock::LogLock()
|
||||
: mLocked(false), mOK(false)
|
||||
{
|
||||
if (!gLogMutexp)
|
||||
{
|
||||
mOK = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const int MAX_RETRIES = 5;
|
||||
for (int attempts = 0; attempts < MAX_RETRIES; ++attempts)
|
||||
{
|
||||
apr_status_t s = apr_thread_mutex_trylock(gLogMutexp);
|
||||
if (!APR_STATUS_IS_EBUSY(s))
|
||||
{
|
||||
mLocked = true;
|
||||
mOK = true;
|
||||
return;
|
||||
}
|
||||
|
||||
ms_sleep(1);
|
||||
//apr_thread_yield();
|
||||
// Just yielding won't necessarily work, I had problems with
|
||||
// this on Linux - doug 12/02/04
|
||||
}
|
||||
|
||||
// We're hosed, we can't get the mutex. Blah.
|
||||
std::cerr << "LogLock::LogLock: failed to get mutex for log"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
LogLock::~LogLock()
|
||||
{
|
||||
if (mLocked)
|
||||
{
|
||||
apr_thread_mutex_unlock(gLogMutexp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace LLError
|
||||
|
|
@ -1232,8 +1197,8 @@ namespace LLError
|
|||
|
||||
bool Log::shouldLog(CallSite& site)
|
||||
{
|
||||
LogLock lock;
|
||||
if (!lock.ok())
|
||||
LLMutexTrylock lock(&gLogMutex, 5);
|
||||
if (!lock.isLocked())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1283,11 +1248,11 @@ namespace LLError
|
|||
|
||||
std::ostringstream* Log::out()
|
||||
{
|
||||
LogLock lock;
|
||||
LLMutexTrylock lock(&gLogMutex,5);
|
||||
// If we hit a logging request very late during shutdown processing,
|
||||
// when either of the relevant LLSingletons has already been deleted,
|
||||
// DO NOT resurrect them.
|
||||
if (lock.ok() && ! (Settings::wasDeleted() || Globals::wasDeleted()))
|
||||
if (lock.isLocked() && ! (Settings::wasDeleted() || Globals::wasDeleted()))
|
||||
{
|
||||
Globals* g = Globals::getInstance();
|
||||
|
||||
|
|
@ -1303,8 +1268,8 @@ namespace LLError
|
|||
|
||||
void Log::flush(std::ostringstream* out, char* message)
|
||||
{
|
||||
LogLock lock;
|
||||
if (!lock.ok())
|
||||
LLMutexTrylock lock(&gLogMutex,5);
|
||||
if (!lock.isLocked())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -1343,8 +1308,8 @@ namespace LLError
|
|||
|
||||
void Log::flush(std::ostringstream* out, const CallSite& site)
|
||||
{
|
||||
LogLock lock;
|
||||
if (!lock.ok())
|
||||
LLMutexTrylock lock(&gLogMutex,5);
|
||||
if (!lock.isLocked())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -1514,69 +1479,6 @@ namespace LLError
|
|||
char** LLCallStacks::sBuffer = NULL ;
|
||||
S32 LLCallStacks::sIndex = 0 ;
|
||||
|
||||
#define SINGLE_THREADED 1
|
||||
|
||||
class CallStacksLogLock
|
||||
{
|
||||
public:
|
||||
CallStacksLogLock();
|
||||
~CallStacksLogLock();
|
||||
|
||||
#if SINGLE_THREADED
|
||||
bool ok() const { return true; }
|
||||
#else
|
||||
bool ok() const { return mOK; }
|
||||
private:
|
||||
bool mLocked;
|
||||
bool mOK;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if SINGLE_THREADED
|
||||
CallStacksLogLock::CallStacksLogLock()
|
||||
{
|
||||
}
|
||||
CallStacksLogLock::~CallStacksLogLock()
|
||||
{
|
||||
}
|
||||
#else
|
||||
CallStacksLogLock::CallStacksLogLock()
|
||||
: mLocked(false), mOK(false)
|
||||
{
|
||||
if (!gCallStacksLogMutexp)
|
||||
{
|
||||
mOK = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const int MAX_RETRIES = 5;
|
||||
for (int attempts = 0; attempts < MAX_RETRIES; ++attempts)
|
||||
{
|
||||
apr_status_t s = apr_thread_mutex_trylock(gCallStacksLogMutexp);
|
||||
if (!APR_STATUS_IS_EBUSY(s))
|
||||
{
|
||||
mLocked = true;
|
||||
mOK = true;
|
||||
return;
|
||||
}
|
||||
|
||||
ms_sleep(1);
|
||||
}
|
||||
|
||||
// We're hosed, we can't get the mutex. Blah.
|
||||
std::cerr << "CallStacksLogLock::CallStacksLogLock: failed to get mutex for log"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
CallStacksLogLock::~CallStacksLogLock()
|
||||
{
|
||||
if (mLocked)
|
||||
{
|
||||
apr_thread_mutex_unlock(gCallStacksLogMutexp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//static
|
||||
void LLCallStacks::allocateStackBuffer()
|
||||
{
|
||||
|
|
@ -1605,8 +1507,8 @@ namespace LLError
|
|||
//static
|
||||
void LLCallStacks::push(const char* function, const int line)
|
||||
{
|
||||
CallStacksLogLock lock;
|
||||
if (!lock.ok())
|
||||
LLMutexTrylock lock(&gCallStacksLogMutex, 5);
|
||||
if (!lock.isLocked())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -1640,8 +1542,8 @@ namespace LLError
|
|||
//static
|
||||
void LLCallStacks::end(std::ostringstream* _out)
|
||||
{
|
||||
CallStacksLogLock lock;
|
||||
if (!lock.ok())
|
||||
LLMutexTrylock lock(&gCallStacksLogMutex, 5);
|
||||
if (!lock.isLocked())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -1662,8 +1564,8 @@ namespace LLError
|
|||
//static
|
||||
void LLCallStacks::print()
|
||||
{
|
||||
CallStacksLogLock lock;
|
||||
if (!lock.ok())
|
||||
LLMutexTrylock lock(&gCallStacksLogMutex, 5);
|
||||
if (!lock.isLocked())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -1700,8 +1602,8 @@ namespace LLError
|
|||
|
||||
bool debugLoggingEnabled(const std::string& tag)
|
||||
{
|
||||
LogLock lock;
|
||||
if (!lock.ok())
|
||||
LLMutexTrylock lock(&gLogMutex, 5);
|
||||
if (!lock.isLocked())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
LLFixedBuffer::LLFixedBuffer(const U32 max_lines)
|
||||
: LLLineBuffer(),
|
||||
mMaxLines(max_lines),
|
||||
mMutex(NULL)
|
||||
mMutex()
|
||||
{
|
||||
mTimer.reset();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,17 +36,16 @@
|
|||
|
||||
void LLInstanceTrackerBase::StaticBase::incrementDepth()
|
||||
{
|
||||
apr_atomic_inc32(&sIterationNestDepth);
|
||||
++sIterationNestDepth;
|
||||
}
|
||||
|
||||
void LLInstanceTrackerBase::StaticBase::decrementDepth()
|
||||
{
|
||||
llassert(sIterationNestDepth);
|
||||
apr_atomic_dec32(&sIterationNestDepth);
|
||||
--sIterationNestDepth;
|
||||
}
|
||||
|
||||
U32 LLInstanceTrackerBase::StaticBase::getDepth()
|
||||
{
|
||||
apr_uint32_t data = apr_atomic_read32(&sIterationNestDepth);
|
||||
return data;
|
||||
return sIterationNestDepth;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#ifndef LL_LLINSTANCETRACKER_H
|
||||
#define LL_LLINSTANCETRACKER_H
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <typeinfo>
|
||||
|
||||
|
|
@ -81,8 +82,12 @@ protected:
|
|||
void decrementDepth();
|
||||
U32 getDepth();
|
||||
private:
|
||||
U32 sIterationNestDepth;
|
||||
};
|
||||
#ifdef LL_WINDOWS
|
||||
std::atomic_uint32_t sIterationNestDepth;
|
||||
#else
|
||||
std::atomic_uint sIterationNestDepth;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
LL_COMMON_API void assert_main_thread();
|
||||
|
|
|
|||
|
|
@ -24,47 +24,22 @@
|
|||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llapr.h"
|
||||
|
||||
#include "apr_portable.h"
|
||||
|
||||
#include "llmutex.h"
|
||||
#include "llthread.h"
|
||||
#include "lltimer.h"
|
||||
|
||||
//============================================================================
|
||||
|
||||
LLMutex::LLMutex(apr_pool_t *poolp) :
|
||||
mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD)
|
||||
LLMutex::LLMutex() :
|
||||
mCount(0),
|
||||
mLockingThread(NO_THREAD)
|
||||
{
|
||||
//if (poolp)
|
||||
//{
|
||||
// mIsLocalPool = FALSE;
|
||||
// mAPRPoolp = poolp;
|
||||
//}
|
||||
//else
|
||||
{
|
||||
mIsLocalPool = TRUE;
|
||||
apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
|
||||
}
|
||||
apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
|
||||
}
|
||||
|
||||
|
||||
LLMutex::~LLMutex()
|
||||
{
|
||||
#if MUTEX_DEBUG
|
||||
//bad assertion, the subclass LLSignal might be "locked", and that's OK
|
||||
//llassert_always(!isLocked()); // better not be locked!
|
||||
#endif
|
||||
if (ll_apr_is_initialized())
|
||||
{
|
||||
apr_thread_mutex_destroy(mAPRMutexp);
|
||||
if (mIsLocalPool)
|
||||
{
|
||||
apr_pool_destroy(mAPRPoolp);
|
||||
}
|
||||
}
|
||||
mAPRMutexp = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -76,7 +51,7 @@ void LLMutex::lock()
|
|||
return;
|
||||
}
|
||||
|
||||
apr_thread_mutex_lock(mAPRMutexp);
|
||||
mMutex.lock();
|
||||
|
||||
#if MUTEX_DEBUG
|
||||
// Have to have the lock before we can access the debug info
|
||||
|
|
@ -106,19 +81,18 @@ void LLMutex::unlock()
|
|||
#endif
|
||||
|
||||
mLockingThread = NO_THREAD;
|
||||
apr_thread_mutex_unlock(mAPRMutexp);
|
||||
mMutex.unlock();
|
||||
}
|
||||
|
||||
bool LLMutex::isLocked()
|
||||
{
|
||||
apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp);
|
||||
if (APR_STATUS_IS_EBUSY(status))
|
||||
if (!mMutex.try_lock())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
apr_thread_mutex_unlock(mAPRMutexp);
|
||||
mMutex.unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -141,8 +115,7 @@ bool LLMutex::trylock()
|
|||
return true;
|
||||
}
|
||||
|
||||
apr_status_t status(apr_thread_mutex_trylock(mAPRMutexp));
|
||||
if (APR_STATUS_IS_EBUSY(status))
|
||||
if (!mMutex.try_lock())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -161,45 +134,95 @@ bool LLMutex::trylock()
|
|||
|
||||
//============================================================================
|
||||
|
||||
LLCondition::LLCondition(apr_pool_t *poolp) :
|
||||
LLMutex(poolp)
|
||||
LLCondition::LLCondition() :
|
||||
LLMutex()
|
||||
{
|
||||
// base class (LLMutex) has already ensured that mAPRPoolp is set up.
|
||||
|
||||
apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
|
||||
}
|
||||
|
||||
|
||||
LLCondition::~LLCondition()
|
||||
{
|
||||
apr_thread_cond_destroy(mAPRCondp);
|
||||
mAPRCondp = NULL;
|
||||
}
|
||||
|
||||
|
||||
void LLCondition::wait()
|
||||
{
|
||||
if (!isLocked())
|
||||
{ //mAPRMutexp MUST be locked before calling apr_thread_cond_wait
|
||||
apr_thread_mutex_lock(mAPRMutexp);
|
||||
#if MUTEX_DEBUG
|
||||
// avoid asserts on destruction in non-release builds
|
||||
U32 id = LLThread::currentID();
|
||||
mIsLocked[id] = TRUE;
|
||||
#endif
|
||||
}
|
||||
apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
|
||||
std::unique_lock< std::mutex > lock(mMutex);
|
||||
mCond.wait(lock);
|
||||
}
|
||||
|
||||
void LLCondition::signal()
|
||||
{
|
||||
apr_thread_cond_signal(mAPRCondp);
|
||||
mCond.notify_one();
|
||||
}
|
||||
|
||||
void LLCondition::broadcast()
|
||||
{
|
||||
apr_thread_cond_broadcast(mAPRCondp);
|
||||
mCond.notify_all();
|
||||
}
|
||||
|
||||
|
||||
|
||||
LLMutexTrylock::LLMutexTrylock(LLMutex* mutex)
|
||||
: mMutex(mutex),
|
||||
mLocked(false)
|
||||
{
|
||||
if (mMutex)
|
||||
mLocked = mMutex->trylock();
|
||||
}
|
||||
|
||||
LLMutexTrylock::LLMutexTrylock(LLMutex* mutex, U32 aTries, U32 delay_ms)
|
||||
: mMutex(mutex),
|
||||
mLocked(false)
|
||||
{
|
||||
if (!mMutex)
|
||||
return;
|
||||
|
||||
for (U32 i = 0; i < aTries; ++i)
|
||||
{
|
||||
mLocked = mMutex->trylock();
|
||||
if (mLocked)
|
||||
break;
|
||||
ms_sleep(delay_ms);
|
||||
}
|
||||
}
|
||||
|
||||
LLMutexTrylock::~LLMutexTrylock()
|
||||
{
|
||||
if (mMutex && mLocked)
|
||||
mMutex->unlock();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// LLScopedLock
|
||||
//
|
||||
LLScopedLock::LLScopedLock(std::mutex* mutex) : mMutex(mutex)
|
||||
{
|
||||
if(mutex)
|
||||
{
|
||||
mutex->lock();
|
||||
mLocked = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mLocked = false;
|
||||
}
|
||||
}
|
||||
|
||||
LLScopedLock::~LLScopedLock()
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
|
||||
void LLScopedLock::unlock()
|
||||
{
|
||||
if(mLocked)
|
||||
{
|
||||
mMutex->unlock();
|
||||
mLocked = false;
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
|
|
|||
|
|
@ -28,6 +28,19 @@
|
|||
#define LL_LLMUTEX_H
|
||||
|
||||
#include "stdtypes.h"
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#if LL_WINDOWS
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable:4265)
|
||||
#endif
|
||||
// 'std::_Pad' : class has virtual functions, but destructor is not virtual
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
#if LL_WINDOWS
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
|
@ -37,10 +50,6 @@
|
|||
#include <map>
|
||||
#endif
|
||||
|
||||
struct apr_thread_mutex_t;
|
||||
struct apr_pool_t;
|
||||
struct apr_thread_cond_t;
|
||||
|
||||
class LL_COMMON_API LLMutex
|
||||
{
|
||||
public:
|
||||
|
|
@ -49,7 +58,7 @@ public:
|
|||
NO_THREAD = 0xFFFFFFFF
|
||||
} e_locking_thread;
|
||||
|
||||
LLMutex(apr_pool_t *apr_poolp = NULL); // NULL pool constructs a new pool for the mutex
|
||||
LLMutex();
|
||||
virtual ~LLMutex();
|
||||
|
||||
void lock(); // blocks
|
||||
|
|
@ -60,13 +69,10 @@ public:
|
|||
U32 lockingThread() const; //get ID of locking thread
|
||||
|
||||
protected:
|
||||
apr_thread_mutex_t *mAPRMutexp;
|
||||
std::mutex mMutex;
|
||||
mutable U32 mCount;
|
||||
mutable U32 mLockingThread;
|
||||
|
||||
apr_pool_t *mAPRPoolp;
|
||||
BOOL mIsLocalPool;
|
||||
|
||||
#if MUTEX_DEBUG
|
||||
std::map<U32, BOOL> mIsLocked;
|
||||
#endif
|
||||
|
|
@ -76,7 +82,7 @@ protected:
|
|||
class LL_COMMON_API LLCondition : public LLMutex
|
||||
{
|
||||
public:
|
||||
LLCondition(apr_pool_t* apr_poolp); // Defaults to global pool, could use the thread pool as well.
|
||||
LLCondition();
|
||||
~LLCondition();
|
||||
|
||||
void wait(); // blocks
|
||||
|
|
@ -84,7 +90,7 @@ public:
|
|||
void broadcast();
|
||||
|
||||
protected:
|
||||
apr_thread_cond_t* mAPRCondp;
|
||||
std::condition_variable mCond;
|
||||
};
|
||||
|
||||
class LLMutexLock
|
||||
|
|
@ -119,19 +125,9 @@ private:
|
|||
class LLMutexTrylock
|
||||
{
|
||||
public:
|
||||
LLMutexTrylock(LLMutex* mutex)
|
||||
: mMutex(mutex),
|
||||
mLocked(false)
|
||||
{
|
||||
if (mMutex)
|
||||
mLocked = mMutex->trylock();
|
||||
}
|
||||
|
||||
~LLMutexTrylock()
|
||||
{
|
||||
if (mMutex && mLocked)
|
||||
mMutex->unlock();
|
||||
}
|
||||
LLMutexTrylock(LLMutex* mutex);
|
||||
LLMutexTrylock(LLMutex* mutex, U32 aTries, U32 delay_ms = 10);
|
||||
~LLMutexTrylock();
|
||||
|
||||
bool isLocked() const
|
||||
{
|
||||
|
|
@ -142,4 +138,43 @@ private:
|
|||
LLMutex* mMutex;
|
||||
bool mLocked;
|
||||
};
|
||||
#endif // LL_LLTHREAD_H
|
||||
|
||||
/**
|
||||
* @class LLScopedLock
|
||||
* @brief Small class to help lock and unlock mutexes.
|
||||
*
|
||||
* The constructor handles the lock, and the destructor handles
|
||||
* the unlock. Instances of this class are <b>not</b> thread safe.
|
||||
*/
|
||||
class LL_COMMON_API LLScopedLock : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor which accepts a mutex, and locks it.
|
||||
*
|
||||
* @param mutex An allocated mutex. If you pass in NULL,
|
||||
* this wrapper will not lock.
|
||||
*/
|
||||
LLScopedLock(std::mutex* mutex);
|
||||
|
||||
/**
|
||||
* @brief Destructor which unlocks the mutex if still locked.
|
||||
*/
|
||||
~LLScopedLock();
|
||||
|
||||
/**
|
||||
* @brief Check lock.
|
||||
*/
|
||||
bool isLocked() const { return mLocked; }
|
||||
|
||||
/**
|
||||
* @brief This method unlocks the mutex.
|
||||
*/
|
||||
void unlock();
|
||||
|
||||
protected:
|
||||
bool mLocked;
|
||||
std::mutex* mMutex;
|
||||
};
|
||||
|
||||
#endif // LL_LLMUTEX_H
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "llapr.h"
|
||||
#include "llatomic.h"
|
||||
|
||||
#include "llthread.h"
|
||||
#include "llsimplehash.h"
|
||||
|
|
@ -128,7 +128,7 @@ public:
|
|||
};
|
||||
|
||||
protected:
|
||||
LLAtomic32<status_t> mStatus;
|
||||
LLAtomicBase<status_t> mStatus;
|
||||
U32 mPriority;
|
||||
U32 mFlags;
|
||||
};
|
||||
|
|
@ -198,7 +198,7 @@ public:
|
|||
protected:
|
||||
BOOL mThreaded; // if false, run on main thread and do updates during update()
|
||||
BOOL mStarted; // required when mThreaded is false to call startThread() from update()
|
||||
LLAtomic32<BOOL> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
|
||||
LLAtomicBool mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
|
||||
|
||||
typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;
|
||||
request_queue_t mRequestQueue;
|
||||
|
|
|
|||
|
|
@ -29,25 +29,9 @@
|
|||
|
||||
#include "llerror.h"
|
||||
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
#include "llthread.h"
|
||||
#include "llapr.h"
|
||||
#endif
|
||||
|
||||
LLRefCount::LLRefCount(const LLRefCount& other)
|
||||
: mRef(0)
|
||||
{
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
if(gAPRPoolp)
|
||||
{
|
||||
mMutexp = new LLMutex(gAPRPoolp) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
mMutexp = NULL ;
|
||||
}
|
||||
mCrashAtUnlock = FALSE ;
|
||||
#endif
|
||||
}
|
||||
|
||||
LLRefCount& LLRefCount::operator=(const LLRefCount&)
|
||||
|
|
@ -59,17 +43,6 @@ LLRefCount& LLRefCount::operator=(const LLRefCount&)
|
|||
LLRefCount::LLRefCount() :
|
||||
mRef(0)
|
||||
{
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
if(gAPRPoolp)
|
||||
{
|
||||
mMutexp = new LLMutex(gAPRPoolp) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
mMutexp = NULL ;
|
||||
}
|
||||
mCrashAtUnlock = FALSE ;
|
||||
#endif
|
||||
}
|
||||
|
||||
LLRefCount::~LLRefCount()
|
||||
|
|
@ -78,87 +51,5 @@ LLRefCount::~LLRefCount()
|
|||
{
|
||||
LL_ERRS() << "deleting non-zero reference" << LL_ENDL;
|
||||
}
|
||||
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
if(gAPRPoolp)
|
||||
{
|
||||
delete mMutexp ;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
void LLRefCount::ref() const
|
||||
{
|
||||
if(mMutexp)
|
||||
{
|
||||
if(mMutexp->isLocked())
|
||||
{
|
||||
mCrashAtUnlock = TRUE ;
|
||||
LL_ERRS() << "the mutex is locked by the thread: " << mLockedThreadID
|
||||
<< " Current thread: " << LLThread::currentID() << LL_ENDL ;
|
||||
}
|
||||
|
||||
mMutexp->lock() ;
|
||||
mLockedThreadID = LLThread::currentID() ;
|
||||
|
||||
mRef++;
|
||||
|
||||
if(mCrashAtUnlock)
|
||||
{
|
||||
while(1); //crash here.
|
||||
}
|
||||
mMutexp->unlock() ;
|
||||
}
|
||||
else
|
||||
{
|
||||
mRef++;
|
||||
}
|
||||
}
|
||||
|
||||
S32 LLRefCount::unref() const
|
||||
{
|
||||
if(mMutexp)
|
||||
{
|
||||
if(mMutexp->isLocked())
|
||||
{
|
||||
mCrashAtUnlock = TRUE ;
|
||||
LL_ERRS() << "the mutex is locked by the thread: " << mLockedThreadID
|
||||
<< " Current thread: " << LLThread::currentID() << LL_ENDL ;
|
||||
}
|
||||
|
||||
mMutexp->lock() ;
|
||||
mLockedThreadID = LLThread::currentID() ;
|
||||
|
||||
llassert(mRef >= 1);
|
||||
if (0 == --mRef)
|
||||
{
|
||||
if(mCrashAtUnlock)
|
||||
{
|
||||
while(1); //crash here.
|
||||
}
|
||||
mMutexp->unlock() ;
|
||||
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(mCrashAtUnlock)
|
||||
{
|
||||
while(1); //crash here.
|
||||
}
|
||||
mMutexp->unlock() ;
|
||||
return mRef;
|
||||
}
|
||||
else
|
||||
{
|
||||
llassert(mRef >= 1);
|
||||
if (0 == --mRef)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return mRef;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -29,12 +29,7 @@
|
|||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include "llmutex.h"
|
||||
#include "llapr.h"
|
||||
|
||||
#define LL_REF_COUNT_DEBUG 0
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
class LLMutex ;
|
||||
#endif
|
||||
#include "llatomic.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// RefCount objects should generally only be accessed by way of LLPointer<>'s
|
||||
|
|
@ -51,10 +46,6 @@ protected:
|
|||
public:
|
||||
LLRefCount();
|
||||
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
void ref() const ;
|
||||
S32 unref() const ;
|
||||
#else
|
||||
inline void ref() const
|
||||
{
|
||||
mRef++;
|
||||
|
|
@ -69,8 +60,7 @@ public:
|
|||
return 0;
|
||||
}
|
||||
return mRef;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//NOTE: when passing around a const LLRefCount object, this can return different results
|
||||
// at different types, since mRef is mutable
|
||||
|
|
@ -81,12 +71,6 @@ public:
|
|||
|
||||
private:
|
||||
mutable S32 mRef;
|
||||
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
LLMutex* mMutexp ;
|
||||
mutable U32 mLockedThreadID ;
|
||||
mutable BOOL mCrashAtUnlock ;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -123,8 +107,8 @@ public:
|
|||
void unref()
|
||||
{
|
||||
llassert(mRef >= 1);
|
||||
if ((--mRef) == 0) // See note in llapr.h on atomic decrement operator return value.
|
||||
{
|
||||
if ((--mRef) == 0)
|
||||
{
|
||||
// If we hit zero, the caller should be the only smart pointer owning the object and we can delete it.
|
||||
// It is technically possible for a vanilla pointer to mess this up, or another thread to
|
||||
// jump in, find this object, create another smart pointer and end up dangling, but if
|
||||
|
|
@ -140,7 +124,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
LLAtomic32< S32 > mRef;
|
||||
LLAtomicS32 mRef;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -268,10 +268,32 @@ LLOSInfo::LLOSInfo() :
|
|||
}
|
||||
}
|
||||
|
||||
S32 ubr = 0; // Windows 10 Update Build Revision, can be retrieved from a registry
|
||||
if (mMajorVer == 10)
|
||||
{
|
||||
DWORD cbData(sizeof(DWORD));
|
||||
DWORD data(0);
|
||||
HKEY key;
|
||||
BOOL ret_code = RegOpenKeyExW(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), 0, KEY_READ, &key);
|
||||
if (ERROR_SUCCESS == ret_code)
|
||||
{
|
||||
ret_code = RegQueryValueExW(key, L"UBR", 0, NULL, reinterpret_cast<LPBYTE>(&data), &cbData);
|
||||
if (ERROR_SUCCESS == ret_code)
|
||||
{
|
||||
ubr = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mOSString = mOSStringSimple;
|
||||
if (mBuild > 0)
|
||||
{
|
||||
mOSString += llformat("(Build %d)", mBuild);
|
||||
mOSString += llformat("(Build %d", mBuild);
|
||||
if (ubr > 0)
|
||||
{
|
||||
mOSString += llformat(".%d", ubr);
|
||||
}
|
||||
mOSString += ")";
|
||||
}
|
||||
|
||||
LLStringUtil::trim(mOSStringSimple);
|
||||
|
|
|
|||
|
|
@ -116,29 +116,27 @@ void LLThread::registerThreadID()
|
|||
//
|
||||
// Handed to the APR thread creation function
|
||||
//
|
||||
void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap)
|
||||
void LLThread::threadRun()
|
||||
{
|
||||
LLThread *threadp = (LLThread *)datap;
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
set_thread_name(-1, threadp->mName.c_str());
|
||||
set_thread_name(-1, mName.c_str());
|
||||
#endif
|
||||
|
||||
// for now, hard code all LLThreads to report to single master thread recorder, which is known to be running on main thread
|
||||
threadp->mRecorder = new LLTrace::ThreadRecorder(*LLTrace::get_master_thread_recorder());
|
||||
mRecorder = new LLTrace::ThreadRecorder(*LLTrace::get_master_thread_recorder());
|
||||
|
||||
sThreadID = threadp->mID;
|
||||
sThreadID = mID;
|
||||
|
||||
// Run the user supplied function
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
threadp->run();
|
||||
run();
|
||||
}
|
||||
catch (const LLContinueError &e)
|
||||
{
|
||||
LL_WARNS("THREAD") << "ContinueException on thread '" << threadp->mName <<
|
||||
LL_WARNS("THREAD") << "ContinueException on thread '" << mName <<
|
||||
"' reentering run(). Error what is: '" << e.what() << "'" << LL_ENDL;
|
||||
//output possible call stacks to log file.
|
||||
LLError::LLCallStacks::print();
|
||||
|
|
@ -153,41 +151,27 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
|
|||
//LL_INFOS() << "LLThread::staticRun() Exiting: " << threadp->mName << LL_ENDL;
|
||||
|
||||
|
||||
delete threadp->mRecorder;
|
||||
threadp->mRecorder = NULL;
|
||||
delete mRecorder;
|
||||
mRecorder = NULL;
|
||||
|
||||
// We're done with the run function, this thread is done executing now.
|
||||
//NB: we are using this flag to sync across threads...we really need memory barriers here
|
||||
// Todo: add LLMutex per thread instead of flag?
|
||||
// We are using "while (mStatus != STOPPED) {ms_sleep();}" everywhere.
|
||||
threadp->mStatus = STOPPED;
|
||||
|
||||
return NULL;
|
||||
mStatus = STOPPED;
|
||||
}
|
||||
|
||||
LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
|
||||
mPaused(FALSE),
|
||||
mName(name),
|
||||
mAPRThreadp(NULL),
|
||||
mThreadp(NULL),
|
||||
mStatus(STOPPED),
|
||||
mRecorder(NULL)
|
||||
{
|
||||
|
||||
mID = ++sIDIter;
|
||||
|
||||
// Thread creation probably CAN be paranoid about APR being initialized, if necessary
|
||||
if (poolp)
|
||||
{
|
||||
mIsLocalPool = FALSE;
|
||||
mAPRPoolp = poolp;
|
||||
}
|
||||
else
|
||||
{
|
||||
mIsLocalPool = TRUE;
|
||||
apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
|
||||
}
|
||||
mRunCondition = new LLCondition(mAPRPoolp);
|
||||
mDataLock = new LLMutex(mAPRPoolp);
|
||||
mRunCondition = new LLCondition();
|
||||
mDataLock = new LLMutex();
|
||||
mLocalAPRFilePoolp = NULL ;
|
||||
}
|
||||
|
||||
|
|
@ -217,7 +201,7 @@ void LLThread::shutdown()
|
|||
|
||||
// Warning! If you somehow call the thread destructor from itself,
|
||||
// the thread will die in an unclean fashion!
|
||||
if (mAPRThreadp)
|
||||
if (mThreadp)
|
||||
{
|
||||
if (!isStopped())
|
||||
{
|
||||
|
|
@ -248,14 +232,19 @@ void LLThread::shutdown()
|
|||
{
|
||||
// This thread just wouldn't stop, even though we gave it time
|
||||
//LL_WARNS() << "LLThread::~LLThread() exiting thread before clean exit!" << LL_ENDL;
|
||||
// Put a stake in its heart.
|
||||
apr_thread_exit(mAPRThreadp, -1);
|
||||
// Put a stake in its heart. (A very hostile method to force a thread to quit)
|
||||
#if LL_WINDOWS
|
||||
TerminateThread(mNativeHandle, 0);
|
||||
#else
|
||||
pthread_cancel(mNativeHandle);
|
||||
#endif
|
||||
|
||||
delete mRecorder;
|
||||
mRecorder = NULL;
|
||||
mStatus = STOPPED;
|
||||
return;
|
||||
}
|
||||
mAPRThreadp = NULL;
|
||||
mThreadp = NULL;
|
||||
}
|
||||
|
||||
delete mRunCondition;
|
||||
|
|
@ -263,12 +252,6 @@ void LLThread::shutdown()
|
|||
|
||||
delete mDataLock;
|
||||
mDataLock = NULL;
|
||||
|
||||
if (mIsLocalPool && mAPRPoolp)
|
||||
{
|
||||
apr_pool_destroy(mAPRPoolp);
|
||||
mAPRPoolp = 0;
|
||||
}
|
||||
|
||||
if (mRecorder)
|
||||
{
|
||||
|
|
@ -287,19 +270,15 @@ void LLThread::start()
|
|||
// Set thread state to running
|
||||
mStatus = RUNNING;
|
||||
|
||||
apr_status_t status =
|
||||
apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);
|
||||
|
||||
if(status == APR_SUCCESS)
|
||||
{
|
||||
// We won't bother joining
|
||||
apr_thread_detach(mAPRThreadp);
|
||||
try
|
||||
{
|
||||
mThreadp = new std::thread(std::bind(&LLThread::threadRun, this));
|
||||
mNativeHandle = mThreadp->native_handle();
|
||||
}
|
||||
else
|
||||
catch (std::system_error& ex)
|
||||
{
|
||||
mStatus = STOPPED;
|
||||
LL_WARNS() << "failed to start thread " << mName << LL_ENDL;
|
||||
ll_apr_warn_status(status);
|
||||
LL_WARNS() << "failed to start thread " << mName << " " << ex.what() << LL_ENDL;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -376,11 +355,7 @@ U32 LLThread::currentID()
|
|||
// static
|
||||
void LLThread::yield()
|
||||
{
|
||||
#if LL_LINUX || LL_SOLARIS
|
||||
sched_yield(); // annoyingly, apr_thread_yield is a noop on linux...
|
||||
#else
|
||||
apr_thread_yield();
|
||||
#endif
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
void LLThread::wake()
|
||||
|
|
@ -413,7 +388,7 @@ void LLThreadSafeRefCount::initThreadSafeRefCount()
|
|||
{
|
||||
if (!sMutex)
|
||||
{
|
||||
sMutex = new LLMutex(0);
|
||||
sMutex = new LLMutex();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,10 +29,10 @@
|
|||
|
||||
#include "llapp.h"
|
||||
#include "llapr.h"
|
||||
#include "apr_thread_cond.h"
|
||||
#include "boost/intrusive_ptr.hpp"
|
||||
#include "llmutex.h"
|
||||
#include "llrefcount.h"
|
||||
#include <thread>
|
||||
|
||||
LL_COMMON_API void assert_main_thread();
|
||||
|
||||
|
|
@ -86,7 +86,6 @@ public:
|
|||
// this kicks off the apr thread
|
||||
void start(void);
|
||||
|
||||
apr_pool_t *getAPRPool() { return mAPRPoolp; }
|
||||
LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; }
|
||||
|
||||
U32 getID() const { return mID; }
|
||||
|
|
@ -97,19 +96,18 @@ public:
|
|||
static void registerThreadID();
|
||||
|
||||
private:
|
||||
BOOL mPaused;
|
||||
bool mPaused;
|
||||
std::thread::native_handle_type mNativeHandle; // for termination in case of issues
|
||||
|
||||
// static function passed to APR thread creation routine
|
||||
static void *APR_THREAD_FUNC staticRun(struct apr_thread_t *apr_threadp, void *datap);
|
||||
void threadRun();
|
||||
|
||||
protected:
|
||||
std::string mName;
|
||||
class LLCondition* mRunCondition;
|
||||
LLMutex* mDataLock;
|
||||
|
||||
apr_thread_t *mAPRThreadp;
|
||||
apr_pool_t *mAPRPoolp;
|
||||
BOOL mIsLocalPool;
|
||||
std::thread *mThreadp;
|
||||
EThreadStatus mStatus;
|
||||
U32 mID;
|
||||
LLTrace::ThreadRecorder* mRecorder;
|
||||
|
|
|
|||
|
|
@ -24,87 +24,6 @@
|
|||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include <apr_pools.h>
|
||||
#include <apr_queue.h>
|
||||
#include "llthreadsafequeue.h"
|
||||
#include "llexception.h"
|
||||
|
||||
|
||||
|
||||
// LLThreadSafeQueueImplementation
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(apr_pool_t * pool, unsigned int capacity):
|
||||
mOwnsPool(pool == 0),
|
||||
mPool(pool),
|
||||
mQueue(0)
|
||||
{
|
||||
if(mOwnsPool) {
|
||||
apr_status_t status = apr_pool_create(&mPool, 0);
|
||||
if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate pool"));
|
||||
} else {
|
||||
; // No op.
|
||||
}
|
||||
|
||||
apr_status_t status = apr_queue_create(&mQueue, capacity, mPool);
|
||||
if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate queue"));
|
||||
}
|
||||
|
||||
|
||||
LLThreadSafeQueueImplementation::~LLThreadSafeQueueImplementation()
|
||||
{
|
||||
if(mQueue != 0) {
|
||||
if(apr_queue_size(mQueue) != 0) LL_WARNS() <<
|
||||
"terminating queue which still contains " << apr_queue_size(mQueue) <<
|
||||
" elements;" << "memory will be leaked" << LL_ENDL;
|
||||
apr_queue_term(mQueue);
|
||||
}
|
||||
if(mOwnsPool && (mPool != 0)) apr_pool_destroy(mPool);
|
||||
}
|
||||
|
||||
|
||||
void LLThreadSafeQueueImplementation::pushFront(void * element)
|
||||
{
|
||||
apr_status_t status = apr_queue_push(mQueue, element);
|
||||
|
||||
if(status == APR_EINTR) {
|
||||
LLTHROW(LLThreadSafeQueueInterrupt());
|
||||
} else if(status != APR_SUCCESS) {
|
||||
LLTHROW(LLThreadSafeQueueError("push failed"));
|
||||
} else {
|
||||
; // Success.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LLThreadSafeQueueImplementation::tryPushFront(void * element){
|
||||
return apr_queue_trypush(mQueue, element) == APR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
void * LLThreadSafeQueueImplementation::popBack(void)
|
||||
{
|
||||
void * element;
|
||||
apr_status_t status = apr_queue_pop(mQueue, &element);
|
||||
|
||||
if(status == APR_EINTR) {
|
||||
LLTHROW(LLThreadSafeQueueInterrupt());
|
||||
} else if(status != APR_SUCCESS) {
|
||||
LLTHROW(LLThreadSafeQueueError("pop failed"));
|
||||
} else {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LLThreadSafeQueueImplementation::tryPopBack(void *& element)
|
||||
{
|
||||
return apr_queue_trypop(mQueue, &element) == APR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
size_t LLThreadSafeQueueImplementation::size()
|
||||
{
|
||||
return apr_queue_size(mQueue);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,12 +28,20 @@
|
|||
#define LL_LLTHREADSAFEQUEUE_H
|
||||
|
||||
#include "llexception.h"
|
||||
#include <deque>
|
||||
#include <string>
|
||||
|
||||
#if LL_WINDOWS
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable:4265)
|
||||
#endif
|
||||
// 'std::_Pad' : class has virtual functions, but destructor is not virtual
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
struct apr_pool_t; // From apr_pools.h
|
||||
class LLThreadSafeQueueImplementation; // See below.
|
||||
|
||||
#if LL_WINDOWS
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
//
|
||||
// A general queue exception.
|
||||
|
|
@ -64,31 +72,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
struct apr_queue_t; // From apr_queue.h
|
||||
|
||||
|
||||
//
|
||||
// Implementation details.
|
||||
//
|
||||
class LL_COMMON_API LLThreadSafeQueueImplementation
|
||||
{
|
||||
public:
|
||||
LLThreadSafeQueueImplementation(apr_pool_t * pool, unsigned int capacity);
|
||||
~LLThreadSafeQueueImplementation();
|
||||
void pushFront(void * element);
|
||||
bool tryPushFront(void * element);
|
||||
void * popBack(void);
|
||||
bool tryPopBack(void *& element);
|
||||
size_t size();
|
||||
|
||||
private:
|
||||
bool mOwnsPool;
|
||||
apr_pool_t * mPool;
|
||||
apr_queue_t * mQueue;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Implements a thread safe FIFO.
|
||||
//
|
||||
|
|
@ -100,7 +83,7 @@ public:
|
|||
|
||||
// If the pool is set to NULL one will be allocated and managed by this
|
||||
// queue.
|
||||
LLThreadSafeQueue(apr_pool_t * pool = 0, unsigned int capacity = 1024);
|
||||
LLThreadSafeQueue(U32 capacity = 1024);
|
||||
|
||||
// Add an element to the front of queue (will block if the queue has
|
||||
// reached capacity).
|
||||
|
|
@ -128,77 +111,103 @@ public:
|
|||
size_t size();
|
||||
|
||||
private:
|
||||
LLThreadSafeQueueImplementation mImplementation;
|
||||
std::deque< ElementT > mStorage;
|
||||
U32 mCapacity;
|
||||
|
||||
std::mutex mLock;
|
||||
std::condition_variable mCapacityCond;
|
||||
std::condition_variable mEmptyCond;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// LLThreadSafeQueue
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
template<typename ElementT>
|
||||
LLThreadSafeQueue<ElementT>::LLThreadSafeQueue(apr_pool_t * pool, unsigned int capacity):
|
||||
mImplementation(pool, capacity)
|
||||
LLThreadSafeQueue<ElementT>::LLThreadSafeQueue(U32 capacity) :
|
||||
mCapacity(capacity)
|
||||
{
|
||||
; // No op.
|
||||
}
|
||||
|
||||
|
||||
template<typename ElementT>
|
||||
void LLThreadSafeQueue<ElementT>::pushFront(ElementT const & element)
|
||||
{
|
||||
ElementT * elementCopy = new ElementT(element);
|
||||
try {
|
||||
mImplementation.pushFront(elementCopy);
|
||||
} catch (LLThreadSafeQueueInterrupt) {
|
||||
delete elementCopy;
|
||||
throw;
|
||||
}
|
||||
while (true)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock1(mLock);
|
||||
|
||||
if (mStorage.size() < mCapacity)
|
||||
{
|
||||
mStorage.push_front(element);
|
||||
mEmptyCond.notify_one();
|
||||
return;
|
||||
}
|
||||
|
||||
// Storage Full. Wait for signal.
|
||||
mCapacityCond.wait(lock1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename ElementT>
|
||||
bool LLThreadSafeQueue<ElementT>::tryPushFront(ElementT const & element)
|
||||
{
|
||||
ElementT * elementCopy = new ElementT(element);
|
||||
bool result = mImplementation.tryPushFront(elementCopy);
|
||||
if(!result) delete elementCopy;
|
||||
return result;
|
||||
std::unique_lock<std::mutex> lock1(mLock, std::defer_lock);
|
||||
if (!lock1.try_lock())
|
||||
return false;
|
||||
|
||||
if (mStorage.size() >= mCapacity)
|
||||
return false;
|
||||
|
||||
mStorage.push_front(element);
|
||||
mEmptyCond.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename ElementT>
|
||||
ElementT LLThreadSafeQueue<ElementT>::popBack(void)
|
||||
{
|
||||
ElementT * element = reinterpret_cast<ElementT *> (mImplementation.popBack());
|
||||
ElementT result(*element);
|
||||
delete element;
|
||||
return result;
|
||||
while (true)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock1(mLock);
|
||||
|
||||
if (!mStorage.empty())
|
||||
{
|
||||
ElementT value = mStorage.back();
|
||||
mStorage.pop_back();
|
||||
mCapacityCond.notify_one();
|
||||
return value;
|
||||
}
|
||||
|
||||
// Storage empty. Wait for signal.
|
||||
mEmptyCond.wait(lock1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename ElementT>
|
||||
bool LLThreadSafeQueue<ElementT>::tryPopBack(ElementT & element)
|
||||
{
|
||||
void * storedElement;
|
||||
bool result = mImplementation.tryPopBack(storedElement);
|
||||
if(result) {
|
||||
ElementT * elementPtr = reinterpret_cast<ElementT *>(storedElement);
|
||||
element = *elementPtr;
|
||||
delete elementPtr;
|
||||
} else {
|
||||
; // No op.
|
||||
}
|
||||
return result;
|
||||
std::unique_lock<std::mutex> lock1(mLock, std::defer_lock);
|
||||
if (!lock1.try_lock())
|
||||
return false;
|
||||
|
||||
if (mStorage.empty())
|
||||
return false;
|
||||
|
||||
element = mStorage.back();
|
||||
mStorage.pop_back();
|
||||
mCapacityCond.notify_one();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename ElementT>
|
||||
size_t LLThreadSafeQueue<ElementT>::size(void)
|
||||
{
|
||||
return mImplementation.size();
|
||||
std::lock_guard<std::mutex> lock(mLock);
|
||||
return mStorage.size();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -738,7 +738,7 @@ void LLUUID::getCurrentTime(uuid_time_t *timestamp)
|
|||
getSystemTime(&time_last);
|
||||
uuids_this_tick = uuids_per_tick;
|
||||
init = TRUE;
|
||||
mMutex = new LLMutex(NULL);
|
||||
mMutex = new LLMutex();
|
||||
}
|
||||
|
||||
uuid_time_t time_now = {0,0};
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded, bool should_pause) :
|
||||
LLQueuedThread(name, threaded, should_pause)
|
||||
{
|
||||
mDeleteMutex = new LLMutex(NULL);
|
||||
mDeleteMutex = new LLMutex();
|
||||
|
||||
if(!mLocalAPRFilePoolp)
|
||||
{
|
||||
|
|
@ -204,7 +204,7 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na
|
|||
mWorkerClassName(name),
|
||||
mRequestHandle(LLWorkerThread::nullHandle()),
|
||||
mRequestPriority(LLWorkerThread::PRIORITY_NORMAL),
|
||||
mMutex(NULL),
|
||||
mMutex(),
|
||||
mWorkFlags(0)
|
||||
{
|
||||
if (!mWorkerThread)
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
#include <string>
|
||||
|
||||
#include "llqueuedthread.h"
|
||||
#include "llapr.h"
|
||||
#include "llatomic.h"
|
||||
|
||||
#define USE_FRAME_CALLBACK_MANAGER 0
|
||||
|
||||
|
|
|
|||
|
|
@ -555,6 +555,11 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
|
|||
// about 700 or so requests and starts issuing TCP RSTs to
|
||||
// new connections. Reuse the DNS lookups for even a few
|
||||
// seconds and no RSTs.
|
||||
//
|
||||
// -1 stores forever
|
||||
// 0 never stores
|
||||
// any other positive number specifies seconds
|
||||
// supposedly curl 7.62.0 can use TTL by default, otherwise default is 60 seconds
|
||||
check_curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, dnsCacheTimeout);
|
||||
|
||||
if (gpolicy.mUseLLProxy)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llapr.h"
|
||||
#include "llatomic.h"
|
||||
#include "httpcommon.h"
|
||||
#include "httprequest.h"
|
||||
#include "_httppolicyglobal.h"
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
#include <boost/thread.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
|
||||
#include "llapr.h"
|
||||
#include "llatomic.h"
|
||||
|
||||
|
||||
namespace LLCoreInt
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include <boost/function.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
|
||||
#include "apr.h" // thread-related functions
|
||||
#include "_refcounted.h"
|
||||
|
||||
namespace LLCoreInt
|
||||
|
|
|
|||
|
|
@ -333,7 +333,7 @@ LLMutex *getCurlMutex()
|
|||
|
||||
if (!sHandleMutexp)
|
||||
{
|
||||
sHandleMutexp = new LLMutex(NULL);
|
||||
sHandleMutexp = new LLMutex();
|
||||
}
|
||||
|
||||
return sHandleMutexp;
|
||||
|
|
@ -389,7 +389,7 @@ void initialize()
|
|||
S32 mutex_count = CRYPTO_num_locks();
|
||||
for (S32 i = 0; i < mutex_count; i++)
|
||||
{
|
||||
sSSLMutex.push_back(LLMutex_ptr(new LLMutex(NULL)));
|
||||
sSSLMutex.push_back(LLMutex_ptr(new LLMutex()));
|
||||
}
|
||||
CRYPTO_set_id_callback(&ssl_thread_id);
|
||||
CRYPTO_set_locking_callback(&ssl_locking_callback);
|
||||
|
|
|
|||
|
|
@ -2903,6 +2903,13 @@ void HttpRequestTestObjectType::test<22>()
|
|||
|
||||
set_test_name("BUG-2295");
|
||||
|
||||
#if LL_WINDOWS && ADDRESS_SIZE == 64
|
||||
// teamcity win64 builds freeze on this test, if you figure out the cause, please fix it
|
||||
if (getenv("TEAMCITY_PROJECT_NAME"))
|
||||
{
|
||||
skip("BUG-2295 - partial load on W64 causes freeze");
|
||||
}
|
||||
#endif
|
||||
// Handler can be stack-allocated *if* there are no dangling
|
||||
// references to it after completion of this method.
|
||||
// Create before memory record as the string copy will bump numbers.
|
||||
|
|
@ -2921,6 +2928,7 @@ void HttpRequestTestObjectType::test<22>()
|
|||
// options set
|
||||
options = HttpOptions::ptr_t(new HttpOptions());
|
||||
options->setRetries(1); // Partial_File is retryable and can timeout in here
|
||||
options->setDNSCacheTimeout(30);
|
||||
|
||||
// Get singletons created
|
||||
HttpRequest::createService();
|
||||
|
|
@ -3091,7 +3099,11 @@ void HttpRequestTestObjectType::test<23>()
|
|||
set_test_name("HttpRequest GET 503s with 'Retry-After'");
|
||||
|
||||
#if LL_WINDOWS && ADDRESS_SIZE == 64
|
||||
skip("llcorehttp 503-with-retry test hangs on Windows 64");
|
||||
// teamcity win64 builds freeze on this test, if you figure out the cause, please fix it
|
||||
if (getenv("TEAMCITY_PROJECT_NAME"))
|
||||
{
|
||||
skip("llcorehttp 503-with-retry test hangs on Windows 64");
|
||||
}
|
||||
#endif
|
||||
|
||||
// This tests mainly that the code doesn't fall over if
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llapr.h" // thread-related functions
|
||||
#include "llcrashlock.h"
|
||||
#include "lldir.h"
|
||||
#include "llsd.h"
|
||||
|
|
|
|||
|
|
@ -594,7 +594,7 @@ void LLImage::initClass(bool use_new_byte_range, S32 minimal_reverse_byte_range_
|
|||
{
|
||||
sUseNewByteRange = use_new_byte_range;
|
||||
sMinimalReverseByteRangePercent = minimal_reverse_byte_range_percent;
|
||||
sMutex = new LLMutex(NULL);
|
||||
sMutex = new LLMutex();
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
LLImageDecodeThread::LLImageDecodeThread(bool threaded)
|
||||
: LLQueuedThread("imagedecode", threaded)
|
||||
{
|
||||
mCreationMutex = new LLMutex(getAPRPool());
|
||||
mCreationMutex = new LLMutex();
|
||||
}
|
||||
|
||||
//virtual
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ LLVolumeMgr::LLVolumeMgr()
|
|||
{
|
||||
// the LLMutex magic interferes with easy unit testing,
|
||||
// so you now must manually call useMutex() to use it
|
||||
//mDataMutex = new LLMutex(gAPRPoolp);
|
||||
//mDataMutex = new LLMutex();
|
||||
}
|
||||
|
||||
LLVolumeMgr::~LLVolumeMgr()
|
||||
|
|
@ -214,7 +214,7 @@ void LLVolumeMgr::useMutex()
|
|||
{
|
||||
if (!mDataMutex)
|
||||
{
|
||||
mDataMutex = new LLMutex(gAPRPoolp);
|
||||
mDataMutex = new LLMutex();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ void LLBufferArray::setThreaded(bool threaded)
|
|||
{
|
||||
if(!mMutexp)
|
||||
{
|
||||
mMutexp = new LLMutex(NULL);
|
||||
mMutexp = new LLMutex();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ static void tcp_close_channel(LLSocket::ptr_t* handle_ptr); // Close an open TCP
|
|||
|
||||
LLProxy::LLProxy():
|
||||
mHTTPProxyEnabled(false),
|
||||
mProxyMutex(NULL),
|
||||
mProxyMutex(),
|
||||
mUDPProxy(),
|
||||
mTCPProxy(),
|
||||
mHTTPProxy(),
|
||||
|
|
|
|||
|
|
@ -298,7 +298,7 @@ private:
|
|||
private:
|
||||
// Is the HTTP proxy enabled? Safe to read in any thread, but do not write directly.
|
||||
// Instead use enableHTTPProxy() and disableHTTPProxy() instead.
|
||||
mutable LLAtomic32<bool> mHTTPProxyEnabled;
|
||||
mutable LLAtomicBool mHTTPProxyEnabled;
|
||||
|
||||
// Mutex to protect shared members in non-main thread calls to applyProxySettings().
|
||||
mutable LLMutex mProxyMutex;
|
||||
|
|
|
|||
|
|
@ -54,11 +54,7 @@
|
|||
|
||||
// constants for poll timeout. if we are threading, we want to have a
|
||||
// longer poll timeout.
|
||||
#if LL_THREADS_APR
|
||||
static const S32 DEFAULT_POLL_TIMEOUT = 1000;
|
||||
#else
|
||||
static const S32 DEFAULT_POLL_TIMEOUT = 0;
|
||||
#endif
|
||||
|
||||
// The default (and fallback) expiration time for chains
|
||||
const F32 DEFAULT_CHAIN_EXPIRY_SECS = 30.0f;
|
||||
|
|
@ -169,8 +165,6 @@ LLPumpIO::LLPumpIO(apr_pool_t* pool) :
|
|||
mPool(NULL),
|
||||
mCurrentPool(NULL),
|
||||
mCurrentPoolReallocCount(0),
|
||||
mChainsMutex(NULL),
|
||||
mCallbackMutex(NULL),
|
||||
mCurrentChain(mRunningChains.end())
|
||||
{
|
||||
mCurrentChain = mRunningChains.end();
|
||||
|
|
@ -194,9 +188,6 @@ bool LLPumpIO::addChain(const chain_t& chain, F32 timeout, bool has_curl_request
|
|||
{
|
||||
if(chain.empty()) return false;
|
||||
|
||||
#if LL_THREADS_APR
|
||||
LLScopedLock lock(mChainsMutex);
|
||||
#endif
|
||||
LLChainInfo info;
|
||||
info.mHasCurlRequest = has_curl_request;
|
||||
info.setTimeoutSeconds(timeout);
|
||||
|
|
@ -234,9 +225,6 @@ bool LLPumpIO::addChain(
|
|||
if(!data) return false;
|
||||
if(links.empty()) return false;
|
||||
|
||||
#if LL_THREADS_APR
|
||||
LLScopedLock lock(mChainsMutex);
|
||||
#endif
|
||||
#if LL_DEBUG_PIPE_TYPE_IN_PUMP
|
||||
LL_DEBUGS() << "LLPumpIO::addChain() " << links[0].mPipe << " '"
|
||||
<< typeid(*(links[0].mPipe)).name() << "'" << LL_ENDL;
|
||||
|
|
@ -391,9 +379,6 @@ void LLPumpIO::clearLock(S32 key)
|
|||
// therefore won't be treading into deleted memory. I think we can
|
||||
// also clear the lock on the chain safely since the pump only
|
||||
// reads that value.
|
||||
#if LL_THREADS_APR
|
||||
LLScopedLock lock(mChainsMutex);
|
||||
#endif
|
||||
mClearLocks.insert(key);
|
||||
}
|
||||
|
||||
|
|
@ -457,9 +442,6 @@ void LLPumpIO::pump(const S32& poll_timeout)
|
|||
PUMP_DEBUG;
|
||||
if(true)
|
||||
{
|
||||
#if LL_THREADS_APR
|
||||
LLScopedLock lock(mChainsMutex);
|
||||
#endif
|
||||
// bail if this pump is paused.
|
||||
if(PAUSING == mState)
|
||||
{
|
||||
|
|
@ -724,25 +706,10 @@ void LLPumpIO::pump(const S32& poll_timeout)
|
|||
END_PUMP_DEBUG;
|
||||
}
|
||||
|
||||
//bool LLPumpIO::respond(const chain_t& pipes)
|
||||
//{
|
||||
//#if LL_THREADS_APR
|
||||
// LLScopedLock lock(mCallbackMutex);
|
||||
//#endif
|
||||
// LLChainInfo info;
|
||||
// links_t links;
|
||||
//
|
||||
// mPendingCallbacks.push_back(info);
|
||||
// return true;
|
||||
//}
|
||||
|
||||
bool LLPumpIO::respond(LLIOPipe* pipe)
|
||||
{
|
||||
if(NULL == pipe) return false;
|
||||
|
||||
#if LL_THREADS_APR
|
||||
LLScopedLock lock(mCallbackMutex);
|
||||
#endif
|
||||
LLChainInfo info;
|
||||
LLLinkInfo link;
|
||||
link.mPipe = pipe;
|
||||
|
|
@ -761,10 +728,6 @@ bool LLPumpIO::respond(
|
|||
if(!data) return false;
|
||||
if(links.empty()) return false;
|
||||
|
||||
#if LL_THREADS_APR
|
||||
LLScopedLock lock(mCallbackMutex);
|
||||
#endif
|
||||
|
||||
// Add the callback response
|
||||
LLChainInfo info;
|
||||
info.mChainLinks = links;
|
||||
|
|
@ -781,9 +744,6 @@ void LLPumpIO::callback()
|
|||
//LL_INFOS() << "LLPumpIO::callback()" << LL_ENDL;
|
||||
if(true)
|
||||
{
|
||||
#if LL_THREADS_APR
|
||||
LLScopedLock lock(mCallbackMutex);
|
||||
#endif
|
||||
std::copy(
|
||||
mPendingCallbacks.begin(),
|
||||
mPendingCallbacks.end(),
|
||||
|
|
@ -809,9 +769,6 @@ void LLPumpIO::callback()
|
|||
|
||||
void LLPumpIO::control(LLPumpIO::EControl op)
|
||||
{
|
||||
#if LL_THREADS_APR
|
||||
LLScopedLock lock(mChainsMutex);
|
||||
#endif
|
||||
switch(op)
|
||||
{
|
||||
case PAUSE:
|
||||
|
|
@ -829,22 +786,11 @@ void LLPumpIO::control(LLPumpIO::EControl op)
|
|||
void LLPumpIO::initialize(apr_pool_t* pool)
|
||||
{
|
||||
if(!pool) return;
|
||||
#if LL_THREADS_APR
|
||||
// SJB: Windows defaults to NESTED and OSX defaults to UNNESTED, so use UNNESTED explicitly.
|
||||
apr_thread_mutex_create(&mChainsMutex, APR_THREAD_MUTEX_UNNESTED, pool);
|
||||
apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_UNNESTED, pool);
|
||||
#endif
|
||||
mPool = pool;
|
||||
}
|
||||
|
||||
void LLPumpIO::cleanup()
|
||||
{
|
||||
#if LL_THREADS_APR
|
||||
if(mChainsMutex) apr_thread_mutex_destroy(mChainsMutex);
|
||||
if(mCallbackMutex) apr_thread_mutex_destroy(mCallbackMutex);
|
||||
#endif
|
||||
mChainsMutex = NULL;
|
||||
mCallbackMutex = NULL;
|
||||
if(mPollset)
|
||||
{
|
||||
// LL_DEBUGS() << "cleaning up pollset" << LL_ENDL;
|
||||
|
|
|
|||
|
|
@ -40,9 +40,6 @@
|
|||
#include "lliopipe.h"
|
||||
#include "llrun.h"
|
||||
|
||||
// Define this to enable use with the APR thread library.
|
||||
//#define LL_THREADS_APR 1
|
||||
|
||||
// some simple constants to help with timeouts
|
||||
extern const F32 DEFAULT_CHAIN_EXPIRY_SECS;
|
||||
extern const F32 SHORT_CHAIN_EXPIRY_SECS;
|
||||
|
|
@ -393,14 +390,6 @@ protected:
|
|||
apr_pool_t* mCurrentPool;
|
||||
S32 mCurrentPoolReallocCount;
|
||||
|
||||
#if LL_THREADS_APR
|
||||
apr_thread_mutex_t* mChainsMutex;
|
||||
apr_thread_mutex_t* mCallbackMutex;
|
||||
#else
|
||||
int* mChainsMutex;
|
||||
int* mCallbackMutex;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void initialize(apr_pool_t* pool);
|
||||
void cleanup();
|
||||
|
|
|
|||
|
|
@ -92,8 +92,8 @@ void LLPluginMessagePipeOwner::killMessagePipe(void)
|
|||
}
|
||||
|
||||
LLPluginMessagePipe::LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket):
|
||||
mInputMutex(gAPRPoolp),
|
||||
mOutputMutex(gAPRPoolp),
|
||||
mInputMutex(),
|
||||
mOutputMutex(),
|
||||
mOutputStartIndex(0),
|
||||
mOwner(owner),
|
||||
mSocket(socket)
|
||||
|
|
|
|||
|
|
@ -80,11 +80,11 @@ protected:
|
|||
};
|
||||
|
||||
LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
|
||||
mIncomingQueueMutex(gAPRPoolp)
|
||||
mIncomingQueueMutex()
|
||||
{
|
||||
if(!sInstancesMutex)
|
||||
{
|
||||
sInstancesMutex = new LLMutex(gAPRPoolp);
|
||||
sInstancesMutex = new LLMutex();
|
||||
}
|
||||
|
||||
mOwner = owner;
|
||||
|
|
|
|||
|
|
@ -154,7 +154,6 @@ public:
|
|||
void ClearFacesAndMaterials() { mVolumeFaces.clear(); mMaterialList.clear(); }
|
||||
|
||||
std::string getName() const;
|
||||
std::string getMetric() const {return mMetric;}
|
||||
EModelStatus getStatus() const {return mStatus;}
|
||||
static std::string getStatusString(U32 status) ;
|
||||
|
||||
|
|
@ -260,8 +259,6 @@ public:
|
|||
std::string mRequestedLabel; // name requested in UI, if any.
|
||||
std::string mLabel; // name computed from dae.
|
||||
|
||||
std::string mMetric; // user-supplied metric data for upload
|
||||
|
||||
LLVector3 mNormalizedScale;
|
||||
LLVector3 mNormalizedTranslation;
|
||||
|
||||
|
|
|
|||
|
|
@ -1580,7 +1580,7 @@ bool LLPrimitive::getTESTAxes(const U8 face, U32* s_axis, U32* t_axis)
|
|||
*s_axis = VY; *t_axis = VZ;
|
||||
return true;
|
||||
}
|
||||
else if (face == 5)
|
||||
else if (face >= 5)
|
||||
{
|
||||
*s_axis = VX; *t_axis = VY;
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -200,6 +200,7 @@ set(llui_HEADER_FILES
|
|||
llresizehandle.h
|
||||
llresmgr.h
|
||||
llrngwriter.h
|
||||
llsearchablecontrol.h
|
||||
llsearcheditor.h
|
||||
llscrollbar.h
|
||||
llscrollcontainer.h
|
||||
|
|
|
|||
|
|
@ -769,6 +769,10 @@ void LLButton::draw()
|
|||
}
|
||||
}
|
||||
|
||||
// Highlight if needed
|
||||
if( ll::ui::SearchableControl::getHighlighted() )
|
||||
label_color = ll::ui::SearchableControl::getHighlightColor();
|
||||
|
||||
// Unselected label assignments
|
||||
LLWString label = getCurrentLabel();
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ class LLUICtrlFactory;
|
|||
|
||||
class LLButton
|
||||
: public LLUICtrl, public LLBadgeOwner
|
||||
, public ll::ui::SearchableControl
|
||||
{
|
||||
public:
|
||||
struct Params
|
||||
|
|
@ -380,6 +381,12 @@ protected:
|
|||
LLFlashTimer * mFlashingTimer;
|
||||
bool mForceFlashing; // Stick flashing color even if button is pressed
|
||||
bool mHandleRightMouse;
|
||||
|
||||
protected:
|
||||
virtual std::string _getSearchText() const
|
||||
{
|
||||
return getLabelUnselected() + getToolTip();
|
||||
}
|
||||
};
|
||||
|
||||
// Build time optimization, generate once in .cpp file
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ class LLViewBorder;
|
|||
|
||||
class LLCheckBoxCtrl
|
||||
: public LLUICtrl
|
||||
, public ll::ui::SearchableControl
|
||||
{
|
||||
public:
|
||||
struct Params
|
||||
|
|
@ -92,6 +93,8 @@ public:
|
|||
// LLCheckBoxCtrl interface
|
||||
virtual BOOL toggle() { return mButton->toggleState(); } // returns new state
|
||||
|
||||
void setBtnFocus() { mButton->setFocus(TRUE); }
|
||||
|
||||
void setEnabledColor( const LLColor4 &color ) { mTextEnabledColor = color; }
|
||||
void setDisabledColor( const LLColor4 &color ) { mTextDisabledColor = color; }
|
||||
|
||||
|
|
@ -106,6 +109,18 @@ public:
|
|||
virtual BOOL isDirty() const; // Returns TRUE if the user has modified this control.
|
||||
virtual void resetDirty(); // Clear dirty state
|
||||
|
||||
protected:
|
||||
virtual std::string _getSearchText() const
|
||||
{
|
||||
return getLabel() + getToolTip();
|
||||
}
|
||||
|
||||
virtual void onSetHighlight() const // When highlight, really do highlight the label
|
||||
{
|
||||
if( mLabel )
|
||||
mLabel->ll::ui::SearchableControl::setHighlighted( ll::ui::SearchableControl::getHighlighted() );
|
||||
}
|
||||
|
||||
protected:
|
||||
// note: value is stored in toggle state of button
|
||||
LLButton* mButton;
|
||||
|
|
|
|||
|
|
@ -243,7 +243,14 @@ LLScrollListItem* LLComboBox::add(const std::string& name, EAddPosition pos, BOO
|
|||
item->setEnabled(enabled);
|
||||
if (!mAllowTextEntry && mLabel.empty())
|
||||
{
|
||||
selectFirstItem();
|
||||
if (mControlVariable)
|
||||
{
|
||||
setValue(mControlVariable->getValue()); // selects the appropriate item
|
||||
}
|
||||
else
|
||||
{
|
||||
selectFirstItem();
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
|
@ -255,7 +262,14 @@ LLScrollListItem* LLComboBox::add(const std::string& name, const LLUUID& id, EAd
|
|||
item->setEnabled(enabled);
|
||||
if (!mAllowTextEntry && mLabel.empty())
|
||||
{
|
||||
selectFirstItem();
|
||||
if (mControlVariable)
|
||||
{
|
||||
setValue(mControlVariable->getValue()); // selects the appropriate item
|
||||
}
|
||||
else
|
||||
{
|
||||
selectFirstItem();
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
|
@ -268,7 +282,14 @@ LLScrollListItem* LLComboBox::add(const std::string& name, void* userdata, EAddP
|
|||
item->setUserdata( userdata );
|
||||
if (!mAllowTextEntry && mLabel.empty())
|
||||
{
|
||||
selectFirstItem();
|
||||
if (mControlVariable)
|
||||
{
|
||||
setValue(mControlVariable->getValue()); // selects the appropriate item
|
||||
}
|
||||
else
|
||||
{
|
||||
selectFirstItem();
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
|
@ -280,7 +301,14 @@ LLScrollListItem* LLComboBox::add(const std::string& name, LLSD value, EAddPosit
|
|||
item->setEnabled(enabled);
|
||||
if (!mAllowTextEntry && mLabel.empty())
|
||||
{
|
||||
selectFirstItem();
|
||||
if (mControlVariable)
|
||||
{
|
||||
setValue(mControlVariable->getValue()); // selects the appropriate item
|
||||
}
|
||||
else
|
||||
{
|
||||
selectFirstItem();
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -251,8 +251,14 @@ void LLLayoutStack::draw()
|
|||
|
||||
// always clip to stack itself
|
||||
LLLocalClipRect clip(getLocalRect());
|
||||
BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
|
||||
for (LLLayoutPanel* panelp : mPanels)
|
||||
{
|
||||
if ((!panelp->getVisible() || panelp->mCollapsed)
|
||||
&& (panelp->mVisibleAmt < 0.001f || !mAnimate))
|
||||
{
|
||||
// essentially invisible
|
||||
continue;
|
||||
}
|
||||
// clip to layout rectangle, not bounding rectangle
|
||||
LLRect clip_rect = panelp->getRect();
|
||||
// scale clipping rectangle by visible amount
|
||||
|
|
|
|||
|
|
@ -504,6 +504,10 @@ void LLMenuItemGL::draw( void )
|
|||
color = mDisabledColor.get();
|
||||
}
|
||||
|
||||
// Highlight if needed
|
||||
if( ll::ui::SearchableControl::getHighlighted() )
|
||||
color = ll::ui::SearchableControl::getHighlightColor();
|
||||
|
||||
// Draw the text on top.
|
||||
if (mBriefItem)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ extern S32 MENU_BAR_WIDTH;
|
|||
// The LLMenuItemGL represents a single menu item in a menu.
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class LLMenuItemGL : public LLUICtrl
|
||||
class LLMenuItemGL: public LLUICtrl, public ll::ui::SearchableControl
|
||||
{
|
||||
public:
|
||||
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
|
||||
|
|
@ -175,7 +175,12 @@ protected:
|
|||
// This function appends the character string representation of
|
||||
// the current accelerator key and mask to the provided string.
|
||||
void appendAcceleratorString( std::string& st ) const;
|
||||
|
||||
|
||||
virtual std::string _getSearchText() const
|
||||
{
|
||||
return mLabel.getString();
|
||||
}
|
||||
|
||||
protected:
|
||||
KEY mAcceleratorKey;
|
||||
MASK mAcceleratorMask;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* @file llsearchablecontrol.h
|
||||
*
|
||||
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2019, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_SEARCHABLE_CONTROL_H
|
||||
#define LL_SEARCHABLE_CONTROL_H
|
||||
|
||||
#include "lluicolortable.h"
|
||||
#include "lluicolor.h"
|
||||
|
||||
namespace ll
|
||||
{
|
||||
namespace ui
|
||||
{
|
||||
class SearchableControl
|
||||
{
|
||||
mutable bool mIsHighlighed;
|
||||
public:
|
||||
SearchableControl()
|
||||
: mIsHighlighed( false )
|
||||
{ }
|
||||
virtual ~SearchableControl()
|
||||
{ }
|
||||
|
||||
LLColor4 getHighlightColor( ) const
|
||||
{
|
||||
static LLUIColor highlight_color = LLUIColorTable::instance().getColor("SearchableControlHighlightColor", LLColor4::red);
|
||||
return highlight_color.get();
|
||||
}
|
||||
|
||||
void setHighlighted( bool aVal ) const
|
||||
{
|
||||
mIsHighlighed = aVal;
|
||||
onSetHighlight( );
|
||||
}
|
||||
bool getHighlighted( ) const
|
||||
{ return mIsHighlighed; }
|
||||
|
||||
std::string getSearchText() const
|
||||
{ return _getSearchText(); }
|
||||
protected:
|
||||
virtual std::string _getSearchText() const = 0;
|
||||
virtual void onSetHighlight( ) const
|
||||
{ }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
#include "lllineeditor.h"
|
||||
|
||||
|
||||
class LLSliderCtrl : public LLF32UICtrl
|
||||
class LLSliderCtrl: public LLF32UICtrl, public ll::ui::SearchableControl
|
||||
{
|
||||
public:
|
||||
struct Params : public LLInitParam::Block<Params, LLF32UICtrl::Params>
|
||||
|
|
@ -131,6 +131,19 @@ public:
|
|||
static void onEditorGainFocus(LLFocusableElement* caller, void *userdata);
|
||||
static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata);
|
||||
|
||||
protected:
|
||||
virtual std::string _getSearchText() const
|
||||
{
|
||||
std::string strLabel;
|
||||
if( mLabelBox )
|
||||
strLabel = mLabelBox->getLabel();
|
||||
return strLabel + getToolTip();
|
||||
}
|
||||
virtual void onSetHighlight() const // When highlight, really do highlight the label
|
||||
{
|
||||
if( mLabelBox )
|
||||
mLabelBox->ll::ui::SearchableControl::setHighlighted( ll::ui::SearchableControl::getHighlighted() );
|
||||
}
|
||||
private:
|
||||
void updateText();
|
||||
void reportInvalidData();
|
||||
|
|
|
|||
|
|
@ -76,7 +76,8 @@ public:
|
|||
mButton(b),
|
||||
mOldState(FALSE),
|
||||
mPlaceholderText(placeholder),
|
||||
mPadding(0)
|
||||
mPadding(0),
|
||||
mVisible(true)
|
||||
{}
|
||||
|
||||
LLTabContainer* mTabContainer;
|
||||
|
|
@ -85,6 +86,8 @@ public:
|
|||
BOOL mOldState;
|
||||
LLTextBox* mPlaceholderText;
|
||||
S32 mPadding;
|
||||
|
||||
mutable bool mVisible;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
@ -398,7 +401,10 @@ void LLTabContainer::draw()
|
|||
{
|
||||
break;
|
||||
}
|
||||
target_pixel_scroll += (*iter)->mButton->getRect().getWidth();
|
||||
|
||||
if( (*iter)->mVisible )
|
||||
target_pixel_scroll += (*iter)->mButton->getRect().getWidth();
|
||||
|
||||
cur_scroll_pos--;
|
||||
}
|
||||
|
||||
|
|
@ -467,6 +473,12 @@ void LLTabContainer::draw()
|
|||
{
|
||||
LLTabTuple* tuple = *iter;
|
||||
|
||||
if( !tuple->mVisible )
|
||||
{
|
||||
tuple->mButton->setVisible( false );
|
||||
continue;
|
||||
}
|
||||
|
||||
tuple->mButton->translate( left ? left - tuple->mButton->getRect().mLeft : 0,
|
||||
top ? top - tuple->mButton->getRect().mTop : 0 );
|
||||
if (top) top -= BTN_HEIGHT + tabcntrv_pad;
|
||||
|
|
@ -724,11 +736,11 @@ BOOL LLTabContainer::handleToolTip( S32 x, S32 y, MASK mask)
|
|||
{
|
||||
for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
|
||||
{
|
||||
LLTabTuple* tuple = *iter;
|
||||
tuple->mButton->setVisible( TRUE );
|
||||
S32 local_x = x - tuple->mButton->getRect().mLeft;
|
||||
S32 local_y = y - tuple->mButton->getRect().mBottom;
|
||||
handled = tuple->mButton->handleToolTip( local_x, local_y, mask);
|
||||
LLButton* tab_button = (*iter)->mButton;
|
||||
if (!tab_button->getVisible()) continue;
|
||||
S32 local_x = x - tab_button->getRect().mLeft;
|
||||
S32 local_y = y - tab_button->getRect().mBottom;
|
||||
handled = tab_button->handleToolTip(local_x, local_y, mask);
|
||||
if( handled )
|
||||
{
|
||||
break;
|
||||
|
|
@ -1505,7 +1517,7 @@ BOOL LLTabContainer::setTab(S32 which)
|
|||
}
|
||||
|
||||
BOOL is_visible = FALSE;
|
||||
if (selected_tuple->mButton->getEnabled())
|
||||
if( selected_tuple->mButton->getEnabled() && selected_tuple->mVisible )
|
||||
{
|
||||
setCurrentPanelIndex(which);
|
||||
|
||||
|
|
@ -2121,3 +2133,35 @@ S32 LLTabContainer::getTotalTabWidth() const
|
|||
{
|
||||
return mTotalTabWidth;
|
||||
}
|
||||
|
||||
void LLTabContainer::setTabVisibility( LLPanel const *aPanel, bool aVisible )
|
||||
{
|
||||
for( tuple_list_t::const_iterator itr = mTabList.begin(); itr != mTabList.end(); ++itr )
|
||||
{
|
||||
LLTabTuple const *pTT = *itr;
|
||||
if( pTT->mTabPanel == aPanel )
|
||||
{
|
||||
pTT->mVisible = aVisible;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool foundTab( false );
|
||||
for( tuple_list_t::const_iterator itr = mTabList.begin(); itr != mTabList.end(); ++itr )
|
||||
{
|
||||
LLTabTuple const *pTT = *itr;
|
||||
if( pTT->mVisible )
|
||||
{
|
||||
this->selectTab( itr - mTabList.begin() );
|
||||
foundTab = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( foundTab )
|
||||
this->setVisible( TRUE );
|
||||
else
|
||||
this->setVisible( FALSE );
|
||||
|
||||
updateMaxScrollPos();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -216,6 +216,8 @@ public:
|
|||
S32 getMinTabWidth() const { return mMinTabWidth; }
|
||||
S32 getMaxTabWidth() const { return mMaxTabWidth; }
|
||||
|
||||
void setTabVisibility( LLPanel const *aPanel, bool );
|
||||
|
||||
void startDragAndDropDelayTimer() { mDragAndDropDelayTimer.start(); }
|
||||
|
||||
void onTabBtn( const LLSD& data, LLPanel* panel );
|
||||
|
|
|
|||
|
|
@ -1222,6 +1222,17 @@ void LLTextBase::draw()
|
|||
gl_rect_2d(text_rect, bg_color % alpha, TRUE);
|
||||
}
|
||||
|
||||
// Draw highlighted if needed
|
||||
if( ll::ui::SearchableControl::getHighlighted() )
|
||||
{
|
||||
LLColor4 bg_color = ll::ui::SearchableControl::getHighlightColor();
|
||||
LLRect bg_rect = mVisibleTextRect;
|
||||
if( mScroller )
|
||||
bg_rect.intersectWith( text_rect );
|
||||
|
||||
gl_rect_2d( text_rect, bg_color, TRUE );
|
||||
}
|
||||
|
||||
bool should_clip = mClip || mScroller != NULL;
|
||||
{ LLLocalClipRect clip(text_rect, should_clip);
|
||||
|
||||
|
|
|
|||
|
|
@ -275,7 +275,8 @@ typedef LLPointer<LLTextSegment> LLTextSegmentPtr;
|
|||
class LLTextBase
|
||||
: public LLUICtrl,
|
||||
protected LLEditMenuHandler,
|
||||
public LLSpellCheckMenuHandler
|
||||
public LLSpellCheckMenuHandler,
|
||||
public ll::ui::SearchableControl
|
||||
{
|
||||
public:
|
||||
friend class LLTextSegment;
|
||||
|
|
@ -617,6 +618,11 @@ protected:
|
|||
void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only = false);
|
||||
S32 normalizeUri(std::string& uri);
|
||||
|
||||
protected:
|
||||
virtual std::string _getSearchText() const
|
||||
{
|
||||
return mLabel.getString() + getToolTip();
|
||||
}
|
||||
|
||||
protected:
|
||||
// text segmentation and flow
|
||||
|
|
|
|||
|
|
@ -732,14 +732,30 @@ BOOL LLTextEditor::handleRightMouseDown(S32 x, S32 y, MASK mask)
|
|||
{
|
||||
setFocus(TRUE);
|
||||
}
|
||||
|
||||
bool show_menu = false;
|
||||
|
||||
// Prefer editor menu if it has selection. See EXT-6806.
|
||||
if (hasSelection() || !LLTextBase::handleRightMouseDown(x, y, mask))
|
||||
if (hasSelection())
|
||||
{
|
||||
if(getShowContextMenu())
|
||||
S32 click_pos = getDocIndexFromLocalCoord(x, y, FALSE);
|
||||
if (click_pos > mSelectionStart && click_pos < mSelectionEnd)
|
||||
{
|
||||
showContextMenu(x, y);
|
||||
show_menu = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Let segments handle the click, if nothing does, show editor menu
|
||||
if (!show_menu && !LLTextBase::handleRightMouseDown(x, y, mask))
|
||||
{
|
||||
show_menu = true;
|
||||
}
|
||||
|
||||
if (show_menu && getShowContextMenu())
|
||||
{
|
||||
showContextMenu(x, y);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "llinitparam.h"
|
||||
#include "llview.h"
|
||||
#include "llviewmodel.h" // *TODO move dependency to .cpp file
|
||||
#include "llsearchablecontrol.h"
|
||||
|
||||
const BOOL TAKE_FOCUS_YES = TRUE;
|
||||
const BOOL TAKE_FOCUS_NO = FALSE;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "llapr.h"
|
||||
#include "llpointer.h"
|
||||
#include "llqueuedthread.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llapr.h" // thread-related functions
|
||||
#include "llpidlock.h"
|
||||
#include "lldir.h"
|
||||
#include "llsd.h"
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename
|
|||
mDataFP(NULL),
|
||||
mIndexFP(NULL)
|
||||
{
|
||||
mDataMutex = new LLMutex(0);
|
||||
mDataMutex = new LLMutex();
|
||||
|
||||
S32 i;
|
||||
for (i = 0; i < VFSLOCK_COUNT; i++)
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@
|
|||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "llapr.h"
|
||||
|
||||
#include "llqueuedthread.h"
|
||||
|
||||
#include "llvfs.h"
|
||||
|
|
|
|||
|
|
@ -343,6 +343,10 @@ attributedStringInfo getSegments(NSAttributedString *str)
|
|||
|
||||
- (void) mouseDown:(NSEvent *)theEvent
|
||||
{
|
||||
NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
|
||||
mMousePos[0] = mPoint.x;
|
||||
mMousePos[1] = mPoint.y;
|
||||
|
||||
// Apparently people still use this?
|
||||
if ([theEvent modifierFlags] & NSCommandKeyMask &&
|
||||
!([theEvent modifierFlags] & NSControlKeyMask) &&
|
||||
|
|
@ -380,11 +384,17 @@ attributedStringInfo getSegments(NSAttributedString *str)
|
|||
|
||||
- (void) rightMouseDown:(NSEvent *)theEvent
|
||||
{
|
||||
NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
|
||||
mMousePos[0] = mPoint.x;
|
||||
mMousePos[1] = mPoint.y;
|
||||
callRightMouseDown(mMousePos, [theEvent modifierFlags]);
|
||||
}
|
||||
|
||||
- (void) rightMouseUp:(NSEvent *)theEvent
|
||||
{
|
||||
NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
|
||||
mMousePos[0] = mPoint.x;
|
||||
mMousePos[1] = mPoint.y;
|
||||
callRightMouseUp(mMousePos, [theEvent modifierFlags]);
|
||||
}
|
||||
|
||||
|
|
@ -431,11 +441,17 @@ attributedStringInfo getSegments(NSAttributedString *str)
|
|||
|
||||
- (void) otherMouseDown:(NSEvent *)theEvent
|
||||
{
|
||||
NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
|
||||
mMousePos[0] = mPoint.x;
|
||||
mMousePos[1] = mPoint.y;
|
||||
callMiddleMouseDown(mMousePos, [theEvent modifierFlags]);
|
||||
}
|
||||
|
||||
- (void) otherMouseUp:(NSEvent *)theEvent
|
||||
{
|
||||
NSPoint mPoint = gHiDPISupport ? [self convertPointToBacking:[theEvent locationInWindow]] : [theEvent locationInWindow];
|
||||
mMousePos[0] = mPoint.x;
|
||||
mMousePos[1] = mPoint.y;
|
||||
callMiddleMouseUp(mMousePos, [theEvent modifierFlags]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -110,9 +110,9 @@ void glSwapBuffers(void* context);
|
|||
CGLContextObj getCGLContextObj(GLViewRef view);
|
||||
unsigned long getVramSize(GLViewRef view);
|
||||
float getDeviceUnitSize(GLViewRef view);
|
||||
const CGPoint & getContentViewBoundsPosition(NSWindowRef window);
|
||||
const CGSize & getContentViewBoundsSize(NSWindowRef window);
|
||||
const CGSize & getDeviceContentViewSize(NSWindowRef window, GLViewRef view);
|
||||
const CGPoint getContentViewBoundsPosition(NSWindowRef window);
|
||||
const CGSize getContentViewBoundsSize(NSWindowRef window);
|
||||
const CGSize getDeviceContentViewSize(NSWindowRef window, GLViewRef view);
|
||||
void getWindowSize(NSWindowRef window, float* size);
|
||||
void setWindowSize(NSWindowRef window, int width, int height);
|
||||
void getCursorPos(NSWindowRef window, float* pos);
|
||||
|
|
|
|||
|
|
@ -258,17 +258,17 @@ float getDeviceUnitSize(GLViewRef view)
|
|||
return [(LLOpenGLView*)view convertSizeToBacking:NSMakeSize(1, 1)].width;
|
||||
}
|
||||
|
||||
const CGPoint & getContentViewBoundsPosition(NSWindowRef window)
|
||||
const CGPoint getContentViewBoundsPosition(NSWindowRef window)
|
||||
{
|
||||
return [[(LLNSWindow*)window contentView] bounds].origin;
|
||||
}
|
||||
|
||||
const CGSize & getContentViewBoundsSize(NSWindowRef window)
|
||||
const CGSize getContentViewBoundsSize(NSWindowRef window)
|
||||
{
|
||||
return [[(LLNSWindow*)window contentView] bounds].size;
|
||||
}
|
||||
|
||||
const CGSize & getDeviceContentViewSize(NSWindowRef window, GLViewRef view)
|
||||
const CGSize getDeviceContentViewSize(NSWindowRef window, GLViewRef view)
|
||||
{
|
||||
return [(NSOpenGLView*)view convertRectToBacking:[[(LLNSWindow*)window contentView] bounds]].size;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -869,10 +869,11 @@ BOOL LLWindowMacOSX::getSize(LLCoordScreen *size)
|
|||
|
||||
size->mX = sz.width;
|
||||
size->mY = sz.height;
|
||||
err = noErr;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_ERRS() << "LLWindowMacOSX::getPosition(): no window and not fullscreen!" << LL_ENDL;
|
||||
LL_ERRS() << "LLWindowMacOSX::getSize(): no window and not fullscreen!" << LL_ENDL;
|
||||
}
|
||||
|
||||
return (err == noErr);
|
||||
|
|
@ -894,10 +895,13 @@ BOOL LLWindowMacOSX::getSize(LLCoordWindow *size)
|
|||
|
||||
size->mX = sz.width;
|
||||
size->mY = sz.height;
|
||||
err = noErr;
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_ERRS() << "LLWindowMacOSX::getPosition(): no window and not fullscreen!" << LL_ENDL;
|
||||
LL_ERRS() << "LLWindowMacOSX::getSize(): no window and not fullscreen!" << LL_ENDL;
|
||||
}
|
||||
|
||||
return (err == noErr);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,9 @@
|
|||
#include "llrect.h"
|
||||
#include "llxmltree.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llfile.h"
|
||||
#include "lltimer.h"
|
||||
#include "lldir.h"
|
||||
|
||||
#if LL_RELEASE_WITH_DEBUG_INFO || LL_DEBUG
|
||||
#define CONTROL_ERRS LL_ERRS("ControlErrors")
|
||||
|
|
@ -92,6 +95,17 @@ template <> LLSD convert_from_llsd<LLSD>(const LLSD& sd, eControlType type, cons
|
|||
//this defines the current version of the settings file
|
||||
const S32 CURRENT_VERSION = 101;
|
||||
|
||||
// If you define the environment variable LL_SETTINGS_PROFILE to any value this will activate
|
||||
// the gSavedSettings profiling code. This code tracks the calls to get a saved (debug) setting.
|
||||
// When the viewer exits the results are written to the log directory to the file specified
|
||||
// by SETTINGS_PROFILE below. Only settings with an average access rate >= 2/second are output.
|
||||
typedef std::pair<std::string, U32> settings_pair_t;
|
||||
typedef std::vector<settings_pair_t> settings_vec_t;
|
||||
LLSD getCount;
|
||||
settings_vec_t getCount_v;
|
||||
F64 start_time = 0;
|
||||
std::string SETTINGS_PROFILE = "settings_profile.log";
|
||||
|
||||
bool LLControlVariable::llsd_compare(const LLSD& a, const LLSD & b)
|
||||
{
|
||||
bool result = false;
|
||||
|
|
@ -327,6 +341,11 @@ LLSD LLControlVariable::getSaveValue() const
|
|||
|
||||
LLPointer<LLControlVariable> LLControlGroup::getControl(const std::string& name)
|
||||
{
|
||||
if (mSettingsProfile)
|
||||
{
|
||||
incrCount(name);
|
||||
}
|
||||
|
||||
ctrl_name_table_t::iterator iter = mNameTable.find(name);
|
||||
return iter == mNameTable.end() ? LLPointer<LLControlVariable>() : iter->second;
|
||||
}
|
||||
|
|
@ -349,8 +368,14 @@ const std::string LLControlGroup::mTypeString[TYPE_COUNT] = { "U32"
|
|||
};
|
||||
|
||||
LLControlGroup::LLControlGroup(const std::string& name)
|
||||
: LLInstanceTracker<LLControlGroup, std::string>(name)
|
||||
: LLInstanceTracker<LLControlGroup, std::string>(name),
|
||||
mSettingsProfile(false)
|
||||
{
|
||||
|
||||
if (NULL != getenv("LL_SETTINGS_PROFILE"))
|
||||
{
|
||||
mSettingsProfile = true;
|
||||
}
|
||||
}
|
||||
|
||||
LLControlGroup::~LLControlGroup()
|
||||
|
|
@ -358,8 +383,66 @@ LLControlGroup::~LLControlGroup()
|
|||
cleanup();
|
||||
}
|
||||
|
||||
static bool compareRoutine(settings_pair_t lhs, settings_pair_t rhs)
|
||||
{
|
||||
return lhs.second > rhs.second;
|
||||
};
|
||||
|
||||
void LLControlGroup::cleanup()
|
||||
{
|
||||
if(mSettingsProfile && getCount.size() != 0)
|
||||
{
|
||||
std::string file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, SETTINGS_PROFILE);
|
||||
LLFILE* out = LLFile::fopen(file, "w"); /* Flawfinder: ignore */
|
||||
if(!out)
|
||||
{
|
||||
LL_WARNS("SettingsProfile") << "Error opening " << SETTINGS_PROFILE << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
F64 end_time = LLTimer::getTotalSeconds();
|
||||
U32 total_seconds = (U32)(end_time - start_time);
|
||||
|
||||
std::string msg = llformat("Runtime (seconds): %d\n\n No. accesses Avg. accesses/sec Name\n", total_seconds);
|
||||
std::ostringstream data_msg;
|
||||
|
||||
data_msg << msg;
|
||||
size_t data_size = data_msg.str().size();
|
||||
if (fwrite(data_msg.str().c_str(), 1, data_size, out) != data_size)
|
||||
{
|
||||
LL_WARNS("SettingsProfile") << "Failed to write settings profile header" << LL_ENDL;
|
||||
}
|
||||
|
||||
for (LLSD::map_const_iterator iter = getCount.beginMap(); iter != getCount.endMap(); ++iter)
|
||||
{
|
||||
getCount_v.push_back(settings_pair_t(iter->first, iter->second.asInteger()));
|
||||
}
|
||||
sort(getCount_v.begin(), getCount_v.end(), compareRoutine);
|
||||
|
||||
for (settings_vec_t::iterator iter = getCount_v.begin(); iter != getCount_v.end(); ++iter)
|
||||
{
|
||||
U32 access_rate = 0;
|
||||
if (total_seconds != 0)
|
||||
{
|
||||
access_rate = iter->second / total_seconds;
|
||||
}
|
||||
if (access_rate >= 2)
|
||||
{
|
||||
std::ostringstream data_msg;
|
||||
msg = llformat("%13d %7d %s", iter->second, access_rate, iter->first.c_str());
|
||||
data_msg << msg << "\n";
|
||||
size_t data_size = data_msg.str().size();
|
||||
if (fwrite(data_msg.str().c_str(), 1, data_size, out) != data_size)
|
||||
{
|
||||
LL_WARNS("SettingsProfile") << "Failed to write settings profile" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
getCount = LLSD::emptyMap();
|
||||
fclose(out);
|
||||
}
|
||||
}
|
||||
|
||||
mNameTable.clear();
|
||||
}
|
||||
|
||||
|
|
@ -460,6 +543,15 @@ LLControlVariable* LLControlGroup::declareLLSD(const std::string& name, const LL
|
|||
return declareControl(name, TYPE_LLSD, initial_val, comment, persist);
|
||||
}
|
||||
|
||||
void LLControlGroup::incrCount(const std::string& name)
|
||||
{
|
||||
if (0.0 == start_time)
|
||||
{
|
||||
start_time = LLTimer::getTotalSeconds();
|
||||
}
|
||||
getCount[name] = getCount[name].asInteger() + 1;
|
||||
}
|
||||
|
||||
BOOL LLControlGroup::getBOOL(const std::string& name)
|
||||
{
|
||||
return (BOOL)get<bool>(name);
|
||||
|
|
|
|||
|
|
@ -301,6 +301,9 @@ public:
|
|||
U32 saveToFile(const std::string& filename, BOOL nondefault_only);
|
||||
U32 loadFromFile(const std::string& filename, bool default_values = false, bool save_values = true);
|
||||
void resetToDefaults();
|
||||
void incrCount(const std::string& name);
|
||||
|
||||
bool mSettingsProfile;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -276,6 +276,7 @@ set(viewer_SOURCE_FILES
|
|||
llfloatermemleak.cpp
|
||||
llfloatermodelpreview.cpp
|
||||
llfloatermodeluploadbase.cpp
|
||||
llfloatermyscripts.cpp
|
||||
llfloaternamedesc.cpp
|
||||
llfloaternotificationsconsole.cpp
|
||||
llfloaternotificationstabbed.cpp
|
||||
|
|
@ -545,6 +546,7 @@ set(viewer_SOURCE_FILES
|
|||
llscrollingpanelparam.cpp
|
||||
llscrollingpanelparambase.cpp
|
||||
llsculptidsize.cpp
|
||||
llsearchableui.cpp
|
||||
llsearchcombobox.cpp
|
||||
llsearchhistory.cpp
|
||||
llsecapi.cpp
|
||||
|
|
@ -906,6 +908,7 @@ set(viewer_HEADER_FILES
|
|||
llfloatermemleak.h
|
||||
llfloatermodelpreview.h
|
||||
llfloatermodeluploadbase.h
|
||||
llfloatermyscripts.h
|
||||
llfloaternamedesc.h
|
||||
llfloaternotificationsconsole.h
|
||||
llfloaternotificationstabbed.h
|
||||
|
|
@ -1164,6 +1167,7 @@ set(viewer_HEADER_FILES
|
|||
llscrollingpanelparam.h
|
||||
llscrollingpanelparambase.h
|
||||
llsculptidsize.h
|
||||
llsearchableui.h
|
||||
llsearchcombobox.h
|
||||
llsearchhistory.h
|
||||
llsecapi.h
|
||||
|
|
@ -1624,6 +1628,7 @@ endif (WINDOWS)
|
|||
# from within the IDE.
|
||||
set(viewer_XUI_FILES
|
||||
skins/default/colors.xml
|
||||
skins/default/default_languages.xml
|
||||
skins/default/textures/textures.xml
|
||||
)
|
||||
file(GLOB DEFAULT_XUI_FILE_GLOB_LIST
|
||||
|
|
@ -1878,6 +1883,15 @@ if (WINDOWS)
|
|||
windows-crash-logger
|
||||
)
|
||||
|
||||
# sets the 'working directory' for debugging from visual studio.
|
||||
# Condition for version can be moved to requirements once build agents will be updated (see TOOL-3865)
|
||||
if ((NOT UNATTENDED) AND (${CMAKE_VERSION} VERSION_GREATER "3.7.2"))
|
||||
set_property(
|
||||
TARGET ${VIEWER_BINARY_NAME}
|
||||
PROPERTY VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
)
|
||||
endif ((NOT UNATTENDED) AND (${CMAKE_VERSION} VERSION_GREATER "3.7.2"))
|
||||
|
||||
if (PACKAGE)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.bz2
|
||||
|
|
@ -2109,7 +2123,7 @@ if (DARWIN)
|
|||
set(MACOSX_BUNDLE_BUNDLE_NAME "SecondLife")
|
||||
set(MACOSX_BUNDLE_SHORT_VERSION_STRING "${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}")
|
||||
set(MACOSX_BUNDLE_BUNDLE_VERSION "${VIEWER_SHORT_VERSION}${VIEWER_MACOSX_PHASE}${VIEWER_REVISION}")
|
||||
set(MACOSX_BUNDLE_COPYRIGHT "Copyright © Linden Research, Inc. 2007")
|
||||
set(MACOSX_BUNDLE_COPYRIGHT "Copyright © Linden Research, Inc. 2019")
|
||||
set(MACOSX_BUNDLE_NSMAIN_NIB_FILE "SecondLife.nib")
|
||||
set(MACOSX_BUNDLE_NSPRINCIPAL_CLASS "NSApplication")
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
6.2.1
|
||||
6.2.2
|
||||
|
|
|
|||
|
|
@ -11362,6 +11362,17 @@
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>MenuSearch</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Show/hide 'Search menus' field</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>GroupListShowIcons</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -14090,6 +14101,17 @@
|
|||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>RegionCrossingInterpolationTime</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>How long to extrapolate object motion after crossing regions</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>VertexShaderEnable</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -720,9 +720,7 @@ RMDir "$INSTDIR"
|
|||
IfFileExists "$INSTDIR" FOLDERFOUND NOFOLDER
|
||||
|
||||
FOLDERFOUND:
|
||||
# Silent uninstall always removes all files (/SD IDYES)
|
||||
MessageBox MB_YESNO $(DeleteProgramFilesMB) /SD IDYES IDNO NOFOLDER
|
||||
RMDir /r "$INSTDIR"
|
||||
MessageBox MB_OK $(DeleteProgramFilesMB) /SD IDOK IDOK NOFOLDER
|
||||
|
||||
NOFOLDER:
|
||||
|
||||
|
|
|
|||
|
|
@ -572,12 +572,12 @@ static void settings_to_globals()
|
|||
LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");
|
||||
LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic");
|
||||
LLImageGL::sCompressTextures = gSavedSettings.getBOOL("RenderCompressTextures");
|
||||
LLVOVolume::sLODFactor = gSavedSettings.getF32("RenderVolumeLODFactor");
|
||||
LLVOVolume::sLODFactor = llclamp(gSavedSettings.getF32("RenderVolumeLODFactor"), 0.01f, MAX_LOD_FACTOR);
|
||||
LLVOVolume::sDistanceFactor = 1.f-LLVOVolume::sLODFactor * 0.1f;
|
||||
LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor");
|
||||
LLVOTree::sTreeFactor = gSavedSettings.getF32("RenderTreeLODFactor");
|
||||
LLVOAvatar::sLODFactor = gSavedSettings.getF32("RenderAvatarLODFactor");
|
||||
LLVOAvatar::sPhysicsLODFactor = gSavedSettings.getF32("RenderAvatarPhysicsLODFactor");
|
||||
LLVOAvatar::sLODFactor = llclamp(gSavedSettings.getF32("RenderAvatarLODFactor"), 0.f, MAX_AVATAR_LOD_FACTOR);
|
||||
LLVOAvatar::sPhysicsLODFactor = llclamp(gSavedSettings.getF32("RenderAvatarPhysicsLODFactor"), 0.f, MAX_AVATAR_LOD_FACTOR);
|
||||
LLVOAvatar::updateImpostorRendering(gSavedSettings.getU32("RenderAvatarMaxNonImpostors"));
|
||||
LLVOAvatar::sVisibleInFirstPerson = gSavedSettings.getBOOL("FirstPersonAvatarVisible");
|
||||
// clamp auto-open time to some minimum usable value
|
||||
|
|
@ -1167,8 +1167,18 @@ bool LLAppViewer::init()
|
|||
// ForceAddressSize
|
||||
updater.args.add(stringize(gSavedSettings.getU32("ForceAddressSize")));
|
||||
|
||||
// Run the updater. An exception from launching the updater should bother us.
|
||||
#if LL_WINDOWS && !LL_RELEASE_FOR_DOWNLOAD && !LL_SEND_CRASH_REPORTS
|
||||
// This is neither a release package, nor crash-reporting enabled test build
|
||||
// try to run version updater, but don't bother if it fails (file might be missing)
|
||||
LLLeap *leap_p = LLLeap::create(updater, false);
|
||||
if (!leap_p)
|
||||
{
|
||||
LL_WARNS("LLLeap") << "Failed to run LLLeap" << LL_ENDL;
|
||||
}
|
||||
#else
|
||||
// Run the updater. An exception from launching the updater should bother us.
|
||||
LLLeap::create(updater, true);
|
||||
#endif
|
||||
|
||||
// Iterate over --leap command-line options. But this is a bit tricky: if
|
||||
// there's only one, it won't be an array at all.
|
||||
|
|
@ -2168,7 +2178,7 @@ bool LLAppViewer::initThreads()
|
|||
|
||||
if (LLTrace::BlockTimer::sLog || LLTrace::BlockTimer::sMetricLog)
|
||||
{
|
||||
LLTrace::BlockTimer::setLogLock(new LLMutex(NULL));
|
||||
LLTrace::BlockTimer::setLogLock(new LLMutex());
|
||||
mFastTimerLogThread = new LLFastTimerLogThread(LLTrace::BlockTimer::sLogName);
|
||||
mFastTimerLogThread->start();
|
||||
}
|
||||
|
|
@ -5462,7 +5472,8 @@ void LLAppViewer::resumeMainloopTimeout(const std::string& state, F32 secs)
|
|||
{
|
||||
if(secs < 0.0f)
|
||||
{
|
||||
secs = gSavedSettings.getF32("MainloopTimeoutDefault");
|
||||
static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60);
|
||||
secs = mainloop_timeout;
|
||||
}
|
||||
|
||||
mMainloopTimeout->setTimeout(secs);
|
||||
|
|
@ -5489,7 +5500,8 @@ void LLAppViewer::pingMainloopTimeout(const std::string& state, F32 secs)
|
|||
{
|
||||
if(secs < 0.0f)
|
||||
{
|
||||
secs = gSavedSettings.getF32("MainloopTimeoutDefault");
|
||||
static LLCachedControl<F32> mainloop_timeout(gSavedSettings, "MainloopTimeoutDefault", 60);
|
||||
secs = mainloop_timeout;
|
||||
}
|
||||
|
||||
mMainloopTimeout->setTimeout(secs);
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#define LL_LLAPPVIEWER_H
|
||||
|
||||
#include "llallocator.h"
|
||||
#include "llapr.h"
|
||||
#include "llcontrol.h"
|
||||
#include "llsys.h" // for LLOSInfo
|
||||
#include "lltimer.h"
|
||||
|
|
|
|||
|
|
@ -411,68 +411,6 @@ std::string LLAppViewerMacOSX::generateSerialNumber()
|
|||
return serial_md5;
|
||||
}
|
||||
|
||||
static AudioDeviceID get_default_audio_output_device(void)
|
||||
{
|
||||
AudioDeviceID device = 0;
|
||||
UInt32 size = sizeof(device);
|
||||
AudioObjectPropertyAddress device_address = { kAudioHardwarePropertyDefaultOutputDevice,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster };
|
||||
|
||||
OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &device_address, 0, NULL, &size, &device);
|
||||
if(err != noErr)
|
||||
{
|
||||
LL_DEBUGS("SystemMute") << "Couldn't get default audio output device (0x" << std::hex << err << ")" << LL_ENDL;
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLAppViewerMacOSX::setMasterSystemAudioMute(bool new_mute)
|
||||
{
|
||||
AudioDeviceID device = get_default_audio_output_device();
|
||||
|
||||
if(device != 0)
|
||||
{
|
||||
UInt32 mute = new_mute;
|
||||
AudioObjectPropertyAddress device_address = { kAudioDevicePropertyMute,
|
||||
kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMaster };
|
||||
|
||||
OSStatus err = AudioObjectSetPropertyData(device, &device_address, 0, NULL, sizeof(mute), &mute);
|
||||
if(err != noErr)
|
||||
{
|
||||
LL_INFOS("SystemMute") << "Couldn't set audio mute property (0x" << std::hex << err << ")" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//virtual
|
||||
bool LLAppViewerMacOSX::getMasterSystemAudioMute()
|
||||
{
|
||||
// Assume the system isn't muted
|
||||
UInt32 mute = 0;
|
||||
|
||||
AudioDeviceID device = get_default_audio_output_device();
|
||||
|
||||
if(device != 0)
|
||||
{
|
||||
UInt32 size = sizeof(mute);
|
||||
AudioObjectPropertyAddress device_address = { kAudioDevicePropertyMute,
|
||||
kAudioDevicePropertyScopeOutput,
|
||||
kAudioObjectPropertyElementMaster };
|
||||
|
||||
OSStatus err = AudioObjectGetPropertyData(device, &device_address, 0, NULL, &size, &mute);
|
||||
if(err != noErr)
|
||||
{
|
||||
LL_DEBUGS("SystemMute") << "Couldn't get audio mute property (0x" << std::hex << err << ")" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
return (mute != 0);
|
||||
}
|
||||
|
||||
void handleUrl(const char* url_utf8)
|
||||
{
|
||||
if (url_utf8 && gViewerAppPtr)
|
||||
|
|
|
|||
|
|
@ -42,10 +42,6 @@ public:
|
|||
//
|
||||
virtual bool init(); // Override to do application initialization
|
||||
|
||||
// mute/unmute the system's master audio
|
||||
virtual void setMasterSystemAudioMute(bool mute);
|
||||
virtual bool getMasterSystemAudioMute();
|
||||
|
||||
protected:
|
||||
virtual bool restoreErrorTrap();
|
||||
virtual void initCrashReporting(bool reportFreeze);
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ void LLAutoReplace::autoreplaceCallback(S32& replacement_start, S32& replacement
|
|||
word_start--; // walk word_start back to the beginning of the word
|
||||
}
|
||||
LL_DEBUGS("AutoReplace") << "word_start: " << word_start << " word_end: " << word_end << LL_ENDL;
|
||||
std::string str_text = std::string(input_text.begin(), input_text.end());
|
||||
std::string last_word = str_text.substr(word_start, word_end - word_start + 1);
|
||||
LLWString old_string = input_text.substr(word_start, word_end - word_start + 1);
|
||||
std::string last_word = wstring_to_utf8str(old_string);
|
||||
std::string replacement_word(mSettings.replaceWord(last_word));
|
||||
|
||||
if (replacement_word != last_word)
|
||||
|
|
@ -79,9 +79,8 @@ void LLAutoReplace::autoreplaceCallback(S32& replacement_start, S32& replacement
|
|||
{
|
||||
// return the replacement string
|
||||
replacement_start = word_start;
|
||||
replacement_length = last_word.length();
|
||||
replacement_length = word_end - word_start + 1;
|
||||
replacement_string = utf8str_to_wstring(replacement_word);
|
||||
LLWString old_string = utf8str_to_wstring(last_word);
|
||||
S32 size_change = replacement_string.size() - old_string.size();
|
||||
cursor_pos += size_change;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ BOOL LLAvatarListItem::postBuild()
|
|||
mIconPermissionEditTheirs->setVisible(false);
|
||||
|
||||
mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicator");
|
||||
mSpeakingIndicator->setChannelState(LLOutputMonitorCtrl::UNDEFINED_CHANNEL);
|
||||
mInfoBtn = getChild<LLButton>("info_btn");
|
||||
mProfileBtn = getChild<LLButton>("profile_btn");
|
||||
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "llchatitemscontainerctrl.h"
|
||||
#include "lltextbox.h"
|
||||
|
||||
#include "llavataractions.h"
|
||||
#include "llavatariconctrl.h"
|
||||
#include "llcommandhandler.h"
|
||||
#include "llfloaterreg.h"
|
||||
|
|
@ -204,6 +205,7 @@ void LLFloaterIMNearbyChatToastPanel::init(LLSD& notification)
|
|||
|
||||
mMsgText = getChild<LLChatMsgBox>("msg_text", false);
|
||||
mMsgText->setContentTrusted(false);
|
||||
mMsgText->setIsFriendCallback(LLAvatarActions::isFriend);
|
||||
|
||||
mMsgText->setText(std::string(""));
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "llwearableitemslist.h"
|
||||
#include "llpaneloutfitedit.h"
|
||||
#include "lltrans.h"
|
||||
#include "llvoavatarself.h"
|
||||
|
||||
static LLPanelInjector<LLCOFWearables> t_cof_wearables("cof_wearables");
|
||||
|
||||
|
|
@ -330,7 +331,7 @@ void LLCOFWearables::setAttachmentsTitle()
|
|||
{
|
||||
if (mAttachmentsTab)
|
||||
{
|
||||
U32 free_slots = MAX_AGENT_ATTACHMENTS - mAttachments->size();
|
||||
U32 free_slots = gAgentAvatarp->getMaxAttachments() - mAttachments->size();
|
||||
|
||||
LLStringUtil::format_map_t args_attachments;
|
||||
args_attachments["[COUNT]"] = llformat ("%d", free_slots);
|
||||
|
|
|
|||
|
|
@ -351,7 +351,7 @@ void LLConversationItemSession::setParticipantIsMuted(const LLUUID& participant_
|
|||
LLConversationItemParticipant* participant = findParticipant(participant_id);
|
||||
if (participant)
|
||||
{
|
||||
participant->muteVoice(is_muted);
|
||||
participant->moderateVoice(is_muted);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -498,6 +498,7 @@ void LLConversationItemSession::onAvatarNameCache(const LLAvatarName& av_name)
|
|||
|
||||
LLConversationItemParticipant::LLConversationItemParticipant(std::string display_name, const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) :
|
||||
LLConversationItem(display_name,uuid,root_view_model),
|
||||
mIsModeratorMuted(false),
|
||||
mIsModerator(false),
|
||||
mDisplayModeratorLabel(false),
|
||||
mDistToAgent(-1.0)
|
||||
|
|
@ -508,6 +509,7 @@ LLConversationItemParticipant::LLConversationItemParticipant(std::string display
|
|||
|
||||
LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, LLFolderViewModelInterface& root_view_model) :
|
||||
LLConversationItem(uuid,root_view_model),
|
||||
mIsModeratorMuted(false),
|
||||
mIsModerator(false),
|
||||
mDisplayModeratorLabel(false),
|
||||
mDistToAgent(-1.0)
|
||||
|
|
@ -597,25 +599,7 @@ void LLConversationItemParticipant::setDisplayModeratorRole(bool displayRole)
|
|||
|
||||
bool LLConversationItemParticipant::isVoiceMuted()
|
||||
{
|
||||
return LLMuteList::getInstance()->isMuted(mUUID, LLMute::flagVoiceChat);
|
||||
}
|
||||
|
||||
void LLConversationItemParticipant::muteVoice(bool mute_voice)
|
||||
{
|
||||
LLAvatarName av_name;
|
||||
LLAvatarNameCache::get(mUUID, &av_name);
|
||||
LLMuteList * mute_listp = LLMuteList::getInstance();
|
||||
bool voice_already_muted = mute_listp->isMuted(mUUID, av_name.getUserName());
|
||||
|
||||
LLMute mute(mUUID, av_name.getUserName(), LLMute::AGENT);
|
||||
if (voice_already_muted && !mute_voice)
|
||||
{
|
||||
mute_listp->remove(mute);
|
||||
}
|
||||
else if (!voice_already_muted && mute_voice)
|
||||
{
|
||||
mute_listp->add(mute);
|
||||
}
|
||||
return mIsModeratorMuted || LLMuteList::getInstance()->isMuted(mUUID, LLMute::flagVoiceChat);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -194,8 +194,9 @@ public:
|
|||
virtual const std::string& getDisplayName() const { return mDisplayName; }
|
||||
|
||||
bool isVoiceMuted();
|
||||
bool isModeratorMuted() { return mIsModeratorMuted; }
|
||||
bool isModerator() const { return mIsModerator; }
|
||||
void muteVoice(bool mute_voice);
|
||||
void moderateVoice(bool mute_voice) { mIsModeratorMuted = mute_voice; }
|
||||
void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; mNeedsRefresh = true; }
|
||||
void setTimeNow() { mLastActiveTime = LLFrameTimer::getElapsedSeconds(); mNeedsRefresh = true; }
|
||||
void setDistance(F64 dist) { mDistToAgent = dist; mNeedsRefresh = true; }
|
||||
|
|
@ -216,6 +217,7 @@ private:
|
|||
void onAvatarNameCache(const LLAvatarName& av_name); // callback used by fetchAvatarName
|
||||
void updateName(const LLAvatarName& av_name);
|
||||
|
||||
bool mIsModeratorMuted; // default is false
|
||||
bool mIsModerator; // default is false
|
||||
bool mDisplayModeratorLabel; // default is false
|
||||
std::string mDisplayName;
|
||||
|
|
|
|||
|
|
@ -234,6 +234,8 @@ void LLConversationViewSession::draw()
|
|||
// Draw children if root folder, or any other folder that is open. Do not draw children when animating to closed state or you get rendering overlap.
|
||||
bool draw_children = getRoot() == static_cast<LLFolderViewFolder*>(this) || isOpen();
|
||||
|
||||
// Todo/fix this: arrange hides children 'out of bonds', session 'slowly' adjusts container size, unhides children
|
||||
// this process repeats until children fit
|
||||
for (folders_t::iterator iter = mFolders.begin();
|
||||
iter != mFolders.end();)
|
||||
{
|
||||
|
|
@ -254,9 +256,6 @@ void LLConversationViewSession::draw()
|
|||
updateLabelRotation();
|
||||
drawOpenFolderArrow(default_params, sFgColor);
|
||||
}
|
||||
|
||||
refresh();
|
||||
|
||||
LLView::draw();
|
||||
}
|
||||
|
||||
|
|
@ -441,28 +440,23 @@ void LLConversationViewSession::refresh()
|
|||
LLSpeakingIndicatorManager::updateSpeakingIndicators();
|
||||
|
||||
// we should show indicator for specified voice session only if this is current channel. EXT-5562.
|
||||
if (!mIsInActiveVoiceChannel)
|
||||
if (mSpeakingIndicator)
|
||||
{
|
||||
if (mSpeakingIndicator)
|
||||
mSpeakingIndicator->setIsActiveChannel(mIsInActiveVoiceChannel);
|
||||
mSpeakingIndicator->setShowParticipantsSpeaking(mIsInActiveVoiceChannel);
|
||||
}
|
||||
|
||||
LLConversationViewParticipant* participant = NULL;
|
||||
items_t::const_iterator iter;
|
||||
for (iter = getItemsBegin(); iter != getItemsEnd(); iter++)
|
||||
{
|
||||
participant = dynamic_cast<LLConversationViewParticipant*>(*iter);
|
||||
if (participant)
|
||||
{
|
||||
mSpeakingIndicator->setVisible(false);
|
||||
}
|
||||
LLConversationViewParticipant* participant = NULL;
|
||||
items_t::const_iterator iter;
|
||||
for (iter = getItemsBegin(); iter != getItemsEnd(); iter++)
|
||||
{
|
||||
participant = dynamic_cast<LLConversationViewParticipant*>(*iter);
|
||||
if (participant)
|
||||
{
|
||||
participant->hideSpeakingIndicator();
|
||||
}
|
||||
participant->allowSpeakingIndicator(mIsInActiveVoiceChannel);
|
||||
}
|
||||
}
|
||||
|
||||
if (mSpeakingIndicator)
|
||||
{
|
||||
mSpeakingIndicator->setShowParticipantsSpeaking(mIsInActiveVoiceChannel);
|
||||
}
|
||||
|
||||
requestArrange();
|
||||
// Do the regular upstream refresh
|
||||
LLFolderViewFolder::refresh();
|
||||
|
|
@ -474,8 +468,13 @@ void LLConversationViewSession::onCurrentVoiceSessionChanged(const LLUUID& sessi
|
|||
|
||||
if (vmi)
|
||||
{
|
||||
bool old_value = mIsInActiveVoiceChannel;
|
||||
mIsInActiveVoiceChannel = vmi->getUUID() == session_id;
|
||||
mCallIconLayoutPanel->setVisible(mIsInActiveVoiceChannel);
|
||||
if (old_value != mIsInActiveVoiceChannel)
|
||||
{
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -568,6 +567,7 @@ void LLConversationViewParticipant::draw()
|
|||
F32 text_left = (F32)getLabelXPos();
|
||||
|
||||
LLColor4 color;
|
||||
|
||||
LLLocalSpeakerMgr *speakerMgr = LLLocalSpeakerMgr::getInstance();
|
||||
|
||||
if (speakerMgr && speakerMgr->isSpeakerToBeRemoved(mUUID))
|
||||
|
|
@ -579,9 +579,14 @@ void LLConversationViewParticipant::draw()
|
|||
color = mIsSelected ? sHighlightFgColor : sFgColor;
|
||||
}
|
||||
|
||||
LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(getViewModelItem());
|
||||
if (participant_model)
|
||||
{
|
||||
mSpeakingIndicator->setIsModeratorMuted(participant_model->isModeratorMuted());
|
||||
}
|
||||
|
||||
drawHighlight(show_context, mIsSelected, sHighlightBgColor, sFlashBgColor, sFocusOutlineColor, sMouseOverColor);
|
||||
drawLabel(font, text_left, y, color, right_x);
|
||||
refresh();
|
||||
|
||||
LLView::draw();
|
||||
}
|
||||
|
|
@ -605,16 +610,39 @@ S32 LLConversationViewParticipant::arrange(S32* width, S32* height)
|
|||
return arranged;
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLConversationViewParticipant::refresh()
|
||||
{
|
||||
// Refresh the participant view from its model data
|
||||
LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(getViewModelItem());
|
||||
participant_model->resetRefresh();
|
||||
|
||||
// *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat
|
||||
mSpeakingIndicator->setIsModeratorMuted(participant_model->isModeratorMuted());
|
||||
|
||||
// Do the regular upstream refresh
|
||||
LLFolderViewItem::refresh();
|
||||
}
|
||||
|
||||
void LLConversationViewParticipant::addToFolder(LLFolderViewFolder* folder)
|
||||
{
|
||||
// Add the item to the folder (conversation)
|
||||
LLFolderViewItem::addToFolder(folder);
|
||||
|
||||
// Retrieve the folder (conversation) UUID, which is also the speaker session UUID
|
||||
LLConversationItem* vmi = getParentFolder() ? dynamic_cast<LLConversationItem*>(getParentFolder()->getViewModelItem()) : NULL;
|
||||
if (vmi)
|
||||
LLFolderViewFolder *prnt = getParentFolder();
|
||||
if (prnt)
|
||||
{
|
||||
addToSession(vmi->getUUID());
|
||||
LLConversationItem* vmi = dynamic_cast<LLConversationItem*>(prnt->getViewModelItem());
|
||||
if (vmi)
|
||||
{
|
||||
addToSession(vmi->getUUID());
|
||||
}
|
||||
LLConversationViewSession* session = dynamic_cast<LLConversationViewSession*>(prnt);
|
||||
if (session)
|
||||
{
|
||||
allowSpeakingIndicator(session->isInActiveVoiceChannel());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -744,9 +772,9 @@ LLView* LLConversationViewParticipant::getItemChildView(EAvatarListItemChildInde
|
|||
return child_view;
|
||||
}
|
||||
|
||||
void LLConversationViewParticipant::hideSpeakingIndicator()
|
||||
void LLConversationViewParticipant::allowSpeakingIndicator(bool val)
|
||||
{
|
||||
mSpeakingIndicator->setVisible(false);
|
||||
mSpeakingIndicator->setIsActiveChannel(val);
|
||||
}
|
||||
|
||||
// EOF
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ public:
|
|||
void setHighlightState(bool hihglight_state);
|
||||
|
||||
LLFloater* getSessionFloater();
|
||||
bool isInActiveVoiceChannel() { return mIsInActiveVoiceChannel; }
|
||||
|
||||
private:
|
||||
|
||||
|
|
@ -136,6 +137,7 @@ public:
|
|||
virtual ~LLConversationViewParticipant( void );
|
||||
|
||||
bool hasSameValue(const LLUUID& uuid) { return (uuid == mUUID); }
|
||||
/*virtual*/ void refresh();
|
||||
void addToFolder(LLFolderViewFolder* folder);
|
||||
void addToSession(const LLUUID& session_id);
|
||||
|
||||
|
|
@ -144,7 +146,7 @@ public:
|
|||
|
||||
/*virtual*/ S32 getLabelXPos();
|
||||
/*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask );
|
||||
void hideSpeakingIndicator();
|
||||
void allowSpeakingIndicator(bool val);
|
||||
|
||||
protected:
|
||||
friend class LLUICtrlFactory;
|
||||
|
|
|
|||
|
|
@ -315,7 +315,7 @@ void LLDirPickerThread::run()
|
|||
//static
|
||||
void LLDirPickerThread::initClass()
|
||||
{
|
||||
sMutex = new LLMutex(NULL);
|
||||
sMutex = new LLMutex();
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ LLFilePicker::LLFilePicker()
|
|||
mOFN.lpfnHook = NULL;
|
||||
mOFN.lpTemplateName = NULL;
|
||||
mFilesW[0] = '\0';
|
||||
#elif LL_DARWIN
|
||||
mPickOptions = 0;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -812,7 +812,7 @@ bool LLFloaterAvatarPicker::isSelectBtnEnabled()
|
|||
{
|
||||
bool ret_val = visibleItemsSelected();
|
||||
|
||||
if ( ret_val )
|
||||
if ( ret_val && !isMinimized())
|
||||
{
|
||||
std::string acvtive_panel_name;
|
||||
LLScrollListCtrl* list = NULL;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_i
|
|||
mPageSize(gSavedSettings.getS32("ConversationHistoryPageSize")),
|
||||
mAccountName(session_id[LL_FCP_ACCOUNT_NAME]),
|
||||
mCompleteName(session_id[LL_FCP_COMPLETE_NAME]),
|
||||
mMutex(NULL),
|
||||
mMutex(),
|
||||
mShowHistory(false),
|
||||
mMessages(NULL),
|
||||
mHistoryThreadsBusy(false),
|
||||
|
|
|
|||
|
|
@ -269,6 +269,9 @@ BOOL LLFloaterIMContainer::postBuild()
|
|||
// When display name option change, we need to reload all participant names
|
||||
LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMContainer::processParticipantsStyleUpdate, this));
|
||||
|
||||
mParticipantRefreshTimer.setTimerExpirySec(0);
|
||||
mParticipantRefreshTimer.start();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -420,14 +423,66 @@ void LLFloaterIMContainer::processParticipantsStyleUpdate()
|
|||
void LLFloaterIMContainer::idle(void* user_data)
|
||||
{
|
||||
LLFloaterIMContainer* self = static_cast<LLFloaterIMContainer*>(user_data);
|
||||
|
||||
// Update the distance to agent in the nearby chat session if required
|
||||
// Note: it makes no sense of course to update the distance in other session
|
||||
if (self->mConversationViewModel.getSorter().getSortOrderParticipants() == LLConversationFilter::SO_DISTANCE)
|
||||
{
|
||||
self->setNearbyDistances();
|
||||
}
|
||||
self->mConversationsRoot->update();
|
||||
|
||||
if (!self->getVisible() || self->isMinimized())
|
||||
{
|
||||
return;
|
||||
}
|
||||
self->idleUpdate();
|
||||
}
|
||||
|
||||
void LLFloaterIMContainer::idleUpdate()
|
||||
{
|
||||
if (mTabContainer->getTabCount() == 0)
|
||||
{
|
||||
// Do not close the container when every conversation is torn off because the user
|
||||
// still needs the conversation list. Simply collapse the message pane in that case.
|
||||
collapseMessagesPane(true);
|
||||
}
|
||||
|
||||
U32 sort_order = mConversationViewModel.getSorter().getSortOrderParticipants();
|
||||
|
||||
if (mParticipantRefreshTimer.hasExpired())
|
||||
{
|
||||
const LLConversationItem *current_session = getCurSelectedViewModelItem();
|
||||
if (current_session)
|
||||
{
|
||||
// Update moderator options visibility
|
||||
LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = current_session->getChildrenBegin();
|
||||
LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = current_session->getChildrenEnd();
|
||||
bool is_moderator = isGroupModerator();
|
||||
bool can_ban = haveAbilityToBan();
|
||||
while (current_participant_model != end_participant_model)
|
||||
{
|
||||
LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model);
|
||||
participant_model->setModeratorOptionsVisible(is_moderator && participant_model->getUUID() != gAgentID);
|
||||
participant_model->setGroupBanVisible(can_ban && participant_model->getUUID() != gAgentID);
|
||||
|
||||
current_participant_model++;
|
||||
}
|
||||
// Update floater's title as required by the currently selected session or use the default title
|
||||
LLFloaterIMSession * conversation_floaterp = LLFloaterIMSession::findInstance(current_session->getUUID());
|
||||
setTitle(conversation_floaterp && conversation_floaterp->needsTitleOverwrite() ? conversation_floaterp->getTitle() : mGeneralTitle);
|
||||
}
|
||||
|
||||
mParticipantRefreshTimer.setTimerExpirySec(1.0f);
|
||||
}
|
||||
|
||||
// Update the distance to agent in the nearby chat session if required
|
||||
// Note: it makes no sense of course to update the distance in other session
|
||||
if (sort_order == LLConversationFilter::SO_DISTANCE)
|
||||
{
|
||||
// almost real-time updates
|
||||
setNearbyDistances(); //calls arrange all
|
||||
}
|
||||
mConversationsRoot->update(); //arranges, resizes, heavy
|
||||
|
||||
// "Manually" resize of mConversationsPane: same as temporarity cancellation of the flag "auto_resize=false" for it
|
||||
if (!mConversationsPane->isCollapsed() && mMessagesPane->isCollapsed())
|
||||
{
|
||||
LLRect stack_rect = mConversationsStack->getRect();
|
||||
mConversationsPane->reshape(stack_rect.getWidth(), stack_rect.getHeight(), true);
|
||||
}
|
||||
}
|
||||
|
||||
bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
|
||||
|
|
@ -526,39 +581,6 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
|
|||
|
||||
void LLFloaterIMContainer::draw()
|
||||
{
|
||||
if (mTabContainer->getTabCount() == 0)
|
||||
{
|
||||
// Do not close the container when every conversation is torn off because the user
|
||||
// still needs the conversation list. Simply collapse the message pane in that case.
|
||||
collapseMessagesPane(true);
|
||||
}
|
||||
|
||||
const LLConversationItem *current_session = getCurSelectedViewModelItem();
|
||||
if (current_session)
|
||||
{
|
||||
// Update moderator options visibility
|
||||
LLFolderViewModelItemCommon::child_list_t::const_iterator current_participant_model = current_session->getChildrenBegin();
|
||||
LLFolderViewModelItemCommon::child_list_t::const_iterator end_participant_model = current_session->getChildrenEnd();
|
||||
while (current_participant_model != end_participant_model)
|
||||
{
|
||||
LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model);
|
||||
participant_model->setModeratorOptionsVisible(isGroupModerator() && participant_model->getUUID() != gAgentID);
|
||||
participant_model->setGroupBanVisible(haveAbilityToBan() && participant_model->getUUID() != gAgentID);
|
||||
|
||||
current_participant_model++;
|
||||
}
|
||||
// Update floater's title as required by the currently selected session or use the default title
|
||||
LLFloaterIMSession * conversation_floaterp = LLFloaterIMSession::findInstance(current_session->getUUID());
|
||||
setTitle(conversation_floaterp && conversation_floaterp->needsTitleOverwrite() ? conversation_floaterp->getTitle() : mGeneralTitle);
|
||||
}
|
||||
|
||||
// "Manually" resize of mConversationsPane: same as temporarity cancellation of the flag "auto_resize=false" for it
|
||||
if (!mConversationsPane->isCollapsed() && mMessagesPane->isCollapsed())
|
||||
{
|
||||
LLRect stack_rect = mConversationsStack->getRect();
|
||||
mConversationsPane->reshape(stack_rect.getWidth(), stack_rect.getHeight(), true);
|
||||
}
|
||||
|
||||
LLFloater::draw();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -180,6 +180,8 @@ private:
|
|||
void openNearbyChat();
|
||||
bool isParticipantListExpanded();
|
||||
|
||||
void idleUpdate(); // for convenience (self) from static idle
|
||||
|
||||
LLButton* mExpandCollapseBtn;
|
||||
LLButton* mStubCollapseBtn;
|
||||
LLButton* mSpeakBtn;
|
||||
|
|
@ -226,6 +228,8 @@ private:
|
|||
LLConversationViewModel mConversationViewModel;
|
||||
LLFolderView* mConversationsRoot;
|
||||
LLEventStream mConversationsEventStream;
|
||||
|
||||
LLTimer mParticipantRefreshTimer;
|
||||
};
|
||||
|
||||
#endif // LL_LLFLOATERIMCONTAINER_H
|
||||
|
|
|
|||
|
|
@ -416,6 +416,7 @@ BOOL LLPanelLandGeneral::postBuild()
|
|||
mTextSalePending = getChild<LLTextBox>("SalePending");
|
||||
mTextOwnerLabel = getChild<LLTextBox>("Owner:");
|
||||
mTextOwner = getChild<LLTextBox>("OwnerText");
|
||||
mTextOwner->setIsFriendCallback(LLAvatarActions::isFriend);
|
||||
|
||||
mContentRating = getChild<LLTextBox>("ContentRatingText");
|
||||
mLandType = getChild<LLTextBox>("LandTypeText");
|
||||
|
|
@ -1192,6 +1193,7 @@ BOOL LLPanelLandObjects::postBuild()
|
|||
mIconGroup = LLUIImageList::getInstance()->getUIImage("icon_group.tga", 0);
|
||||
|
||||
mOwnerList = getChild<LLNameListCtrl>("owner list");
|
||||
mOwnerList->setIsFriendCallback(LLAvatarActions::isFriend);
|
||||
mOwnerList->sortByColumnIndex(3, FALSE);
|
||||
childSetCommitCallback("owner list", onCommitList, this);
|
||||
mOwnerList->setDoubleClickCallback(onDoubleClickOwner, this);
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ mCalculateBtn(NULL)
|
|||
sInstance = this;
|
||||
mLastMouseX = 0;
|
||||
mLastMouseY = 0;
|
||||
mStatusLock = new LLMutex(NULL);
|
||||
mStatusLock = new LLMutex();
|
||||
mModelPreview = NULL;
|
||||
|
||||
mLODMode[LLModel::LOD_HIGH] = 0;
|
||||
|
|
@ -1208,7 +1208,7 @@ void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handl
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
|
||||
: LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex(NULL)
|
||||
: LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex()
|
||||
, mLodsQuery()
|
||||
, mLodsWithParsingError()
|
||||
, mPelvisZOffset( 0.0f )
|
||||
|
|
@ -1418,8 +1418,6 @@ void LLModelPreview::rebuildUploadData()
|
|||
|
||||
std::string requested_name = mFMP->getChild<LLUICtrl>("description_form")->getValue().asString();
|
||||
|
||||
std::string metric = mFMP->getChild<LLUICtrl>("model_category_combo")->getValue().asString();
|
||||
|
||||
LLSpinCtrl* scale_spinner = mFMP->getChild<LLSpinCtrl>("import_scale");
|
||||
|
||||
F32 scale = scale_spinner->getValue().asReal();
|
||||
|
|
@ -1460,7 +1458,6 @@ void LLModelPreview::rebuildUploadData()
|
|||
if (base_model && !requested_name.empty())
|
||||
{
|
||||
base_model->mRequestedLabel = requested_name;
|
||||
base_model->mMetric = metric;
|
||||
}
|
||||
|
||||
for (int i = LLModel::NUM_LODS - 1; i >= LLModel::LOD_IMPOSTOR; i--)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,294 @@
|
|||
/**
|
||||
* @file llfloatermyscripts.cpp
|
||||
* @brief LLFloaterMyScripts class implementation.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2019, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
#include "llfloatermyscripts.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llcorehttputil.h"
|
||||
#include "llcoros.h"
|
||||
#include "lleventcoro.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llscrolllistctrl.h"
|
||||
#include "lltrans.h"
|
||||
#include "llviewerregion.h"
|
||||
|
||||
const S32 SIZE_OF_ONE_KB = 1024;
|
||||
|
||||
LLFloaterMyScripts::LLFloaterMyScripts(const LLSD& seed)
|
||||
: LLFloater(seed),
|
||||
mGotAttachmentMemoryUsed(false),
|
||||
mAttachmentMemoryMax(0),
|
||||
mAttachmentMemoryUsed(0),
|
||||
mGotAttachmentURLsUsed(false),
|
||||
mAttachmentURLsMax(0),
|
||||
mAttachmentURLsUsed(0)
|
||||
{
|
||||
}
|
||||
|
||||
BOOL LLFloaterMyScripts::postBuild()
|
||||
{
|
||||
childSetAction("refresh_list_btn", onClickRefresh, this);
|
||||
|
||||
std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
|
||||
getChild<LLUICtrl>("loading_text")->setValue(LLSD(msg_waiting));
|
||||
return requestAttachmentDetails();
|
||||
}
|
||||
|
||||
BOOL LLFloaterMyScripts::requestAttachmentDetails()
|
||||
{
|
||||
if (!gAgent.getRegion()) return FALSE;
|
||||
|
||||
LLSD body;
|
||||
std::string url = gAgent.getRegion()->getCapability("AttachmentResources");
|
||||
if (!url.empty())
|
||||
{
|
||||
LLCoros::instance().launch("LLFloaterMyScripts::getAttachmentLimitsCoro",
|
||||
boost::bind(&LLFloaterMyScripts::getAttachmentLimitsCoro, this, url));
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterMyScripts::getAttachmentLimitsCoro(std::string url)
|
||||
{
|
||||
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
|
||||
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
|
||||
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getAttachmentLimitsCoro", httpPolicy));
|
||||
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
|
||||
|
||||
LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
|
||||
|
||||
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
|
||||
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
LL_WARNS() << "Unable to retrieve attachment limits." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LLFloaterMyScripts* instance = LLFloaterReg::getTypedInstance<LLFloaterMyScripts>("my_scripts");
|
||||
|
||||
if (!instance)
|
||||
{
|
||||
LL_WARNS() << "Failed to get LLFloaterMyScripts instance" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
instance->getChild<LLUICtrl>("loading_text")->setValue(LLSD(std::string("")));
|
||||
|
||||
LLButton* btn = instance->getChild<LLButton>("refresh_list_btn");
|
||||
if (btn)
|
||||
{
|
||||
btn->setEnabled(true);
|
||||
}
|
||||
|
||||
result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
|
||||
instance->setAttachmentDetails(result);
|
||||
}
|
||||
|
||||
|
||||
void LLFloaterMyScripts::setAttachmentDetails(LLSD content)
|
||||
{
|
||||
LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
|
||||
|
||||
if(!list)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
S32 number_attachments = content["attachments"].size();
|
||||
|
||||
for(int i = 0; i < number_attachments; i++)
|
||||
{
|
||||
std::string humanReadableLocation = "";
|
||||
if(content["attachments"][i].has("location"))
|
||||
{
|
||||
std::string actualLocation = content["attachments"][i]["location"];
|
||||
humanReadableLocation = LLTrans::getString(actualLocation.c_str());
|
||||
}
|
||||
|
||||
S32 number_objects = content["attachments"][i]["objects"].size();
|
||||
for(int j = 0; j < number_objects; j++)
|
||||
{
|
||||
LLUUID task_id = content["attachments"][i]["objects"][j]["id"].asUUID();
|
||||
S32 size = 0;
|
||||
if(content["attachments"][i]["objects"][j]["resources"].has("memory"))
|
||||
{
|
||||
size = content["attachments"][i]["objects"][j]["resources"]["memory"].asInteger() / SIZE_OF_ONE_KB;
|
||||
}
|
||||
S32 urls = 0;
|
||||
if(content["attachments"][i]["objects"][j]["resources"].has("urls"))
|
||||
{
|
||||
urls = content["attachments"][i]["objects"][j]["resources"]["urls"].asInteger();
|
||||
}
|
||||
std::string name = content["attachments"][i]["objects"][j]["name"].asString();
|
||||
|
||||
LLSD element;
|
||||
|
||||
element["id"] = task_id;
|
||||
element["columns"][0]["column"] = "size";
|
||||
element["columns"][0]["value"] = llformat("%d", size);
|
||||
element["columns"][0]["font"] = "SANSSERIF";
|
||||
element["columns"][0]["halign"] = LLFontGL::RIGHT;
|
||||
|
||||
element["columns"][1]["column"] = "urls";
|
||||
element["columns"][1]["value"] = llformat("%d", urls);
|
||||
element["columns"][1]["font"] = "SANSSERIF";
|
||||
element["columns"][1]["halign"] = LLFontGL::RIGHT;
|
||||
|
||||
element["columns"][2]["column"] = "name";
|
||||
element["columns"][2]["value"] = name;
|
||||
element["columns"][2]["font"] = "SANSSERIF";
|
||||
|
||||
element["columns"][3]["column"] = "location";
|
||||
element["columns"][3]["value"] = humanReadableLocation;
|
||||
element["columns"][3]["font"] = "SANSSERIF";
|
||||
|
||||
list->addElement(element);
|
||||
}
|
||||
}
|
||||
|
||||
setAttachmentSummary(content);
|
||||
|
||||
getChild<LLUICtrl>("loading_text")->setValue(LLSD(std::string("")));
|
||||
|
||||
LLButton* btn = getChild<LLButton>("refresh_list_btn");
|
||||
if(btn)
|
||||
{
|
||||
btn->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterMyScripts::clearList()
|
||||
{
|
||||
LLCtrlListInterface *list = childGetListInterface("scripts_list");
|
||||
|
||||
if (list)
|
||||
{
|
||||
list->operateOnAll(LLCtrlListInterface::OP_DELETE);
|
||||
}
|
||||
|
||||
std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
|
||||
getChild<LLUICtrl>("loading_text")->setValue(LLSD(msg_waiting));
|
||||
}
|
||||
|
||||
void LLFloaterMyScripts::setAttachmentSummary(LLSD content)
|
||||
{
|
||||
if(content["summary"]["used"][0]["type"].asString() == std::string("memory"))
|
||||
{
|
||||
mAttachmentMemoryUsed = content["summary"]["used"][0]["amount"].asInteger() / SIZE_OF_ONE_KB;
|
||||
mAttachmentMemoryMax = content["summary"]["available"][0]["amount"].asInteger() / SIZE_OF_ONE_KB;
|
||||
mGotAttachmentMemoryUsed = true;
|
||||
}
|
||||
else if(content["summary"]["used"][1]["type"].asString() == std::string("memory"))
|
||||
{
|
||||
mAttachmentMemoryUsed = content["summary"]["used"][1]["amount"].asInteger() / SIZE_OF_ONE_KB;
|
||||
mAttachmentMemoryMax = content["summary"]["available"][1]["amount"].asInteger() / SIZE_OF_ONE_KB;
|
||||
mGotAttachmentMemoryUsed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "attachment details don't contain memory summary info" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
if(content["summary"]["used"][0]["type"].asString() == std::string("urls"))
|
||||
{
|
||||
mAttachmentURLsUsed = content["summary"]["used"][0]["amount"].asInteger();
|
||||
mAttachmentURLsMax = content["summary"]["available"][0]["amount"].asInteger();
|
||||
mGotAttachmentURLsUsed = true;
|
||||
}
|
||||
else if(content["summary"]["used"][1]["type"].asString() == std::string("urls"))
|
||||
{
|
||||
mAttachmentURLsUsed = content["summary"]["used"][1]["amount"].asInteger();
|
||||
mAttachmentURLsMax = content["summary"]["available"][1]["amount"].asInteger();
|
||||
mGotAttachmentURLsUsed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "attachment details don't contain urls summary info" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
if((mAttachmentMemoryUsed >= 0) && (mAttachmentMemoryMax >= 0))
|
||||
{
|
||||
LLStringUtil::format_map_t args_attachment_memory;
|
||||
args_attachment_memory["[COUNT]"] = llformat ("%d", mAttachmentMemoryUsed);
|
||||
std::string translate_message = "ScriptLimitsMemoryUsedSimple";
|
||||
|
||||
if (0 < mAttachmentMemoryMax)
|
||||
{
|
||||
S32 attachment_memory_available = mAttachmentMemoryMax - mAttachmentMemoryUsed;
|
||||
|
||||
args_attachment_memory["[MAX]"] = llformat ("%d", mAttachmentMemoryMax);
|
||||
args_attachment_memory["[AVAILABLE]"] = llformat ("%d", attachment_memory_available);
|
||||
translate_message = "ScriptLimitsMemoryUsed";
|
||||
}
|
||||
|
||||
getChild<LLUICtrl>("memory_used")->setValue(LLTrans::getString(translate_message, args_attachment_memory));
|
||||
}
|
||||
|
||||
if((mAttachmentURLsUsed >= 0) && (mAttachmentURLsMax >= 0))
|
||||
{
|
||||
S32 attachment_urls_available = mAttachmentURLsMax - mAttachmentURLsUsed;
|
||||
|
||||
LLStringUtil::format_map_t args_attachment_urls;
|
||||
args_attachment_urls["[COUNT]"] = llformat ("%d", mAttachmentURLsUsed);
|
||||
args_attachment_urls["[MAX]"] = llformat ("%d", mAttachmentURLsMax);
|
||||
args_attachment_urls["[AVAILABLE]"] = llformat ("%d", attachment_urls_available);
|
||||
std::string msg_attachment_urls = LLTrans::getString("ScriptLimitsURLsUsed", args_attachment_urls);
|
||||
getChild<LLUICtrl>("urls_used")->setValue(LLSD(msg_attachment_urls));
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLFloaterMyScripts::onClickRefresh(void* userdata)
|
||||
{
|
||||
LLFloaterMyScripts* instance = LLFloaterReg::getTypedInstance<LLFloaterMyScripts>("my_scripts");
|
||||
if(instance)
|
||||
{
|
||||
LLButton* btn = instance->getChild<LLButton>("refresh_list_btn");
|
||||
|
||||
//To stop people from hammering the refesh button and accidentally dosing themselves - enough requests can crash the viewer!
|
||||
//turn the button off, then turn it on when we get a response
|
||||
if(btn)
|
||||
{
|
||||
btn->setEnabled(false);
|
||||
}
|
||||
instance->clearList();
|
||||
instance->requestAttachmentDetails();
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "could not find LLFloaterMyScripts instance after refresh button clicked" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* @file llfloatermyscripts.h
|
||||
* @brief LLFloaterMyScripts class definition.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2019, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLFLOATERMYSCRIPTS_H
|
||||
#define LL_LLFLOATERMYSCRIPTS_H
|
||||
|
||||
#include "llfloater.h"
|
||||
#include "llpanel.h"
|
||||
|
||||
class LLFloaterMyScripts : public LLFloater
|
||||
{
|
||||
public:
|
||||
LLFloaterMyScripts(const LLSD& seed);
|
||||
|
||||
BOOL postBuild();
|
||||
void setAttachmentDetails(LLSD content);
|
||||
void setAttachmentSummary(LLSD content);
|
||||
BOOL requestAttachmentDetails();
|
||||
void clearList();
|
||||
|
||||
private:
|
||||
void getAttachmentLimitsCoro(std::string url);
|
||||
|
||||
bool mGotAttachmentMemoryUsed;
|
||||
S32 mAttachmentMemoryMax;
|
||||
S32 mAttachmentMemoryUsed;
|
||||
|
||||
bool mGotAttachmentURLsUsed;
|
||||
S32 mAttachmentURLsMax;
|
||||
S32 mAttachmentURLsUsed;
|
||||
|
||||
protected:
|
||||
|
||||
static void onClickRefresh(void* userdata);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -117,6 +117,8 @@
|
|||
#include "llfeaturemanager.h"
|
||||
#include "llviewertexturelist.h"
|
||||
|
||||
#include "llsearchableui.h"
|
||||
|
||||
const F32 BANDWIDTH_UPDATER_TIMEOUT = 0.5f;
|
||||
char const* const VISIBILITY_DEFAULT = "default";
|
||||
char const* const VISIBILITY_HIDDEN = "hidden";
|
||||
|
|
@ -136,6 +138,25 @@ static const F32 MIN_ARC_LOG = log(MIN_ARC_LIMIT);
|
|||
static const F32 MAX_ARC_LOG = log(MAX_ARC_LIMIT);
|
||||
static const F32 ARC_LIMIT_MAP_SCALE = (MAX_ARC_LOG - MIN_ARC_LOG) / (MAX_INDIRECT_ARC_LIMIT - MIN_INDIRECT_ARC_LIMIT);
|
||||
|
||||
struct LabelDef : public LLInitParam::Block<LabelDef>
|
||||
{
|
||||
Mandatory<std::string> name;
|
||||
Mandatory<std::string> value;
|
||||
|
||||
LabelDef()
|
||||
: name("name"),
|
||||
value("value")
|
||||
{}
|
||||
};
|
||||
|
||||
struct LabelTable : public LLInitParam::Block<LabelTable>
|
||||
{
|
||||
Multiple<LabelDef> labels;
|
||||
LabelTable()
|
||||
: labels("label")
|
||||
{}
|
||||
};
|
||||
|
||||
class LLVoiceSetKeyDialog : public LLModalDialog
|
||||
{
|
||||
public:
|
||||
|
|
@ -393,6 +414,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
|
|||
|
||||
mCommitCallbackRegistrar.add("Pref.ClearLog", boost::bind(&LLConversationLog::onClearLog, &LLConversationLog::instance()));
|
||||
mCommitCallbackRegistrar.add("Pref.DeleteTranscripts", boost::bind(&LLFloaterPreference::onDeleteTranscripts, this));
|
||||
mCommitCallbackRegistrar.add("UpdateFilter", boost::bind(&LLFloaterPreference::onUpdateFilterTerm, this, false)); // <FS:ND/> Hook up for filtering
|
||||
}
|
||||
|
||||
void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType type )
|
||||
|
|
@ -506,7 +528,33 @@ BOOL LLFloaterPreference::postBuild()
|
|||
LLSliderCtrl* fov_slider = getChild<LLSliderCtrl>("camera_fov");
|
||||
fov_slider->setMinValue(LLViewerCamera::getInstance()->getMinView());
|
||||
fov_slider->setMaxValue(LLViewerCamera::getInstance()->getMaxView());
|
||||
|
||||
// Hook up and init for filtering
|
||||
mFilterEdit = getChild<LLSearchEditor>("search_prefs_edit");
|
||||
mFilterEdit->setKeystrokeCallback(boost::bind(&LLFloaterPreference::onUpdateFilterTerm, this, false));
|
||||
|
||||
// Load and assign label for 'default language'
|
||||
std::string user_filename = gDirUtilp->getExpandedFilename(LL_PATH_DEFAULT_SKIN, "default_languages.xml");
|
||||
std::map<std::string, std::string> labels;
|
||||
if (loadFromFilename(user_filename, labels))
|
||||
{
|
||||
std::string system_lang = gSavedSettings.getString("SystemLanguage");
|
||||
std::map<std::string, std::string>::iterator iter = labels.find(system_lang);
|
||||
if (iter != labels.end())
|
||||
{
|
||||
getChild<LLComboBox>("language_combobox")->add(iter->second, LLSD("default"), ADD_TOP, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Language \"" << system_lang << "\" is not in default_languages.xml" << LL_ENDL;
|
||||
getChild<LLComboBox>("language_combobox")->add("System default", LLSD("default"), ADD_TOP, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Failed to load labels from " << user_filename << ". Using default." << LL_ENDL;
|
||||
getChild<LLComboBox>("language_combobox")->add("System default", LLSD("default"), ADD_TOP, true);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -2349,6 +2397,7 @@ BOOL LLPanelPreference::postBuild()
|
|||
if (hasChild("mute_chb_label", TRUE))
|
||||
{
|
||||
getChild<LLTextBox>("mute_chb_label")->setShowCursorHand(false);
|
||||
getChild<LLTextBox>("mute_chb_label")->setSoundFlags(LLView::MOUSE_UP);
|
||||
getChild<LLTextBox>("mute_chb_label")->setClickedCallback(boost::bind(&toggleMuteWhenMinimized));
|
||||
}
|
||||
|
||||
|
|
@ -2472,6 +2521,11 @@ void LLPanelPreference::toggleMuteWhenMinimized()
|
|||
{
|
||||
std::string mute("MuteWhenMinimized");
|
||||
gSavedSettings.setBOOL(mute, !gSavedSettings.getBOOL(mute));
|
||||
LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
|
||||
if (instance)
|
||||
{
|
||||
instance->getChild<LLCheckBoxCtrl>("mute_when_minimized")->setBtnFocus();
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelPreference::cancel()
|
||||
|
|
@ -3079,3 +3133,109 @@ void LLFloaterPreferenceProxy::onChangeSocksSettings()
|
|||
|
||||
}
|
||||
|
||||
void LLFloaterPreference::onUpdateFilterTerm(bool force)
|
||||
{
|
||||
LLWString seachValue = utf8str_to_wstring( mFilterEdit->getValue() );
|
||||
LLWStringUtil::toLower( seachValue );
|
||||
|
||||
if( !mSearchData || (mSearchData->mLastFilter == seachValue && !force))
|
||||
return;
|
||||
|
||||
mSearchData->mLastFilter = seachValue;
|
||||
|
||||
if( !mSearchData->mRootTab )
|
||||
return;
|
||||
|
||||
mSearchData->mRootTab->hightlightAndHide( seachValue );
|
||||
LLTabContainer *pRoot = getChild< LLTabContainer >( "pref core" );
|
||||
if( pRoot )
|
||||
pRoot->selectFirstTab();
|
||||
}
|
||||
|
||||
void collectChildren( LLView const *aView, ll::prefs::PanelDataPtr aParentPanel, ll::prefs::TabContainerDataPtr aParentTabContainer )
|
||||
{
|
||||
if( !aView )
|
||||
return;
|
||||
|
||||
llassert_always( aParentPanel || aParentTabContainer );
|
||||
|
||||
LLView::child_list_const_iter_t itr = aView->beginChild();
|
||||
LLView::child_list_const_iter_t itrEnd = aView->endChild();
|
||||
|
||||
while( itr != itrEnd )
|
||||
{
|
||||
LLView *pView = *itr;
|
||||
ll::prefs::PanelDataPtr pCurPanelData = aParentPanel;
|
||||
ll::prefs::TabContainerDataPtr pCurTabContainer = aParentTabContainer;
|
||||
if( !pView )
|
||||
continue;
|
||||
LLPanel const *pPanel = dynamic_cast< LLPanel const *>( pView );
|
||||
LLTabContainer const *pTabContainer = dynamic_cast< LLTabContainer const *>( pView );
|
||||
ll::ui::SearchableControl const *pSCtrl = dynamic_cast< ll::ui::SearchableControl const *>( pView );
|
||||
|
||||
if( pTabContainer )
|
||||
{
|
||||
pCurPanelData.reset();
|
||||
|
||||
pCurTabContainer = ll::prefs::TabContainerDataPtr( new ll::prefs::TabContainerData );
|
||||
pCurTabContainer->mTabContainer = const_cast< LLTabContainer *>( pTabContainer );
|
||||
pCurTabContainer->mLabel = pTabContainer->getLabel();
|
||||
pCurTabContainer->mPanel = 0;
|
||||
|
||||
if( aParentPanel )
|
||||
aParentPanel->mChildPanel.push_back( pCurTabContainer );
|
||||
if( aParentTabContainer )
|
||||
aParentTabContainer->mChildPanel.push_back( pCurTabContainer );
|
||||
}
|
||||
else if( pPanel )
|
||||
{
|
||||
pCurTabContainer.reset();
|
||||
|
||||
pCurPanelData = ll::prefs::PanelDataPtr( new ll::prefs::PanelData );
|
||||
pCurPanelData->mPanel = pPanel;
|
||||
pCurPanelData->mLabel = pPanel->getLabel();
|
||||
|
||||
llassert_always( aParentPanel || aParentTabContainer );
|
||||
|
||||
if( aParentTabContainer )
|
||||
aParentTabContainer->mChildPanel.push_back( pCurPanelData );
|
||||
else if( aParentPanel )
|
||||
aParentPanel->mChildPanel.push_back( pCurPanelData );
|
||||
}
|
||||
else if( pSCtrl && pSCtrl->getSearchText().size() )
|
||||
{
|
||||
ll::prefs::SearchableItemPtr item = ll::prefs::SearchableItemPtr( new ll::prefs::SearchableItem() );
|
||||
item->mView = pView;
|
||||
item->mCtrl = pSCtrl;
|
||||
|
||||
item->mLabel = utf8str_to_wstring( pSCtrl->getSearchText() );
|
||||
LLWStringUtil::toLower( item->mLabel );
|
||||
|
||||
llassert_always( aParentPanel || aParentTabContainer );
|
||||
|
||||
if( aParentPanel )
|
||||
aParentPanel->mChildren.push_back( item );
|
||||
if( aParentTabContainer )
|
||||
aParentTabContainer->mChildren.push_back( item );
|
||||
}
|
||||
collectChildren( pView, pCurPanelData, pCurTabContainer );
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterPreference::collectSearchableItems()
|
||||
{
|
||||
mSearchData.reset( nullptr );
|
||||
LLTabContainer *pRoot = getChild< LLTabContainer >( "pref core" );
|
||||
if( mFilterEdit && pRoot )
|
||||
{
|
||||
mSearchData.reset(new ll::prefs::SearchData() );
|
||||
|
||||
ll::prefs::TabContainerDataPtr pRootTabcontainer = ll::prefs::TabContainerDataPtr( new ll::prefs::TabContainerData );
|
||||
pRootTabcontainer->mTabContainer = pRoot;
|
||||
pRootTabcontainer->mLabel = pRoot->getLabel();
|
||||
mSearchData->mRootTab = pRootTabcontainer;
|
||||
|
||||
collectChildren( this, ll::prefs::PanelDataPtr(), pRootTabcontainer );
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "llfloater.h"
|
||||
#include "llavatarpropertiesprocessor.h"
|
||||
#include "llconversationlog.h"
|
||||
#include "llsearcheditor.h"
|
||||
|
||||
class LLConversationLogObserver;
|
||||
class LLPanelPreference;
|
||||
|
|
@ -47,6 +48,14 @@ class LLSliderCtrl;
|
|||
class LLSD;
|
||||
class LLTextBox;
|
||||
|
||||
namespace ll
|
||||
{
|
||||
namespace prefs
|
||||
{
|
||||
struct SearchData;
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::map<std::string, std::string> notifications_map;
|
||||
|
||||
typedef enum
|
||||
|
|
@ -207,6 +216,12 @@ private:
|
|||
std::string mSavedCameraPreset;
|
||||
std::string mSavedGraphicsPreset;
|
||||
LOG_CLASS(LLFloaterPreference);
|
||||
|
||||
LLSearchEditor *mFilterEdit;
|
||||
std::unique_ptr< ll::prefs::SearchData > mSearchData;
|
||||
|
||||
void onUpdateFilterTerm( bool force = false );
|
||||
void collectSearchableItems();
|
||||
};
|
||||
|
||||
class LLPanelPreference : public LLPanel
|
||||
|
|
@ -256,18 +271,6 @@ private:
|
|||
LOG_CLASS(LLPanelPreference);
|
||||
};
|
||||
|
||||
class LLPanelPreferenceView : public LLPanelPreference
|
||||
{
|
||||
public:
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
void setPresetText();
|
||||
|
||||
private:
|
||||
void onPresetsListChangeCamera();
|
||||
LOG_CLASS(LLPanelPreferenceView);
|
||||
};
|
||||
|
||||
class LLPanelPreferenceGraphics : public LLPanelPreference
|
||||
{
|
||||
public:
|
||||
|
|
@ -285,6 +288,7 @@ protected:
|
|||
bool hasDirtyChilds();
|
||||
|
||||
private:
|
||||
|
||||
void onPresetsListChange();
|
||||
LOG_CLASS(LLPanelPreferenceGraphics);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -90,19 +90,6 @@ LLFloaterScriptLimits::LLFloaterScriptLimits(const LLSD& seed)
|
|||
|
||||
BOOL LLFloaterScriptLimits::postBuild()
|
||||
{
|
||||
// a little cheap and cheerful - if there's an about land panel open default to showing parcel info,
|
||||
// otherwise default to showing attachments (avatar appearance)
|
||||
bool selectParcelPanel = false;
|
||||
|
||||
LLFloaterLand* instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land");
|
||||
if(instance)
|
||||
{
|
||||
if(instance->isShown())
|
||||
{
|
||||
selectParcelPanel = true;
|
||||
}
|
||||
}
|
||||
|
||||
mTab = getChild<LLTabContainer>("scriptlimits_panels");
|
||||
|
||||
if(!mTab)
|
||||
|
|
@ -111,28 +98,12 @@ BOOL LLFloaterScriptLimits::postBuild()
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
// contruct the panels
|
||||
// contruct the panel
|
||||
LLPanelScriptLimitsRegionMemory* panel_memory = new LLPanelScriptLimitsRegionMemory;
|
||||
mInfoPanels.push_back(panel_memory);
|
||||
panel_memory->buildFromFile( "panel_script_limits_region_memory.xml");
|
||||
mTab->addTabPanel(panel_memory);
|
||||
|
||||
LLPanelScriptLimitsAttachment* panel_attachments = new LLPanelScriptLimitsAttachment;
|
||||
mInfoPanels.push_back(panel_attachments);
|
||||
panel_attachments->buildFromFile("panel_script_limits_my_avatar.xml");
|
||||
mTab->addTabPanel(panel_attachments);
|
||||
|
||||
|
||||
if(mInfoPanels.size() > 0)
|
||||
{
|
||||
mTab->selectTab(0);
|
||||
}
|
||||
|
||||
if(!selectParcelPanel && (mInfoPanels.size() > 1))
|
||||
{
|
||||
mTab->selectTab(1);
|
||||
}
|
||||
|
||||
mTab->selectTab(0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -969,269 +940,3 @@ void LLPanelScriptLimitsRegionMemory::onClickReturn(void* userdata)
|
|||
}
|
||||
}
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
// Attachment Panel
|
||||
///----------------------------------------------------------------------------
|
||||
|
||||
BOOL LLPanelScriptLimitsAttachment::requestAttachmentDetails()
|
||||
{
|
||||
if (!gAgent.getRegion()) return FALSE;
|
||||
|
||||
LLSD body;
|
||||
std::string url = gAgent.getRegion()->getCapability("AttachmentResources");
|
||||
if (!url.empty())
|
||||
{
|
||||
LLCoros::instance().launch("LLPanelScriptLimitsAttachment::getAttachmentLimitsCoro",
|
||||
boost::bind(&LLPanelScriptLimitsAttachment::getAttachmentLimitsCoro, this, url));
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void LLPanelScriptLimitsAttachment::getAttachmentLimitsCoro(std::string url)
|
||||
{
|
||||
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
|
||||
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
|
||||
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getAttachmentLimitsCoro", httpPolicy));
|
||||
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
|
||||
|
||||
LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
|
||||
|
||||
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
|
||||
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
LL_WARNS() << "Unable to retrieve attachment limits." << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
|
||||
|
||||
if (!instance)
|
||||
{
|
||||
LL_WARNS() << "Failed to get llfloaterscriptlimits instance" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
|
||||
if (!tab)
|
||||
{
|
||||
LL_WARNS() << "Failed to get scriptlimits_panels" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
LLPanelScriptLimitsAttachment* panel = (LLPanelScriptLimitsAttachment*)tab->getChild<LLPanel>("script_limits_my_avatar_panel");
|
||||
if (!panel)
|
||||
{
|
||||
LL_WARNS() << "Failed to get script_limits_my_avatar_panel" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
panel->getChild<LLUICtrl>("loading_text")->setValue(LLSD(std::string("")));
|
||||
|
||||
LLButton* btn = panel->getChild<LLButton>("refresh_list_btn");
|
||||
if (btn)
|
||||
{
|
||||
btn->setEnabled(true);
|
||||
}
|
||||
|
||||
result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
|
||||
panel->setAttachmentDetails(result);
|
||||
}
|
||||
|
||||
|
||||
void LLPanelScriptLimitsAttachment::setAttachmentDetails(LLSD content)
|
||||
{
|
||||
LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
|
||||
|
||||
if(!list)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
S32 number_attachments = content["attachments"].size();
|
||||
|
||||
for(int i = 0; i < number_attachments; i++)
|
||||
{
|
||||
std::string humanReadableLocation = "";
|
||||
if(content["attachments"][i].has("location"))
|
||||
{
|
||||
std::string actualLocation = content["attachments"][i]["location"];
|
||||
humanReadableLocation = LLTrans::getString(actualLocation.c_str());
|
||||
}
|
||||
|
||||
S32 number_objects = content["attachments"][i]["objects"].size();
|
||||
for(int j = 0; j < number_objects; j++)
|
||||
{
|
||||
LLUUID task_id = content["attachments"][i]["objects"][j]["id"].asUUID();
|
||||
S32 size = 0;
|
||||
if(content["attachments"][i]["objects"][j]["resources"].has("memory"))
|
||||
{
|
||||
size = content["attachments"][i]["objects"][j]["resources"]["memory"].asInteger() / SIZE_OF_ONE_KB;
|
||||
}
|
||||
S32 urls = 0;
|
||||
if(content["attachments"][i]["objects"][j]["resources"].has("urls"))
|
||||
{
|
||||
urls = content["attachments"][i]["objects"][j]["resources"]["urls"].asInteger();
|
||||
}
|
||||
std::string name = content["attachments"][i]["objects"][j]["name"].asString();
|
||||
|
||||
LLSD element;
|
||||
|
||||
element["id"] = task_id;
|
||||
element["columns"][0]["column"] = "size";
|
||||
element["columns"][0]["value"] = llformat("%d", size);
|
||||
element["columns"][0]["font"] = "SANSSERIF";
|
||||
element["columns"][0]["halign"] = LLFontGL::RIGHT;
|
||||
|
||||
element["columns"][1]["column"] = "urls";
|
||||
element["columns"][1]["value"] = llformat("%d", urls);
|
||||
element["columns"][1]["font"] = "SANSSERIF";
|
||||
element["columns"][1]["halign"] = LLFontGL::RIGHT;
|
||||
|
||||
element["columns"][2]["column"] = "name";
|
||||
element["columns"][2]["value"] = name;
|
||||
element["columns"][2]["font"] = "SANSSERIF";
|
||||
|
||||
element["columns"][3]["column"] = "location";
|
||||
element["columns"][3]["value"] = humanReadableLocation;
|
||||
element["columns"][3]["font"] = "SANSSERIF";
|
||||
|
||||
list->addElement(element);
|
||||
}
|
||||
}
|
||||
|
||||
setAttachmentSummary(content);
|
||||
|
||||
getChild<LLUICtrl>("loading_text")->setValue(LLSD(std::string("")));
|
||||
|
||||
LLButton* btn = getChild<LLButton>("refresh_list_btn");
|
||||
if(btn)
|
||||
{
|
||||
btn->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLPanelScriptLimitsAttachment::postBuild()
|
||||
{
|
||||
childSetAction("refresh_list_btn", onClickRefresh, this);
|
||||
|
||||
std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
|
||||
getChild<LLUICtrl>("loading_text")->setValue(LLSD(msg_waiting));
|
||||
return requestAttachmentDetails();
|
||||
}
|
||||
|
||||
void LLPanelScriptLimitsAttachment::clearList()
|
||||
{
|
||||
LLCtrlListInterface *list = childGetListInterface("scripts_list");
|
||||
|
||||
if (list)
|
||||
{
|
||||
list->operateOnAll(LLCtrlListInterface::OP_DELETE);
|
||||
}
|
||||
|
||||
std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
|
||||
getChild<LLUICtrl>("loading_text")->setValue(LLSD(msg_waiting));
|
||||
}
|
||||
|
||||
void LLPanelScriptLimitsAttachment::setAttachmentSummary(LLSD content)
|
||||
{
|
||||
if(content["summary"]["used"][0]["type"].asString() == std::string("memory"))
|
||||
{
|
||||
mAttachmentMemoryUsed = content["summary"]["used"][0]["amount"].asInteger() / SIZE_OF_ONE_KB;
|
||||
mAttachmentMemoryMax = content["summary"]["available"][0]["amount"].asInteger() / SIZE_OF_ONE_KB;
|
||||
mGotAttachmentMemoryUsed = true;
|
||||
}
|
||||
else if(content["summary"]["used"][1]["type"].asString() == std::string("memory"))
|
||||
{
|
||||
mAttachmentMemoryUsed = content["summary"]["used"][1]["amount"].asInteger() / SIZE_OF_ONE_KB;
|
||||
mAttachmentMemoryMax = content["summary"]["available"][1]["amount"].asInteger() / SIZE_OF_ONE_KB;
|
||||
mGotAttachmentMemoryUsed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "attachment details don't contain memory summary info" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
if(content["summary"]["used"][0]["type"].asString() == std::string("urls"))
|
||||
{
|
||||
mAttachmentURLsUsed = content["summary"]["used"][0]["amount"].asInteger();
|
||||
mAttachmentURLsMax = content["summary"]["available"][0]["amount"].asInteger();
|
||||
mGotAttachmentURLsUsed = true;
|
||||
}
|
||||
else if(content["summary"]["used"][1]["type"].asString() == std::string("urls"))
|
||||
{
|
||||
mAttachmentURLsUsed = content["summary"]["used"][1]["amount"].asInteger();
|
||||
mAttachmentURLsMax = content["summary"]["available"][1]["amount"].asInteger();
|
||||
mGotAttachmentURLsUsed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "attachment details don't contain urls summary info" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
|
||||
if((mAttachmentMemoryUsed >= 0) && (mAttachmentMemoryMax >= 0))
|
||||
{
|
||||
LLStringUtil::format_map_t args_attachment_memory;
|
||||
args_attachment_memory["[COUNT]"] = llformat ("%d", mAttachmentMemoryUsed);
|
||||
std::string translate_message = "ScriptLimitsMemoryUsedSimple";
|
||||
|
||||
if (0 < mAttachmentMemoryMax)
|
||||
{
|
||||
S32 attachment_memory_available = mAttachmentMemoryMax - mAttachmentMemoryUsed;
|
||||
|
||||
args_attachment_memory["[MAX]"] = llformat ("%d", mAttachmentMemoryMax);
|
||||
args_attachment_memory["[AVAILABLE]"] = llformat ("%d", attachment_memory_available);
|
||||
translate_message = "ScriptLimitsMemoryUsed";
|
||||
}
|
||||
|
||||
getChild<LLUICtrl>("memory_used")->setValue(LLTrans::getString(translate_message, args_attachment_memory));
|
||||
}
|
||||
|
||||
if((mAttachmentURLsUsed >= 0) && (mAttachmentURLsMax >= 0))
|
||||
{
|
||||
S32 attachment_urls_available = mAttachmentURLsMax - mAttachmentURLsUsed;
|
||||
|
||||
LLStringUtil::format_map_t args_attachment_urls;
|
||||
args_attachment_urls["[COUNT]"] = llformat ("%d", mAttachmentURLsUsed);
|
||||
args_attachment_urls["[MAX]"] = llformat ("%d", mAttachmentURLsMax);
|
||||
args_attachment_urls["[AVAILABLE]"] = llformat ("%d", attachment_urls_available);
|
||||
std::string msg_attachment_urls = LLTrans::getString("ScriptLimitsURLsUsed", args_attachment_urls);
|
||||
getChild<LLUICtrl>("urls_used")->setValue(LLSD(msg_attachment_urls));
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLPanelScriptLimitsAttachment::onClickRefresh(void* userdata)
|
||||
{
|
||||
LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
|
||||
if(instance)
|
||||
{
|
||||
LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
|
||||
LLPanelScriptLimitsAttachment* panel_attachments = (LLPanelScriptLimitsAttachment*)tab->getChild<LLPanel>("script_limits_my_avatar_panel");
|
||||
LLButton* btn = panel_attachments->getChild<LLButton>("refresh_list_btn");
|
||||
|
||||
//To stop people from hammering the refesh button and accidentally dosing themselves - enough requests can crash the viewer!
|
||||
//turn the button off, then turn it on when we get a response
|
||||
if(btn)
|
||||
{
|
||||
btn->setEnabled(false);
|
||||
}
|
||||
panel_attachments->clearList();
|
||||
panel_attachments->requestAttachmentDetails();
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "could not find LLPanelScriptLimitsRegionMemory instance after refresh button clicked" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue