diff options
Diffstat (limited to 'indra/llcommon')
107 files changed, 1714 insertions, 1219 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 5f4ed2fffa..8e43627a5f 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -8,10 +8,8 @@ include(bugsplat) include(Linking) include(Boost) include(LLSharedLibs) -include(JsonCpp) include(Copy3rdPartyLibs) include(ZLIBNG) -include(URIPARSER) include(Tracy) @@ -194,6 +192,7 @@ set(llcommon_HEADER_FILES llmetrics.h llmetricperformancetester.h llmortician.h + llmutex.h llnametable.h llpointer.h llprofiler.h @@ -276,10 +275,8 @@ target_link_libraries( llcommon ll::apr ll::expat - ll::jsoncpp ll::zlib-ng ll::boost - ll::uriparser ll::oslibraries ll::tracy ) diff --git a/indra/llcommon/StackWalker.cpp b/indra/llcommon/StackWalker.cpp index 201eeed56b..e9ae1723fb 100644 --- a/indra/llcommon/StackWalker.cpp +++ b/indra/llcommon/StackWalker.cpp @@ -292,10 +292,10 @@ public: free(m_szSymPath); m_szSymPath = NULL; } - BOOL Init(LPCSTR szSymPath) + bool Init(LPCSTR szSymPath) { if (m_parent == NULL) - return FALSE; + return false; // Dynamically load the Entry-Points for dbghelp.dll: // First try to load the newsest one from TCHAR szTemp[4096]; @@ -364,7 +364,7 @@ public: if (m_hDbhHelp == NULL) // if not already loaded, try to load a default-one m_hDbhHelp = LoadLibrary( _T("dbghelp.dll") ); if (m_hDbhHelp == NULL) - return FALSE; + return false; pSI = (tSI) GetProcAddress(m_hDbhHelp, "SymInitialize" ); pSC = (tSC) GetProcAddress(m_hDbhHelp, "SymCleanup" ); @@ -388,7 +388,7 @@ public: FreeLibrary(m_hDbhHelp); m_hDbhHelp = NULL; pSC = NULL; - return FALSE; + return false; } // SymInitialize @@ -415,7 +415,7 @@ public: GetUserNameA(szUserName, &dwSize); this->m_parent->OnSymInit(buf, symOptions, szUserName); - return TRUE; + return true; } StackWalker *m_parent; @@ -555,7 +555,7 @@ private: typedef MODULEENTRY32 * LPMODULEENTRY32; #pragma pack( pop ) - BOOL GetModuleListTH32(HANDLE hProcess, DWORD pid) + bool GetModuleListTH32(HANDLE hProcess, DWORD pid) { // CreateToolhelp32Snapshot() typedef HANDLE (__stdcall *tCT32S)(DWORD dwFlags, DWORD th32ProcessID); @@ -592,13 +592,13 @@ private: } if (hToolhelp == NULL) - return FALSE; + return false; hSnap = pCT32S( TH32CS_SNAPMODULE, pid ); if (hSnap == (HANDLE) -1) { FreeLibrary(hToolhelp); - return FALSE; + return false; } keepGoing = !!pM32F( hSnap, &me ); @@ -612,8 +612,8 @@ private: CloseHandle(hSnap); FreeLibrary(hToolhelp); if (cnt <= 0) - return FALSE; - return TRUE; + return false; + return true; } // GetModuleListTH32 // **************************************** PSAPI ************************ @@ -623,7 +623,7 @@ private: LPVOID EntryPoint; } MODULEINFO, *LPMODULEINFO; - BOOL GetModuleListPSAPI(HANDLE hProcess) + bool GetModuleListPSAPI(HANDLE hProcess) { // EnumProcessModules() typedef BOOL (__stdcall *tEPM)(HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded ); @@ -652,7 +652,7 @@ private: hPsapi = LoadLibrary( _T("psapi.dll") ); if (hPsapi == NULL) - return FALSE; + return false; pEPM = (tEPM) GetProcAddress( hPsapi, "EnumProcessModules" ); pGMFNE = (tGMFNE) GetProcAddress( hPsapi, "GetModuleFileNameExA" ); @@ -662,7 +662,7 @@ private: { // we couldn't find all functions FreeLibrary(hPsapi); - return FALSE; + return false; } hMods = (HMODULE*) malloc(sizeof(HMODULE) * (TTBUFLEN / sizeof(HMODULE))); @@ -797,7 +797,7 @@ private: return result; } public: - BOOL LoadModules(HANDLE hProcess, DWORD dwProcessId) + bool LoadModules(HANDLE hProcess, DWORD dwProcessId) { // first try toolhelp32 if (GetModuleListTH32(hProcess, dwProcessId)) @@ -807,13 +807,13 @@ public: } - BOOL GetModuleInfo(HANDLE hProcess, DWORD64 baseAddr, IMAGEHLP_MODULE64_V3 *pModuleInfo) + bool GetModuleInfo(HANDLE hProcess, DWORD64 baseAddr, IMAGEHLP_MODULE64_V3 *pModuleInfo) { memset(pModuleInfo, 0, sizeof(IMAGEHLP_MODULE64_V3)); if(this->pSGMI == NULL) { SetLastError(ERROR_DLL_INIT_FAILED); - return FALSE; + return false; } // First try to use the larger ModuleInfo-Structure pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE64_V3); @@ -821,7 +821,7 @@ public: if (pData == NULL) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; + return false; } memcpy(pData, pModuleInfo, sizeof(IMAGEHLP_MODULE64_V3)); static bool s_useV3Version = true; @@ -833,7 +833,7 @@ public: memcpy(pModuleInfo, pData, sizeof(IMAGEHLP_MODULE64_V3)); pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE64_V3); free(pData); - return TRUE; + return true; } s_useV3Version = false; // to prevent unneccessarry calls with the larger struct... } @@ -847,11 +847,11 @@ public: memcpy(pModuleInfo, pData, sizeof(IMAGEHLP_MODULE64_V2)); pModuleInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULE64_V2); free(pData); - return TRUE; + return true; } free(pData); SetLastError(ERROR_DLL_INIT_FAILED); - return FALSE; + return false; } }; @@ -860,7 +860,7 @@ StackWalker::StackWalker(DWORD dwProcessId, HANDLE hProcess) { this->m_verbose = true; this->m_options = OptionsAll; - this->m_modulesLoaded = FALSE; + this->m_modulesLoaded = false; this->m_hProcess = hProcess; this->m_sw = new StackWalkerInternal(this, this->m_hProcess); this->m_dwProcessId = dwProcessId; @@ -871,7 +871,7 @@ StackWalker::StackWalker(bool verbose, int options, LPCSTR szSymPath, DWORD dwPr { this->m_verbose = verbose; this->m_options = options; - this->m_modulesLoaded = FALSE; + this->m_modulesLoaded = false; this->m_hProcess = hProcess; this->m_sw = new StackWalkerInternal(this, this->m_hProcess); this->m_dwProcessId = dwProcessId; @@ -895,15 +895,15 @@ StackWalker::~StackWalker() this->m_sw = NULL; } -BOOL StackWalker::LoadModules() +bool StackWalker::LoadModules() { if (this->m_sw == NULL) { SetLastError(ERROR_DLL_INIT_FAILED); - return FALSE; + return false; } if (m_modulesLoaded != FALSE) - return TRUE; + return true; // Build the sym-path: char *szSymPath = NULL; @@ -914,7 +914,7 @@ BOOL StackWalker::LoadModules() if (szSymPath == NULL) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return FALSE; + return false; } szSymPath[0] = 0; // Now first add the (optional) provided sympath: @@ -994,18 +994,18 @@ BOOL StackWalker::LoadModules() } // if SymBuildPath // First Init the whole stuff... - BOOL bRet = this->m_sw->Init(szSymPath); + bool bRet = this->m_sw->Init(szSymPath); if (szSymPath != NULL) free(szSymPath); szSymPath = NULL; - if (bRet == FALSE) + if (!bRet) { this->OnDbgHelpErr("Error while initializing dbghelp.dll", 0, 0); SetLastError(ERROR_DLL_INIT_FAILED); - return FALSE; + return false; } bRet = this->m_sw->LoadModules(this->m_hProcess, this->m_dwProcessId); - if (bRet != FALSE) - m_modulesLoaded = TRUE; + if (bRet) + m_modulesLoaded = true; return bRet; } @@ -1017,7 +1017,7 @@ BOOL StackWalker::LoadModules() static StackWalker::PReadProcessMemoryRoutine s_readMemoryFunction = NULL; static LPVOID s_readMemoryFunction_UserData = NULL; -BOOL StackWalker::ShowCallstack(bool verbose, HANDLE hThread, const CONTEXT *context, PReadProcessMemoryRoutine readMemoryFunction, LPVOID pUserData) +bool StackWalker::ShowCallstack(bool verbose, HANDLE hThread, const CONTEXT *context, PReadProcessMemoryRoutine readMemoryFunction, LPVOID pUserData) { m_verbose = verbose; CONTEXT c; @@ -1029,13 +1029,13 @@ BOOL StackWalker::ShowCallstack(bool verbose, HANDLE hThread, const CONTEXT *con bool bLastEntryCalled = true; int curRecursionCount = 0; - if (m_modulesLoaded == FALSE) + if (!m_modulesLoaded) this->LoadModules(); // ignore the result... if (this->m_sw->m_hDbhHelp == NULL) { SetLastError(ERROR_DLL_INIT_FAILED); - return FALSE; + return false; } s_readMemoryFunction = readMemoryFunction; @@ -1062,7 +1062,7 @@ BOOL StackWalker::ShowCallstack(bool verbose, HANDLE hThread, const CONTEXT *con if (GetThreadContext(hThread, &c) == FALSE) { ResumeThread(hThread); - return FALSE; + return false; } } } @@ -1256,13 +1256,13 @@ BOOL StackWalker::ShowCallstack(bool verbose, HANDLE hThread, const CONTEXT *con cleanup: if (pSym) free( pSym ); - if (bLastEntryCalled == false) + if (!bLastEntryCalled) this->OnCallstackEntry(lastEntry, csEntry); if (context == NULL) ResumeThread(hThread); - return TRUE; + return true; } BOOL __stdcall StackWalker::myReadProcMem( diff --git a/indra/llcommon/StackWalker.h b/indra/llcommon/StackWalker.h index 91cd55bbaf..c76b07a739 100644 --- a/indra/llcommon/StackWalker.h +++ b/indra/llcommon/StackWalker.h @@ -112,9 +112,9 @@ public: LPVOID pUserData // optional data, which was passed in "ShowCallstack" ); - BOOL LoadModules(); + bool LoadModules(); - BOOL ShowCallstack( + bool ShowCallstack( bool verbose, HANDLE hThread = GetCurrentThread(), const CONTEXT *context = NULL, @@ -159,7 +159,7 @@ protected: StackWalkerInternal *m_sw; HANDLE m_hProcess; DWORD m_dwProcessId; - BOOL m_modulesLoaded; + bool m_modulesLoaded; LPSTR m_szSymPath; bool m_verbose; diff --git a/indra/llcommon/is_approx_equal_fraction.h b/indra/llcommon/is_approx_equal_fraction.h index 79f4f5ebbd..371a1307c1 100644 --- a/indra/llcommon/is_approx_equal_fraction.h +++ b/indra/llcommon/is_approx_equal_fraction.h @@ -43,9 +43,9 @@ * signatures. */ template <typename FTYPE> -inline BOOL is_approx_equal_fraction_impl(FTYPE x, FTYPE y, U32 frac_bits) +inline bool is_approx_equal_fraction_impl(FTYPE x, FTYPE y, U32 frac_bits) { - BOOL ret = TRUE; + bool ret = true; FTYPE diff = (FTYPE) fabs(x - y); S32 diffInt = (S32) diff; @@ -58,20 +58,20 @@ inline BOOL is_approx_equal_fraction_impl(FTYPE x, FTYPE y, U32 frac_bits) // based on the number of bits used for packing decimal portion. if (diffInt != 0 || diffFracTolerance > 1) { - ret = FALSE; + ret = false; } return ret; } /// F32 flavor -inline BOOL is_approx_equal_fraction(F32 x, F32 y, U32 frac_bits) +inline bool is_approx_equal_fraction(F32 x, F32 y, U32 frac_bits) { return is_approx_equal_fraction_impl<F32>(x, y, frac_bits); } /// F64 flavor -inline BOOL is_approx_equal_fraction(F64 x, F64 y, U32 frac_bits) +inline bool is_approx_equal_fraction(F64 x, F64 y, U32 frac_bits) { return is_approx_equal_fraction_impl<F64>(x, y, frac_bits); } diff --git a/indra/llcommon/llalignedarray.h b/indra/llcommon/llalignedarray.h index 0ba8b34cb6..8248f82186 100644 --- a/indra/llcommon/llalignedarray.h +++ b/indra/llcommon/llalignedarray.h @@ -116,7 +116,7 @@ void LLAlignedArray<T, alignment>::resize(U32 size) template <class T, U32 alignment> T& LLAlignedArray<T, alignment>::operator[](int idx) { - if(idx >= mElementCount || idx < 0) + if (idx < 0 || unsigned(idx) >= mElementCount) { LL_ERRS() << "Out of bounds LLAlignedArray, requested: " << (S32)idx << " size: " << mElementCount << LL_ENDL; } @@ -126,7 +126,7 @@ T& LLAlignedArray<T, alignment>::operator[](int idx) template <class T, U32 alignment> const T& LLAlignedArray<T, alignment>::operator[](int idx) const { - if (idx >= mElementCount || idx < 0) + if (idx < 0 || unsigned(idx) >= mElementCount) { LL_ERRS() << "Out of bounds LLAlignedArray, requested: " << (S32)idx << " size: " << mElementCount << LL_ENDL; } diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 9729f68d23..6da764f94c 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -52,15 +52,7 @@ // // Signal handling -// -// Windows uses structured exceptions, so it's handled a bit differently. -// -#if LL_WINDOWS -#include "windows.h" - -LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop); -BOOL ConsoleCtrlHandler(DWORD fdwCtrlType); -#else +#ifndef LL_WINDOWS # include <signal.h> # include <unistd.h> // for fork() void setup_signals(); @@ -87,18 +79,18 @@ S32 LL_HEARTBEAT_SIGNAL = SIGUSR2; S32 LL_SMACKDOWN_SIGNAL = (SIGRTMAX >= 0) ? (SIGRTMAX-1) : SIGUSR1; S32 LL_HEARTBEAT_SIGNAL = (SIGRTMAX >= 0) ? (SIGRTMAX-0) : SIGUSR2; # endif // LL_DARWIN -#endif // LL_WINDOWS +#endif // !LL_WINDOWS // the static application instance LLApp* LLApp::sApplication = NULL; // Allows the generation of core files for post mortem under gdb // and disables crashlogger -BOOL LLApp::sDisableCrashlogger = FALSE; +bool LLApp::sDisableCrashlogger = false; // Local flag for whether or not to do logging in signal handlers. //static -BOOL LLApp::sLogInSignal = FALSE; +bool LLApp::sLogInSignal = true; // static // Keeps track of application status @@ -207,9 +199,9 @@ bool LLApp::parseCommandOptions(int argc, char** argv) #if LL_WINDOWS //Windows changed command line parsing. Deal with it. - S32 slen = value.length() - 1; - S32 start = 0; - S32 end = slen; + size_t slen = value.length() - 1; + size_t start = 0; + size_t end = slen; if (argv[ii][start]=='"')start++; if (argv[ii][end]=='"')end--; if (start!=0 || end!=slen) @@ -272,9 +264,9 @@ bool LLApp::parseCommandOptions(int argc, wchar_t** wargv) #if LL_WINDOWS //Windows changed command line parsing. Deal with it. - S32 slen = value.length() - 1; - S32 start = 0; - S32 end = slen; + size_t slen = value.length() - 1; + size_t start = 0; + size_t end = slen; if (wargv[ii][start]=='"')start++; if (wargv[ii][end]=='"')end--; if (start!=0 || end!=slen) @@ -326,33 +318,6 @@ void LLApp::stepFrame() mRunner.run(); } -#if LL_WINDOWS -//The following code is needed for 32-bit apps on 64-bit windows to keep it from eating -//crashes. It is a lovely undocumented 'feature' in SP1 of Windows 7. An excellent -//in-depth article on the issue may be found here: http://randomascii.wordpress.com/2012/07/05/when-even-crashing-doesn-work/ -void EnableCrashingOnCrashes() -{ - typedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags); - typedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags); - const DWORD EXCEPTION_SWALLOWING = 0x1; - - HMODULE kernel32 = LoadLibraryA("kernel32.dll"); - tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32, - "GetProcessUserModeExceptionPolicy"); - tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32, - "SetProcessUserModeExceptionPolicy"); - if (pGetPolicy && pSetPolicy) - { - DWORD dwFlags; - if (pGetPolicy(&dwFlags)) - { - // Turn off the filter - pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING); - } - } -} -#endif - void LLApp::setupErrorHandling(bool second_instance) { // Error handling is done by starting up an error handling thread, which just sleeps and @@ -408,6 +373,9 @@ static std::map<LLApp::EAppStatus, const char*> statusDesc // static void LLApp::setStatus(EAppStatus status) { + auto status_it = statusDesc.find(status); + std::string status_text = status_it != statusDesc.end() ? std::string(status_it->second) : std::to_string(status); + LL_INFOS() << "status: " << status_text << LL_ENDL; // notify everyone waiting on sStatus any time its value changes sStatus.set_all(status); @@ -416,18 +384,7 @@ void LLApp::setStatus(EAppStatus status) if (! LLEventPumps::wasDeleted()) { // notify interested parties of status change - LLSD statsd; - auto found = statusDesc.find(status); - if (found != statusDesc.end()) - { - statsd = found->second; - } - else - { - // unknown status? at least report value - statsd = LLSD::Integer(status); - } - LLEventPumps::instance().obtain("LLApp").post(llsd::map("status", statsd)); + LLEventPumps::instance().obtain("LLApp").post(llsd::map("status", status_text)); } } @@ -503,13 +460,13 @@ bool LLApp::isExiting() void LLApp::disableCrashlogger() { - sDisableCrashlogger = TRUE; + sDisableCrashlogger = true; } // static bool LLApp::isCrashloggerDisabled() { - return (sDisableCrashlogger == TRUE); + return sDisableCrashlogger; } // static @@ -522,77 +479,34 @@ int LLApp::getPid() #endif } -#if LL_WINDOWS -LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop) +// static +void LLApp::notifyOutOfDiskSpace() { - // Translate the signals/exceptions into cross-platform stuff - // Windows implementation + static const U32Seconds min_interval = U32Seconds(60); + static U32Seconds min_time_to_send = U32Seconds(0); + U32Seconds now = LLTimer::getTotalTime(); + if (now < min_time_to_send) + return; - // Make sure the user sees something to indicate that the app crashed. - LONG retval; + min_time_to_send = now + min_interval; - if (LLApp::isError()) + if (LLApp* app = instance()) { - LL_WARNS() << "Got another fatal signal while in the error handler, die now!" << LL_ENDL; - retval = EXCEPTION_EXECUTE_HANDLER; - return retval; + app->sendOutOfDiskSpaceNotification(); } - - // Flag status to error, so thread_error starts its work - LLApp::setError(); - - // Block in the exception handler until the app has stopped - // This is pretty sketchy, but appears to work just fine - while (!LLApp::isStopped()) + else { - ms_sleep(10); + LL_WARNS() << "No app instance" << LL_ENDL; } - - // - // Generate a minidump if we can. - // - // TODO: This needs to be ported over form the viewer-specific - // LLWinDebug class - - // - // At this point, we always want to exit the app. There's no graceful - // recovery for an unhandled exception. - // - // Just kill the process. - retval = EXCEPTION_EXECUTE_HANDLER; - return retval; } -// Win32 doesn't support signals. This is used instead. -BOOL ConsoleCtrlHandler(DWORD fdwCtrlType) +// virtual +void LLApp::sendOutOfDiskSpaceNotification() { - switch (fdwCtrlType) - { - case CTRL_BREAK_EVENT: - case CTRL_LOGOFF_EVENT: - case CTRL_SHUTDOWN_EVENT: - case CTRL_CLOSE_EVENT: // From end task or the window close button. - case CTRL_C_EVENT: // from CTRL-C on the keyboard - // Just set our state to quitting, not error - if (LLApp::isQuitting() || LLApp::isError()) - { - // We're already trying to die, just ignore this signal - if (LLApp::sLogInSignal) - { - LL_INFOS() << "Signal handler - Already trying to quit, ignoring signal!" << LL_ENDL; - } - return TRUE; - } - LLApp::setQuitting(); - return TRUE; - - default: - return FALSE; - } + LL_WARNS() << "Should never be called" << LL_ENDL; // Should be overridden } -#else //!LL_WINDOWS - +#ifndef LL_WINDOWS void setup_signals() { // @@ -691,9 +605,10 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) switch (signum) { case SIGCHLD: + case SIGHUP: if (LLApp::sLogInSignal) { - LL_INFOS() << "Signal handler - Got SIGCHLD from " << info->si_pid << LL_ENDL; + LL_INFOS() << "Signal handler - Got SIGCHLD or SIGHUP from " << info->si_pid << LL_ENDL; } return; @@ -708,11 +623,10 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) raise(signum); return; case SIGINT: - case SIGHUP: case SIGTERM: if (LLApp::sLogInSignal) { - LL_WARNS() << "Signal handler - Got SIGINT, HUP, or TERM, exiting gracefully" << LL_ENDL; + LL_WARNS() << "Signal handler - Got SIGINT, or TERM, exiting gracefully" << LL_ENDL; } // Graceful exit // Just set our state to quitting, not error @@ -759,6 +673,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) { LL_WARNS() << "Signal handler - Handling fatal signal!" << LL_ENDL; } + if (LLApp::isError()) { // Received second fatal signal while handling first, just die right now @@ -796,18 +711,15 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) clear_signals(); raise(signum); return; - } else { - if (LLApp::sLogInSignal) - { - LL_INFOS() << "Signal handler - Unhandled signal " << signum << ", ignoring!" << LL_ENDL; - } + } + + if (LLApp::sLogInSignal) + { + LL_INFOS() << "Signal handler - Unhandled signal " << signum << ", ignoring!" << LL_ENDL; } } } -#if LL_LINUX -#endif - bool unix_post_minidump_callback(const char *dump_dir, const char *minidump_id, void *context, bool succeeded) diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index 93bf4dd929..d90ecdf661 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -202,6 +202,8 @@ public: static bool isExiting(); // Either quitting or error (app is exiting, cleanly or not) static int getPid(); + static void notifyOutOfDiskSpace(); + // // Sleep for specified time while still running // @@ -291,7 +293,7 @@ protected: static void setStatus(EAppStatus status); // Use this to change the application status. static LLScalarCond<EAppStatus> sStatus; // Reflects current application status - static BOOL sDisableCrashlogger; // Let the OS handle crashes for us. + static bool sDisableCrashlogger; // Let the OS handle crashes for us. std::wstring mCrashReportPipeStr; //Name of pipe to use for crash reporting. std::string mDumpPath; //output path for google breakpad. Dependency workaround. @@ -301,6 +303,8 @@ protected: */ void stepFrame(); + virtual void sendOutOfDiskSpaceNotification(); + private: // Contains the filename of the minidump file after a crash. char mMinidumpPath[MAX_MINDUMP_PATH_LENGTH]; @@ -336,7 +340,7 @@ private: #endif public: - static BOOL sLogInSignal; + static bool sLogInSignal; }; #endif // LL_LLAPP_H diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index c907a8c073..01763c49aa 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -28,6 +28,7 @@ #include "linden_common.h" #include "llapr.h" +#include "llapp.h" #include "llmutex.h" #include "apr_dso.h" @@ -56,7 +57,7 @@ void ll_init_apr() if(!LLAPRFile::sAPRFilePoolp) { - LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ; + LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(false) ; } gAPRInitialized = true; @@ -91,7 +92,7 @@ void ll_cleanup_apr() // //LLAPRPool // -LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) +LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, bool releasePoolFlag) : mParent(parent), mReleasePoolFlag(releasePoolFlag), mMaxSize(size), @@ -145,7 +146,7 @@ apr_pool_t* LLAPRPool::getAPRPool() return mPool ; } -LLVolatileAPRPool::LLVolatileAPRPool(BOOL is_local, apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) +LLVolatileAPRPool::LLVolatileAPRPool(bool is_local, apr_pool_t *parent, apr_size_t size, bool releasePoolFlag) : LLAPRPool(parent, size, releasePoolFlag), mNumActiveRef(0), mNumTotalRef(0) @@ -219,7 +220,7 @@ void LLVolatileAPRPool::clearVolatileAPRPool() llassert(mNumTotalRef <= (FULL_VOLATILE_APR_POOL << 2)) ; } -BOOL LLVolatileAPRPool::isFull() +bool LLVolatileAPRPool::isFull() { return mNumTotalRef > FULL_VOLATILE_APR_POOL ; } @@ -385,7 +386,7 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLV } //use gAPRPoolp. -apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool) +apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, bool use_global_pool) { apr_status_t s; @@ -571,7 +572,7 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb } //static -S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool) +S32 LLAPRFile::writeEx(const std::string& filename, const void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool) { LL_PROFILE_ZONE_SCOPED; apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY; @@ -606,7 +607,11 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n apr_status_t s = apr_file_write(file_handle, buf, &bytes_written); if (s != APR_SUCCESS) { - LL_WARNS("APR") << " Attempting to write filename: " << filename << LL_ENDL; + LL_WARNS("APR") << "Attempting to write filename: " << filename << LL_ENDL; + if (APR_STATUS_IS_ENOSPC(s)) + { + LLApp::notifyOutOfDiskSpace(); + } ll_apr_warn_status(s); bytes_written = 0; } diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index 2f88fdcd59..00ff4d60b7 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -78,7 +78,7 @@ bool LL_COMMON_API ll_apr_is_initialized(); class LL_COMMON_API LLAPRPool { public: - LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE) ; + LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, bool releasePoolFlag = true) ; virtual ~LLAPRPool() ; virtual apr_pool_t* getAPRPool() ; @@ -93,7 +93,7 @@ protected: apr_pool_t* mParent ; //parent pool apr_size_t mMaxSize ; //max size of mPool, mPool should return memory to system if allocated memory beyond this limit. However it seems not to work. apr_status_t mStatus ; //status when creating the pool - BOOL mReleasePoolFlag ; //if set, mPool is destroyed when LLAPRPool is deleted. default value is true. + bool mReleasePoolFlag ; //if set, mPool is destroyed when LLAPRPool is deleted. default value is true. }; // @@ -104,14 +104,14 @@ protected: class LL_COMMON_API LLVolatileAPRPool : public LLAPRPool { public: - LLVolatileAPRPool(BOOL is_local = TRUE, apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE); + LLVolatileAPRPool(bool is_local = true, apr_pool_t *parent = NULL, apr_size_t size = 0, bool releasePoolFlag = true); virtual ~LLVolatileAPRPool(); /*virtual*/ apr_pool_t* getAPRPool() ; //define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool(). apr_pool_t* getVolatileAPRPool() ; void clearVolatileAPRPool() ; - BOOL isFull() ; + bool isFull() ; private: S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool. @@ -158,7 +158,7 @@ public: ~LLAPRFile() ; apr_status_t open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL, S32* sizep = NULL); - apr_status_t open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool); //use gAPRPoolp. + apr_status_t open(const std::string& filename, apr_int32_t flags, bool use_global_pool); //use gAPRPoolp. apr_status_t close() ; // Returns actual offset, -1 if seek fails @@ -193,7 +193,7 @@ public: // Returns bytes read/written, 0 if read/write fails: static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); - static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); // offset<0 means append + static S32 writeEx(const std::string& filename, const void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); // offset<0 means append //******************************************************************************************************************************* }; diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 3e46bde954..c09cf7abd2 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -97,8 +97,10 @@ LLAssetDictionary::LLAssetDictionary() addEntry(LLAssetType::AT_PERSON, new AssetEntry("PERSON", "person", "person", false, false, false)); addEntry(LLAssetType::AT_SETTINGS, new AssetEntry("SETTINGS", "settings", "settings blob", true, true, true)); addEntry(LLAssetType::AT_MATERIAL, new AssetEntry("MATERIAL", "material", "render material", true, true, true)); + addEntry(LLAssetType::AT_GLTF, new AssetEntry("GLTF", "gltf", "GLTF", true, true, true)); + addEntry(LLAssetType::AT_GLTF_BIN, new AssetEntry("GLTF_BIN", "glbin", "GLTF binary", true, true, true)); addEntry(LLAssetType::AT_UNKNOWN, new AssetEntry("UNKNOWN", "invalid", NULL, false, false, false)); - addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, FALSE, FALSE, FALSE)); + addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, false, false, false)); }; diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index 1989155550..547c3f4329 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -128,8 +128,10 @@ public: AT_SETTINGS = 56, // Collection of settings AT_MATERIAL = 57, // Render Material + AT_GLTF = 58, // gltf json document + AT_GLTF_BIN = 59, // gltf binary data - AT_COUNT = 58, + AT_COUNT = 60, // +*********************************************************+ // | TO ADD AN ELEMENT TO THIS ENUM: | diff --git a/indra/llcommon/llbase64.cpp b/indra/llcommon/llbase64.cpp index dbbbec9813..b8185a0c84 100644 --- a/indra/llcommon/llbase64.cpp +++ b/indra/llcommon/llbase64.cpp @@ -59,3 +59,19 @@ std::string LLBase64::encode(const U8* input, size_t input_size) return output; } +std::string LLBase64::decodeAsString(const std::string &input) +{ + int b64_buffer_length = apr_base64_decode_len(input.c_str()); + char* b64_buffer = new char[b64_buffer_length]; + + // This is faster than apr_base64_encode() if you know + // you're not on an EBCDIC machine. Also, the output is + // null terminated, even though the documentation doesn't + // specify. See apr_base64.c for details. JC + b64_buffer_length = apr_base64_decode(b64_buffer, input.c_str()); + std::string res; + res.assign(b64_buffer); + delete[] b64_buffer; + return res; +} + diff --git a/indra/llcommon/llbase64.h b/indra/llcommon/llbase64.h index d4e9d97ea4..4f21e65244 100644 --- a/indra/llcommon/llbase64.h +++ b/indra/llcommon/llbase64.h @@ -32,6 +32,7 @@ class LL_COMMON_API LLBase64 { public: static std::string encode(const U8* input, size_t input_size); + static std::string decodeAsString(const std::string& input); }; #endif diff --git a/indra/llcommon/llcallbacklist.cpp b/indra/llcommon/llcallbacklist.cpp index b5a58e90b3..3d5d30bd90 100644 --- a/indra/llcommon/llcallbacklist.cpp +++ b/indra/llcommon/llcallbacklist.cpp @@ -70,11 +70,11 @@ bool LLCallbackList::containsFunction( callback_t func, void *data) callback_list_t::iterator iter = find(func,data); if (iter != mCallbackList.end()) { - return TRUE; + return true; } else { - return FALSE; + return false; } } @@ -85,11 +85,11 @@ bool LLCallbackList::deleteFunction( callback_t func, void *data) if (iter != mCallbackList.end()) { mCallbackList.erase(iter); - return TRUE; + return true; } else { - return FALSE; + return false; } } @@ -191,10 +191,10 @@ public: } private: - BOOL tick() + bool tick() { mCallable(); - return TRUE; + return true; } nullary_func_t mCallable; @@ -215,7 +215,7 @@ public: { } private: - BOOL tick() + bool tick() { return mCallable(); } diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index 14bdeb5c60..f1f3958fe0 100644 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -115,7 +115,7 @@ void tracy_aligned_free(void *memblock) #endif //static -BOOL LLCommon::sAprInitialized = FALSE; +bool LLCommon::sAprInitialized = false; static LLTrace::ThreadRecorder* sMasterThreadRecorder = NULL; @@ -125,10 +125,9 @@ void LLCommon::initClass() if (!sAprInitialized) { ll_init_apr(); - sAprInitialized = TRUE; + sAprInitialized = true; } LLTimer::initClass(); - LLThreadSafeRefCount::initThreadSafeRefCount(); assert_main_thread(); // Make sure we record the main thread if (!sMasterThreadRecorder) { @@ -143,11 +142,10 @@ void LLCommon::cleanupClass() delete sMasterThreadRecorder; sMasterThreadRecorder = NULL; LLTrace::set_master_thread_recorder(NULL); - LLThreadSafeRefCount::cleanupThreadSafeRefCount(); SUBSYSTEM_CLEANUP_DBG(LLTimer); if (sAprInitialized) { ll_cleanup_apr(); - sAprInitialized = FALSE; + sAprInitialized = false; } } diff --git a/indra/llcommon/llcommon.h b/indra/llcommon/llcommon.h index 129e71f703..41a101eb62 100644 --- a/indra/llcommon/llcommon.h +++ b/indra/llcommon/llcommon.h @@ -36,7 +36,7 @@ public: static void initClass(); static void cleanupClass(); private: - static BOOL sAprInitialized; + static bool sAprInitialized; }; #endif diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 8612f9353f..1539b48bd3 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -3,25 +3,25 @@ * @author Nat Goodspeed * @date 2009-06-03 * @brief Implementation for llcoros. - * + * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, 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$ */ @@ -62,6 +62,23 @@ #endif // static +bool LLCoros::on_main_coro() +{ + if (!LLCoros::instanceExists() || LLCoros::getName().empty()) + { + return true; + } + + return false; +} + +// static +bool LLCoros::on_main_thread_main_coro() +{ + return on_main_coro() && on_main_thread(); +} + +// static LLCoros::CoroData& LLCoros::get_CoroData(const std::string& caller) { CoroData* current{ nullptr }; diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index 71c1c1c443..c3820ae987 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -31,8 +31,9 @@ #include "llexception.h" #include <boost/fiber/fss.hpp> -#include <boost/fiber/future/promise.hpp> #include <boost/fiber/future/future.hpp> +#include <boost/fiber/future/promise.hpp> +#include <boost/fiber/recursive_mutex.hpp> #include "mutex.h" #include "llsingleton.h" #include "llinstancetracker.h" @@ -94,6 +95,16 @@ class LL_COMMON_API LLCoros: public LLSingleton<LLCoros> void cleanupSingleton() override; public: + // For debugging, return true if on the main coroutine for the current thread + // Code that should not be executed from a coroutine should be protected by + // llassert(LLCoros::on_main_coro()) + static bool on_main_coro(); + + // For debugging, return true if on the main thread and not in a coroutine + // Non-thread-safe code in the main loop should be protected by + // llassert(LLCoros::on_main_thread_main_coro()) + static bool on_main_thread_main_coro(); + /// The viewer's use of the term "coroutine" became deeply embedded before /// the industry term "fiber" emerged to distinguish userland threads from /// simpler, more transient kinds of coroutines. Semantically they've @@ -297,6 +308,12 @@ public: // use mutex, lock, condition_variable suitable for coroutines using Mutex = boost::fibers::mutex; + using RMutex = boost::fibers::recursive_mutex; + // With C++17, LockType is deprecated: at this point we can directly + // declare 'std::unique_lock lk(some_mutex)' without explicitly stating + // the mutex type. Sadly, making LockType an alias template for + // std::unique_lock doesn't work the same way: Class Template Argument + // Deduction only works for class templates, not alias templates. using LockType = std::unique_lock<Mutex>; using cv_status = boost::fibers::cv_status; using ConditionVariable = boost::fibers::condition_variable; diff --git a/indra/llcommon/llcrc.cpp b/indra/llcommon/llcrc.cpp index 34aa7b46e8..d79d06e2a2 100644 --- a/indra/llcommon/llcrc.cpp +++ b/indra/llcommon/llcrc.cpp @@ -200,7 +200,7 @@ void LLCRC::update(const std::string& filename) #ifdef _DEBUG -BOOL LLCRC::testHarness() +bool LLCRC::testHarness() { const S32 TEST_BUFFER_SIZE = 16; const char TEST_BUFFER[TEST_BUFFER_SIZE] = "hello &#$)$&Nd0"; /* Flawfinder: ignore */ diff --git a/indra/llcommon/llcrc.h b/indra/llcommon/llcrc.h index 3b48b778ff..a3bde47780 100644 --- a/indra/llcommon/llcrc.h +++ b/indra/llcommon/llcrc.h @@ -59,8 +59,8 @@ public: #ifdef _DEBUG // This function runs tests to make sure the crc is - // working. Returns TRUE if it is. - static BOOL testHarness(); + // working. Returns true if it is. + static bool testHarness(); #endif }; diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index c63c7012d1..b38864688d 100644 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -41,20 +41,11 @@ #include "llstring.h" #include "llfasttimer.h" -static const F64 DATE_EPOCH = 0.0; - static const F64 LL_APR_USEC_PER_SEC = 1000000.0; // should be APR_USEC_PER_SEC, but that relies on INT64_C which // isn't defined in glib under our build set up for some reason -LLDate::LLDate() : mSecondsSinceEpoch(DATE_EPOCH) -{} - -LLDate::LLDate(const LLDate& date) : - mSecondsSinceEpoch(date.mSecondsSinceEpoch) -{} - LLDate::LLDate(F64SecondsImplicit seconds_since_epoch) : mSecondsSinceEpoch(seconds_since_epoch.value()) {} diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index 81f2dd0d1c..1a69a04232 100644 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -43,16 +43,13 @@ */ class LL_COMMON_API LLDate { + static constexpr F64 DATE_EPOCH = 0.0; public: /** * @brief Construct a date equal to epoch. */ - LLDate(); - - /** - * @brief Construct a date equal to the source date. - */ - LLDate(const LLDate& date); + constexpr LLDate() : mSecondsSinceEpoch(DATE_EPOCH) + {} /** * @brief Construct a date from a seconds since epoch value. diff --git a/indra/llcommon/lldefs.h b/indra/llcommon/lldefs.h index 0ba756d472..2fbb26dc1a 100644 --- a/indra/llcommon/lldefs.h +++ b/indra/llcommon/lldefs.h @@ -31,64 +31,64 @@ #include <type_traits> // Often used array indices -const U32 VX = 0; -const U32 VY = 1; -const U32 VZ = 2; -const U32 VW = 3; -const U32 VS = 3; - -const U32 VRED = 0; -const U32 VGREEN = 1; -const U32 VBLUE = 2; -const U32 VALPHA = 3; - -const U32 INVALID_DIRECTION = 0xFFFFFFFF; -const U32 EAST = 0; -const U32 NORTH = 1; -const U32 WEST = 2; -const U32 SOUTH = 3; - -const U32 NORTHEAST = 4; -const U32 NORTHWEST = 5; -const U32 SOUTHWEST = 6; -const U32 SOUTHEAST = 7; -const U32 MIDDLE = 8; - -const U8 EAST_MASK = 0x1<<EAST; -const U8 NORTH_MASK = 0x1<<NORTH; -const U8 WEST_MASK = 0x1<<WEST; -const U8 SOUTH_MASK = 0x1<<SOUTH; - -const U8 NORTHEAST_MASK = NORTH_MASK | EAST_MASK; -const U8 NORTHWEST_MASK = NORTH_MASK | WEST_MASK; -const U8 SOUTHWEST_MASK = SOUTH_MASK | WEST_MASK; -const U8 SOUTHEAST_MASK = SOUTH_MASK | EAST_MASK; - -const U32 gDirOpposite[8] = {2, 3, 0, 1, 6, 7, 4, 5}; -const U32 gDirAdjacent[8][2] = { - {4, 7}, - {4, 5}, - {5, 6}, - {6, 7}, - {0, 1}, - {1, 2}, - {2, 3}, - {0, 3} - }; +constexpr U32 VX = 0; +constexpr U32 VY = 1; +constexpr U32 VZ = 2; +constexpr U32 VW = 3; +constexpr U32 VS = 3; + +constexpr U32 VRED = 0; +constexpr U32 VGREEN = 1; +constexpr U32 VBLUE = 2; +constexpr U32 VALPHA = 3; + +constexpr U32 INVALID_DIRECTION = 0xFFFFFFFF; +constexpr U32 EAST = 0; +constexpr U32 NORTH = 1; +constexpr U32 WEST = 2; +constexpr U32 SOUTH = 3; + +constexpr U32 NORTHEAST = 4; +constexpr U32 NORTHWEST = 5; +constexpr U32 SOUTHWEST = 6; +constexpr U32 SOUTHEAST = 7; +constexpr U32 MIDDLE = 8; + +constexpr U8 EAST_MASK = 0x1<<EAST; +constexpr U8 NORTH_MASK = 0x1<<NORTH; +constexpr U8 WEST_MASK = 0x1<<WEST; +constexpr U8 SOUTH_MASK = 0x1<<SOUTH; + +constexpr U8 NORTHEAST_MASK = NORTH_MASK | EAST_MASK; +constexpr U8 NORTHWEST_MASK = NORTH_MASK | WEST_MASK; +constexpr U8 SOUTHWEST_MASK = SOUTH_MASK | WEST_MASK; +constexpr U8 SOUTHEAST_MASK = SOUTH_MASK | EAST_MASK; + +constexpr U32 gDirOpposite[8] = {2, 3, 0, 1, 6, 7, 4, 5}; +constexpr U32 gDirAdjacent[8][2] = { + {4, 7}, + {4, 5}, + {5, 6}, + {6, 7}, + {0, 1}, + {1, 2}, + {2, 3}, + {0, 3} + }; // Magnitude along the x and y axis -const S32 gDirAxes[8][2] = { - { 1, 0}, // east - { 0, 1}, // north - {-1, 0}, // west - { 0,-1}, // south - { 1, 1}, // ne - {-1, 1}, // nw - {-1,-1}, // sw - { 1,-1}, // se - }; - -const S32 gDirMasks[8] = { +constexpr S32 gDirAxes[8][2] = { + { 1, 0}, // east + { 0, 1}, // north + {-1, 0}, // west + { 0,-1}, // south + { 1, 1}, // ne + {-1, 1}, // nw + {-1,-1}, // sw + { 1,-1}, // se + }; + +constexpr S32 gDirMasks[8] = { EAST_MASK, NORTH_MASK, WEST_MASK, @@ -117,22 +117,22 @@ const S32 gDirMasks[8] = { // | / -6- | / // |/ / |/ // +------------------+ -const U32 NO_SIDE = 0; -const U32 FRONT_SIDE = 1; -const U32 BACK_SIDE = 2; -const U32 LEFT_SIDE = 3; -const U32 RIGHT_SIDE = 4; -const U32 TOP_SIDE = 5; -const U32 BOTTOM_SIDE = 6; - -const U8 LL_SOUND_FLAG_NONE = 0x0; -const U8 LL_SOUND_FLAG_LOOP = 1<<0; -const U8 LL_SOUND_FLAG_SYNC_MASTER = 1<<1; -const U8 LL_SOUND_FLAG_SYNC_SLAVE = 1<<2; -const U8 LL_SOUND_FLAG_SYNC_PENDING = 1<<3; -const U8 LL_SOUND_FLAG_QUEUE = 1<<4; -const U8 LL_SOUND_FLAG_STOP = 1<<5; -const U8 LL_SOUND_FLAG_SYNC_MASK = LL_SOUND_FLAG_SYNC_MASTER | LL_SOUND_FLAG_SYNC_SLAVE | LL_SOUND_FLAG_SYNC_PENDING; +constexpr U32 NO_SIDE = 0; +constexpr U32 FRONT_SIDE = 1; +constexpr U32 BACK_SIDE = 2; +constexpr U32 LEFT_SIDE = 3; +constexpr U32 RIGHT_SIDE = 4; +constexpr U32 TOP_SIDE = 5; +constexpr U32 BOTTOM_SIDE = 6; + +constexpr U8 LL_SOUND_FLAG_NONE = 0x0; +constexpr U8 LL_SOUND_FLAG_LOOP = 1<<0; +constexpr U8 LL_SOUND_FLAG_SYNC_MASTER = 1<<1; +constexpr U8 LL_SOUND_FLAG_SYNC_SLAVE = 1<<2; +constexpr U8 LL_SOUND_FLAG_SYNC_PENDING = 1<<3; +constexpr U8 LL_SOUND_FLAG_QUEUE = 1<<4; +constexpr U8 LL_SOUND_FLAG_STOP = 1<<5; +constexpr U8 LL_SOUND_FLAG_SYNC_MASK = LL_SOUND_FLAG_SYNC_MASTER | LL_SOUND_FLAG_SYNC_SLAVE | LL_SOUND_FLAG_SYNC_PENDING; // // *NOTE: These values may be used as hard-coded numbers in scanf() variants. @@ -141,17 +141,17 @@ const U8 LL_SOUND_FLAG_SYNC_MASK = LL_SOUND_FLAG_SYNC_MASTER | LL_SOUND_FLAG_SYN // DO NOT CHANGE. // -------------- // -const U32 LL_MAX_PATH = 1024; // buffer size of maximum path + filename string length +constexpr U32 LL_MAX_PATH = 1024; // buffer size of maximum path + filename string length // For strings we send in messages -const U32 STD_STRING_BUF_SIZE = 255; // Buffer size -const U32 STD_STRING_STR_LEN = 254; // Length of the string (not including \0) +constexpr U32 STD_STRING_BUF_SIZE = 255; // Buffer size +constexpr U32 STD_STRING_STR_LEN = 254; // Length of the string (not including \0) // *NOTE: This value is used as hard-coded numbers in scanf() variants. // DO NOT CHANGE. -const U32 MAX_STRING = STD_STRING_BUF_SIZE; // Buffer size +constexpr U32 MAX_STRING = STD_STRING_BUF_SIZE; // Buffer size -const U32 MAXADDRSTR = 17; // 123.567.901.345 = 15 chars + \0 + 1 for good luck +constexpr U32 MAXADDRSTR = 17; // 123.567.901.345 = 15 chars + \0 + 1 for good luck // C++ is our friend. . . use template functions to make life easier! diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index e4843a88eb..6c3b9c9542 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -167,7 +167,7 @@ namespace { virtual void recordMessage(LLError::ELevel level, const std::string& message) override { - LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING + LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING; if (LLError::getAlwaysFlush()) { mFile << message << std::endl; @@ -234,7 +234,7 @@ namespace { virtual void recordMessage(LLError::ELevel level, const std::string& message) override { - LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING + LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING; // The default colors for error, warn and debug are now a bit more pastel // and easier to read on the default (black) terminal background but you // now have the option to set the color of each via an environment variables: @@ -274,7 +274,7 @@ namespace { LL_FORCE_INLINE void writeANSI(const std::string& ansi_code, const std::string& message) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING + LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING; static std::string s_ansi_bold = createBoldANSI(); // bold text static std::string s_ansi_reset = createResetANSI(); // reset // ANSI color code escape sequence, message, and reset in one fprintf call @@ -311,7 +311,7 @@ namespace { virtual void recordMessage(LLError::ELevel level, const std::string& message) override { - LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING + LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING; mBuffer->addLine(message); } @@ -338,7 +338,7 @@ namespace { virtual void recordMessage(LLError::ELevel level, const std::string& message) override { - LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING + LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING; debugger_print(message); } }; @@ -506,7 +506,7 @@ namespace LLError::TimeFunction mTimeFunction; Recorders mRecorders; - LLMutex mRecorderMutex; + LLCoros::RMutex mRecorderMutex; int mShouldLogCallCounter; @@ -700,7 +700,7 @@ namespace bool shouldLogToStderr() { #if LL_DARWIN - // On Mac OS X, stderr from apps launched from the Finder goes to the + // On macOS, stderr from apps launched from the Finder goes to the // console log. It's generally considered bad form to spam too much // there. That scenario can be detected by noticing that stderr is a // character device (S_IFCHR). @@ -1044,7 +1044,7 @@ namespace LLError return; } SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); - LLMutexLock lock(&s->mRecorderMutex); + std::unique_lock lock(s->mRecorderMutex); s->mRecorders.push_back(recorder); } @@ -1055,7 +1055,7 @@ namespace LLError return; } SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); - LLMutexLock lock(&s->mRecorderMutex); + std::unique_lock lock(s->mRecorderMutex); s->mRecorders.erase(std::remove(s->mRecorders.begin(), s->mRecorders.end(), recorder), s->mRecorders.end()); } @@ -1104,7 +1104,7 @@ namespace LLError std::shared_ptr<RECORDER> findRecorder() { SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); - LLMutexLock lock(&s->mRecorderMutex); + std::unique_lock lock(s->mRecorderMutex); return findRecorderPos<RECORDER>(s).first; } @@ -1115,7 +1115,7 @@ namespace LLError bool removeRecorder() { SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); - LLMutexLock lock(&s->mRecorderMutex); + std::unique_lock lock(s->mRecorderMutex); auto found = findRecorderPos<RECORDER>(s); if (found.first) { @@ -1215,13 +1215,13 @@ namespace void writeToRecorders(const LLError::CallSite& site, const std::string& message) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING + LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING; LLError::ELevel level = site.mLevel; SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig(); std::string escaped_message; - LLMutexLock lock(&s->mRecorderMutex); + std::unique_lock lock(s->mRecorderMutex); for (LLError::RecorderPtr& r : s->mRecorders) { if (!r->enabled()) @@ -1346,7 +1346,7 @@ namespace LLError bool Log::shouldLog(CallSite& site) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING + LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING; LLMutexTrylock lock(getMutex<LOG_MUTEX>(), 5); if (!lock.isLocked()) { @@ -1391,7 +1391,7 @@ namespace LLError void Log::flush(const std::ostringstream& out, const CallSite& site) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING + LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING; LLMutexTrylock lock(getMutex<LOG_MUTEX>(),5); if (!lock.isLocked()) { diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index bf5a6df556..1845fc42db 100644 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -190,7 +190,7 @@ namespace LLError {} void recordMessage(LLError::ELevel level, const std::string& message) override { - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED; mCallable(level, message); } private: @@ -198,7 +198,7 @@ namespace LLError }; /** - * @NOTE: addRecorder() and removeRecorder() uses the boost::shared_ptr to allow for shared ownership + * @NOTE: addRecorder() and removeRecorder() uses the std::shared_ptr to allow for shared ownership * while still ensuring that the allocated memory is eventually freed */ LL_COMMON_API void addRecorder(RecorderPtr); diff --git a/indra/llcommon/lleventemitter.h b/indra/llcommon/lleventemitter.h index 14160e1e76..b9de854fda 100644 --- a/indra/llcommon/lleventemitter.h +++ b/indra/llcommon/lleventemitter.h @@ -57,14 +57,14 @@ class eventEmitter /////////////////////////////////////////////////////////////////////////////// // - BOOL addObserver ( T* observerIn ) + bool addObserver ( T* observerIn ) { if ( ! observerIn ) - return FALSE; + return false; // check if observer already exists if ( std::find ( observers.begin (), observers.end (), observerIn ) != observers.end () ) - return FALSE; + return false; // save it observers.push_back ( observerIn ); @@ -74,14 +74,14 @@ class eventEmitter /////////////////////////////////////////////////////////////////////////////// // - BOOL remObserver ( T* observerIn ) + bool remObserver ( T* observerIn ) { if ( ! observerIn ) - return FALSE; + return false; observers.remove ( observerIn ); - return TRUE; + return true; }; /////////////////////////////////////////////////////////////////////////////// diff --git a/indra/llcommon/lleventfilter.h b/indra/llcommon/lleventfilter.h index 5c45144fad..d8c7e15a27 100644 --- a/indra/llcommon/lleventfilter.h +++ b/indra/llcommon/lleventfilter.h @@ -429,7 +429,7 @@ public: // path, then stores it to mTarget. virtual bool post(const LLSD& event) { - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED; // Extract the element specified by 'mPath' from 'event'. To perform a // generic type-appropriate store through mTarget, construct an diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 5b4e69659d..3c6743eac9 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -382,7 +382,7 @@ std::string LLEventPump::inventName(const std::string& pfx) void LLEventPump::clear() { - LLMutexLock lock(&mConnectionListMutex); + LLCoros::LockType lock(mConnectionListMutex); // Destroy the original LLStandardSignal instance, replacing it with a // whole new one. mSignal = std::make_shared<LLStandardSignal>(); @@ -394,7 +394,7 @@ void LLEventPump::reset() { // Resetting mSignal is supposed to disconnect everything on its own // But due to crash on 'reset' added explicit cleanup to get more data - LLMutexLock lock(&mConnectionListMutex); + LLCoros::LockType lock(mConnectionListMutex); ConnectionMap::const_iterator iter = mConnections.begin(); ConnectionMap::const_iterator end = mConnections.end(); while (iter!=end) @@ -419,7 +419,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL return LLBoundListener(); } - LLMutexLock lock(&mConnectionListMutex); + LLCoros::LockType lock(mConnectionListMutex); float nodePosition = 1.0; @@ -582,7 +582,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL LLBoundListener LLEventPump::getListener(const std::string& name) { - LLMutexLock lock(&mConnectionListMutex); + LLCoros::LockType lock(mConnectionListMutex); ConnectionMap::const_iterator found = mConnections.find(name); if (found != mConnections.end()) { @@ -594,7 +594,7 @@ LLBoundListener LLEventPump::getListener(const std::string& name) void LLEventPump::stopListening(const std::string& name) { - LLMutexLock lock(&mConnectionListMutex); + LLCoros::LockType lock(mConnectionListMutex); ConnectionMap::iterator found = mConnections.find(name); if (found != mConnections.end()) { diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index 9a0a6863f0..f97fca0a32 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -61,6 +61,7 @@ #include "llstl.h" #include "llexception.h" #include "llhandle.h" +#include "llcoros.h" /*==========================================================================*| // override this to allow binding free functions with more parameters @@ -601,7 +602,7 @@ private: LLHandle<LLEventPumps> mRegistry; std::string mName; - LLMutex mConnectionListMutex; + LLCoros::Mutex mConnectionListMutex; protected: virtual LLBoundListener listen_impl(const std::string& name, const LLEventListener&, diff --git a/indra/llcommon/lleventtimer.h b/indra/llcommon/lleventtimer.h index ed6f10d5e1..e0c2381807 100644 --- a/indra/llcommon/lleventtimer.h +++ b/indra/llcommon/lleventtimer.h @@ -43,7 +43,7 @@ public: //function to be called at the supplied frequency // Normally return FALSE; TRUE will delete the timer after the function returns. - virtual BOOL tick() = 0; + virtual bool tick() = 0; static void updateClass(); @@ -86,7 +86,7 @@ public: mOnce(once), mCallable(callable) {} - BOOL tick() override + bool tick() override { mCallable(); // true tells updateClass() to delete this instance diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 17ad37b031..09fcf8a1af 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -215,7 +215,7 @@ private: private: U64 mStartTime; - BlockTimerStackRecord mParentTimerData; + BlockTimerStackRecord mParentTimerData{}; public: // statics diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index 1877dd54ed..9045324bf2 100644 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -27,6 +27,12 @@ * $/LicenseInfo$ */ +#include "linden_common.h" +#include "llfile.h" +#include "llstring.h" +#include "llerror.h" +#include "stringize.h" + #if LL_WINDOWS #include "llwin32headerslean.h" #include <stdlib.h> // Windows errno @@ -35,12 +41,6 @@ #include <errno.h> #endif -#include "linden_common.h" -#include "llfile.h" -#include "llstring.h" -#include "llerror.h" -#include "stringize.h" - using namespace std; static std::string empty; @@ -248,6 +248,24 @@ int LLFile::close(LLFILE * file) return ret_value; } +std::string LLFile::getContents(const std::string& filename) +{ + LLFILE* fp = fopen(filename, "rb"); /* Flawfinder: ignore */ + if (fp) + { + fseek(fp, 0, SEEK_END); + U32 length = ftell(fp); + fseek(fp, 0, SEEK_SET); + + std::vector<char> buffer(length); + size_t nread = fread(buffer.data(), 1, length, fp); + fclose(fp); + + return std::string(buffer.data(), nread); + } + + return LLStringUtil::null; +} int LLFile::remove(const std::string& filename, int supress_error) { @@ -345,7 +363,7 @@ const char *LLFile::tmpdir() sep = '\\'; std::vector<wchar_t> utf16path(MAX_PATH + 1); - GetTempPathW(utf16path.size(), &utf16path[0]); + GetTempPathW(static_cast<DWORD>(utf16path.size()), &utf16path[0]); utf8path = ll_convert_wide_to_string(&utf16path[0]); #else sep = '/'; diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h index 08a008c19a..74110343fc 100644 --- a/indra/llcommon/llfile.h +++ b/indra/llcommon/llfile.h @@ -67,6 +67,8 @@ public: static int close(LLFILE * file); + static std::string getContents(const std::string& filename); + // perms is a permissions mask like 0777 or 0700. In most cases it will // be overridden by the user's umask. It is ignored on Windows. // mkdir() considers "directory already exists" to be SUCCESS. @@ -97,7 +99,7 @@ public: // no copy LLUniqueFile(const LLUniqueFile&) = delete; // move construction - LLUniqueFile(LLUniqueFile&& other) + LLUniqueFile(LLUniqueFile&& other) noexcept { mFileHandle = other.mFileHandle; other.mFileHandle = nullptr; @@ -118,7 +120,7 @@ public: // copy assignment deleted LLUniqueFile& operator=(const LLUniqueFile&) = delete; // move assignment - LLUniqueFile& operator=(LLUniqueFile&& other) + LLUniqueFile& operator=(LLUniqueFile&& other) noexcept { close(); std::swap(mFileHandle, other.mFileHandle); diff --git a/indra/llcommon/llfindlocale.cpp b/indra/llcommon/llfindlocale.cpp index e39812bfc4..ac52f90c9f 100644 --- a/indra/llcommon/llfindlocale.cpp +++ b/indra/llcommon/llfindlocale.cpp @@ -157,14 +157,22 @@ canonise_fl(FL_Locale *l) { if (l->lang && 0 == strcmp(l->lang, "en")) { if (l->country && 0 == strcmp(l->country, "UK")) { free((void*)l->country); +#ifdef LL_WINDOWS + l->country = _strdup("GB"); +#else l->country = strdup("GB"); +#endif } } /* ja_JA -> ja_JP */ if (l->lang && 0 == strcmp(l->lang, "ja")) { if (l->country && 0 == strcmp(l->country, "JA")) { free((void*)l->country); +#ifdef LL_WINDOWS + l->country = _strdup("JP"); +#else l->country = strdup("JP"); +#endif } } } diff --git a/indra/llcommon/llfixedbuffer.h b/indra/llcommon/llfixedbuffer.h index eca0792d35..1234d2014f 100644 --- a/indra/llcommon/llfixedbuffer.h +++ b/indra/llcommon/llfixedbuffer.h @@ -33,6 +33,7 @@ #include "llstring.h" #include "llthread.h" #include "llerrorcontrol.h" +#include "llcoros.h" // fixed buffer implementation class LL_COMMON_API LLFixedBuffer : public LLLineBuffer @@ -58,7 +59,7 @@ protected: void addWLine(const LLWString& line); protected: - LLMutex mMutex ; + LLCoros::Mutex mMutex ; }; #endif //LL_FIXED_BUFFER_H diff --git a/indra/llcommon/llframetimer.cpp b/indra/llcommon/llframetimer.cpp index 2805662d6f..a0080b57bb 100644 --- a/indra/llcommon/llframetimer.cpp +++ b/indra/llcommon/llframetimer.cpp @@ -52,12 +52,12 @@ void LLFrameTimer::updateFrameTime() void LLFrameTimer::start() { reset(); - mStarted = TRUE; + mStarted = true; } void LLFrameTimer::stop() { - mStarted = FALSE; + mStarted = false; } void LLFrameTimer::reset() @@ -84,14 +84,14 @@ void LLFrameTimer::pause() { if (mStarted) mStartTime = sFrameTime - mStartTime; // save dtime - mStarted = FALSE; + mStarted = false; } void LLFrameTimer::unpause() { if (!mStarted) mStartTime = sFrameTime - mStartTime; // restore dtime - mStarted = TRUE; + mStarted = true; } void LLFrameTimer::setTimerExpirySec(F32 expiration) @@ -112,7 +112,7 @@ F64 LLFrameTimer::expiresAt() const return expires_at; } -BOOL LLFrameTimer::checkExpirationAndReset(F32 expiration) +bool LLFrameTimer::checkExpirationAndReset(F32 expiration) { //LL_INFOS() << "LLFrameTimer::checkExpirationAndReset()" << LL_ENDL; //LL_INFOS() << " mStartTime:" << mStartTime << LL_ENDL; @@ -123,9 +123,9 @@ BOOL LLFrameTimer::checkExpirationAndReset(F32 expiration) { reset(); setTimerExpirySec(expiration); - return TRUE; + return true; } - return FALSE; + return false; } // static diff --git a/indra/llcommon/llframetimer.h b/indra/llcommon/llframetimer.h index 876d933fd1..ba4f075b57 100644 --- a/indra/llcommon/llframetimer.h +++ b/indra/llcommon/llframetimer.h @@ -39,7 +39,7 @@ class LL_COMMON_API LLFrameTimer { public: - LLFrameTimer() : mStartTime( sFrameTime ), mExpiry(0), mStarted(TRUE) {} + LLFrameTimer() : mStartTime( sFrameTime ), mExpiry(0), mStarted(true) {} // Return the number of seconds since the start of this // application instance. @@ -84,16 +84,16 @@ public: void unpause(); void setTimerExpirySec(F32 expiration); void setExpiryAt(F64 seconds_since_epoch); - BOOL checkExpirationAndReset(F32 expiration); + bool checkExpirationAndReset(F32 expiration); F32 getElapsedTimeAndResetF32() { F32 t = F32(sFrameTime - mStartTime); reset(); return t; } void setAge(const F64 age) { mStartTime = sFrameTime - age; } // ACCESSORS - BOOL hasExpired() const { return (sFrameTime >= mExpiry); } + bool hasExpired() const { return (sFrameTime >= mExpiry); } F32 getTimeToExpireF32() const { return (F32)(mExpiry - sFrameTime); } F32 getElapsedTimeF32() const { return mStarted ? (F32)(sFrameTime - mStartTime) : (F32)mStartTime; } - BOOL getStarted() const { return mStarted; } + bool getStarted() const { return mStarted; } // return the seconds since epoch when this timer will expire. F64 expiresAt() const; @@ -142,7 +142,7 @@ protected: // Useful bit of state usually associated with timers, but does // not affect actual functionality - BOOL mStarted; + bool mStarted; }; // Glue code for Havok (or anything else that doesn't want the full .h files) diff --git a/indra/llcommon/llindexedvector.h b/indra/llcommon/llindexedvector.h index de3ae0dcc4..0b2e9c76ca 100644 --- a/indra/llcommon/llindexedvector.h +++ b/indra/llcommon/llindexedvector.h @@ -47,7 +47,7 @@ public: typedef typename std::vector<Type>::size_type size_type; protected: std::vector<Type> mVector; - std::map<Key, U32> mIndexMap; + std::map<Key, size_t> mIndexMap; public: LLIndexedVector() { mVector.reserve(BlockSize); } @@ -68,10 +68,10 @@ public: Type& operator[](const Key& k) { - typename std::map<Key, U32>::const_iterator iter = mIndexMap.find(k); + typename std::map<Key, size_t>::const_iterator iter = mIndexMap.find(k); if (iter == mIndexMap.end()) { - U32 n = mVector.size(); + auto n = mVector.size(); mIndexMap[k] = n; mVector.push_back(Type()); llassert(mVector.size() == mIndexMap.size()); @@ -85,7 +85,7 @@ public: const_iterator find(const Key& k) const { - typename std::map<Key, U32>::const_iterator iter = mIndexMap.find(k); + typename std::map<Key, size_t>::const_iterator iter = mIndexMap.find(k); if(iter == mIndexMap.end()) { return mVector.end(); diff --git a/indra/llcommon/llkeythrottle.h b/indra/llcommon/llkeythrottle.h index a5b5eaa946..8ee0e08c69 100644 --- a/indra/llcommon/llkeythrottle.h +++ b/indra/llcommon/llkeythrottle.h @@ -91,9 +91,9 @@ template< class T > class LLKeyThrottle { public: - // @param realtime = FALSE for frame-based throttle, TRUE for usec + // @param realtime = false for frame-based throttle, true for usec // real-time throttle - LLKeyThrottle(U32 limit, F32 interval, BOOL realtime = TRUE) + LLKeyThrottle(U32 limit, F32 interval, bool realtime = true) : m(* new LLKeyThrottleImpl<T>) { setParameters( limit, interval, realtime ); @@ -287,7 +287,7 @@ public: } // Get the throttling parameters - void getParameters( U32 & out_limit, F32 & out_interval, BOOL & out_realtime ) + void getParameters( U32 & out_limit, F32 & out_interval, bool & out_realtime ) { out_limit = m.countLimit; out_interval = m.intervalLength; @@ -295,7 +295,7 @@ public: } // Set the throttling behavior - void setParameters( U32 limit, F32 interval, BOOL realtime = TRUE ) + void setParameters( U32 limit, F32 interval, bool realtime = true ) { // limit is the maximum number of keys // allowed per interval (in seconds or frames) @@ -325,7 +325,7 @@ public: protected: LLKeyThrottleImpl<T>& m; - BOOL mIsRealtime; // TRUE to be time based (default), FALSE for frame based + bool mIsRealtime; // true to be time based (default), false for frame based }; #endif diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp index e93ba83434..662a2511cd 100644 --- a/indra/llcommon/llleap.cpp +++ b/indra/llcommon/llleap.cpp @@ -233,7 +233,7 @@ public: LL_DEBUGS("EventHost") << "Sending: " << static_cast<U64>(buffer.tellp()) << ':'; - std::string::size_type truncate(80); + llssize truncate(80); if (buffer.tellp() <= truncate) { LL_CONT << buffer.str(); diff --git a/indra/llcommon/lllivefile.cpp b/indra/llcommon/lllivefile.cpp index 15651a6813..58de61a7e4 100644 --- a/indra/llcommon/lllivefile.cpp +++ b/indra/llcommon/lllivefile.cpp @@ -170,10 +170,10 @@ namespace : LLEventTimer(refresh), mLiveFile(f) { } - BOOL tick() + bool tick() { mLiveFile.checkAndReload(); - return FALSE; + return false; } private: diff --git a/indra/llcommon/llmainthreadtask.h b/indra/llcommon/llmainthreadtask.h index 28ad62830b..cec95b2356 100644 --- a/indra/llcommon/llmainthreadtask.h +++ b/indra/llcommon/llmainthreadtask.h @@ -79,13 +79,13 @@ private: LLEventTimer(0), mTask(std::forward<CALLABLE>(callable)) {} - BOOL tick() override + bool tick() override { // run the task on the main thread, will populate the future // obtained by get_future() mTask(); // tell LLEventTimer we're done (one shot) - return TRUE; + return true; } // Given arbitrary CALLABLE, which might be a lambda, how are we // supposed to obtain its signature for std::packaged_task? It seems diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index cf5ead718d..99c803e46f 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -39,6 +39,7 @@ #elif LL_LINUX # include <unistd.h> # include <sys/resource.h> +# include <sys/sysinfo.h> #endif #include "llmemory.h" @@ -50,13 +51,28 @@ //---------------------------------------------------------------------------- //static + +// most important memory metric for texture streaming +// On Windows, this should agree with resource monitor -> performance -> memory -> available +// On OS X, this should be activity monitor -> memory -> (physical memory - memory used) +// NOTE: this number MAY be less than the actual available memory on systems with more than MaxHeapSize64 GB of physical memory (default 16GB) +// In that case, should report min(available, sMaxHeapSizeInKB-sAllocateMemInKB) U32Kilobytes LLMemory::sAvailPhysicalMemInKB(U32_MAX); + +// Installed physical memory U32Kilobytes LLMemory::sMaxPhysicalMemInKB(0); -static LLTrace::SampleStatHandle<F64Megabytes> sAllocatedMem("allocated_mem", "active memory in use by application"); -static LLTrace::SampleStatHandle<F64Megabytes> sVirtualMem("virtual_mem", "virtual memory assigned to application"); + +// Maximimum heap size according to the user's settings (default 16GB) +U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX); + +// Current memory usage U32Kilobytes LLMemory::sAllocatedMemInKB(0); + U32Kilobytes LLMemory::sAllocatedPageSizeInKB(0); -U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX); + + +static LLTrace::SampleStatHandle<F64Megabytes> sAllocatedMem("allocated_mem", "active memory in use by application"); +static LLTrace::SampleStatHandle<F64Megabytes> sVirtualMem("virtual_mem", "virtual memory assigned to application"); void ll_assert_aligned_func(uintptr_t ptr,U32 alignment) { @@ -84,7 +100,14 @@ void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size) //static void LLMemory::updateMemoryInfo() { - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED; + + sMaxPhysicalMemInKB = gSysMemory.getPhysicalMemoryKB(); + + U32Kilobytes avail_mem; + LLMemoryInfo::getAvailableMemoryKB(avail_mem); + sAvailPhysicalMemInKB = avail_mem; + #if LL_WINDOWS PROCESS_MEMORY_COUNTERS counters; @@ -95,23 +118,9 @@ void LLMemory::updateMemoryInfo() } sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(counters.WorkingSetSize)); - sample(sAllocatedMem, sAllocatedMemInKB); sAllocatedPageSizeInKB = U32Kilobytes::convert(U64Bytes(counters.PagefileUsage)); sample(sVirtualMem, sAllocatedPageSizeInKB); - U32Kilobytes avail_phys, avail_virtual; - LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ; - sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB); - - if(sMaxPhysicalMemInKB > sAllocatedMemInKB) - { - sAvailPhysicalMemInKB = sMaxPhysicalMemInKB - sAllocatedMemInKB ; - } - else - { - sAvailPhysicalMemInKB = U32Kilobytes(0); - } - #elif defined(LL_DARWIN) task_vm_info info; mach_msg_type_number_t infoCount = TASK_VM_INFO_COUNT; @@ -136,31 +145,19 @@ void LLMemory::updateMemoryInfo() { LL_WARNS() << "task_info failed" << LL_ENDL; } - - // Total installed and available physical memory are properties of the host, not just our process. - vm_statistics64_data_t vmstat; - mach_msg_type_number_t count = HOST_VM_INFO64_COUNT; - mach_port_t host = mach_host_self(); - vm_size_t page_size; - host_page_size(host, &page_size); - kern_return_t result = host_statistics64(host, HOST_VM_INFO64, reinterpret_cast<host_info_t>(&vmstat), &count); - if (result == KERN_SUCCESS) { - // This is what Chrome reports as 'the "Physical Memory Free" value reported by the Memory Monitor in Instruments.' - // Note though that inactive pages are not included here and not yet free, but could become so under memory pressure. - sAvailPhysicalMemInKB = U32Bytes(vmstat.free_count * page_size); - sMaxPhysicalMemInKB = LLMemoryInfo::getHardwareMemSize(); - } - else - { - LL_WARNS() << "task_info failed" << LL_ENDL; - } - +#elif defined(LL_LINUX) + // Use sysinfo() to get the total physical memory. + struct sysinfo info; + sysinfo(&info); + sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(LLMemory::getCurrentRSS())); // represents the RAM allocated by this process only (in line with the windows implementation) #else //not valid for other systems for now. + LL_WARNS() << "LLMemory::updateMemoryInfo() not implemented for this platform." << LL_ENDL; sAllocatedMemInKB = U64Bytes(LLMemory::getCurrentRSS()); - sMaxPhysicalMemInKB = U64Bytes(U32_MAX); - sAvailPhysicalMemInKB = U64Bytes(U32_MAX); #endif + sample(sAllocatedMem, sAllocatedMemInKB); + + sAvailPhysicalMemInKB = llmin(sAvailPhysicalMemInKB, sMaxHeapSizeInKB - sAllocatedMemInKB); return ; } @@ -190,18 +187,18 @@ void* LLMemory::tryToAlloc(void* address, U32 size) } //static -void LLMemory::logMemoryInfo(BOOL update) +void LLMemory::logMemoryInfo(bool update) { - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED; if(update) { updateMemoryInfo() ; } - LL_INFOS() << "Current allocated physical memory(KB): " << sAllocatedMemInKB << LL_ENDL ; - LL_INFOS() << "Current allocated page size (KB): " << sAllocatedPageSizeInKB << LL_ENDL ; - LL_INFOS() << "Current available physical memory(KB): " << sAvailPhysicalMemInKB << LL_ENDL ; - LL_INFOS() << "Current max usable memory(KB): " << sMaxPhysicalMemInKB << LL_ENDL ; + LL_INFOS() << llformat("Current allocated physical memory: %.2f MB", sAllocatedMemInKB / 1024.0) << LL_ENDL; + LL_INFOS() << llformat("Current allocated page size: %.2f MB", sAllocatedPageSizeInKB / 1024.0) << LL_ENDL; + LL_INFOS() << llformat("Current available physical memory: %.2f MB", sAvailPhysicalMemInKB / 1024.0) << LL_ENDL; + LL_INFOS() << llformat("Current max usable memory: %.2f MB", sMaxPhysicalMemInKB / 1024.0) << LL_ENDL; } //static @@ -327,8 +324,8 @@ void* ll_aligned_malloc_fallback( size_t size, int align ) __asm int 3; } DWORD old; - BOOL Res = VirtualProtect((void*)((char*)p + for_alloc), sysinfo.dwPageSize, PAGE_NOACCESS, &old); - if(FALSE == Res) { + bool Res = VirtualProtect((void*)((char*)p + for_alloc), sysinfo.dwPageSize, PAGE_NOACCESS, &old); + if(false == Res) { // call debugger __asm int 3; } diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 313c380587..80cfe554c4 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -134,7 +134,7 @@ public: \ void ll_aligned_free_fallback( void* ptr ); //------------------------------------------------------------------------------------------------ #else - inline void* ll_aligned_malloc_fallback( size_t size, int align ) + inline void* ll_aligned_malloc_fallback( size_t size, size_t align ) { LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY; #if defined(LL_WINDOWS) @@ -390,7 +390,7 @@ public: static void* tryToAlloc(void* address, U32 size); static void initMaxHeapSizeGB(F32Gigabytes max_heap_size); static void updateMemoryInfo() ; - static void logMemoryInfo(BOOL update = FALSE); + static void logMemoryInfo(bool update = false); static U32Kilobytes getAvailableMemKB() ; static U32Kilobytes getMaxMemKB() ; diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp index e05c2558f6..cc258e4609 100644 --- a/indra/llcommon/llmetricperformancetester.cpp +++ b/indra/llcommon/llmetricperformancetester.cpp @@ -50,18 +50,18 @@ void LLMetricPerformanceTesterBasic::cleanupClass() } /*static*/ -BOOL LLMetricPerformanceTesterBasic::addTester(LLMetricPerformanceTesterBasic* tester) +bool LLMetricPerformanceTesterBasic::addTester(LLMetricPerformanceTesterBasic* tester) { llassert_always(tester != NULL); std::string name = tester->getTesterName() ; if (getTester(name)) { LL_ERRS() << "Tester name is already used by some other tester : " << name << LL_ENDL ; - return FALSE; + return false; } sTesterMap.insert(std::make_pair(name, tester)); - return TRUE; + return true; } /*static*/ @@ -88,8 +88,8 @@ LLMetricPerformanceTesterBasic* LLMetricPerformanceTesterBasic::getTester(std::s } /*static*/ -// Return TRUE if this metric is requested or if the general default "catch all" metric is requested -BOOL LLMetricPerformanceTesterBasic::isMetricLogRequested(std::string name) +// Return true if this metric is requested or if the general default "catch all" metric is requested +bool LLMetricPerformanceTesterBasic::isMetricLogRequested(std::string name) { return (LLTrace::BlockTimer::sMetricLog && ((LLTrace::BlockTimer::sLogName == name) || (LLTrace::BlockTimer::sLogName == DEFAULT_METRIC_NAME))); } @@ -215,8 +215,8 @@ void LLMetricPerformanceTesterBasic::analyzePerformance(llofstream* os, LLSD* ba resetCurrentCount() ; std::string current_label = getCurrentLabelName(); - BOOL in_base = (*base).has(current_label) ; - BOOL in_current = (*current).has(current_label) ; + bool in_base = (*base).has(current_label) ; + bool in_current = (*current).has(current_label) ; while(in_base || in_current) { diff --git a/indra/llcommon/llmetricperformancetester.h b/indra/llcommon/llmetricperformancetester.h index 15c564f2ca..78abd53602 100644 --- a/indra/llcommon/llmetricperformancetester.h +++ b/indra/llcommon/llmetricperformancetester.h @@ -48,7 +48,7 @@ public: * Need to be tested after creation of a tester instance so to know if the tester is correctly handled. * A tester might not be added to the map if another tester with the same name already exists. */ - BOOL isValid() const { return mValidInstance; } + bool isValid() const { return mValidInstance; } /** * @brief Write a set of test results to the log LLSD. @@ -122,7 +122,7 @@ private: std::string mName ; // Name of this tester instance S32 mCount ; // Current record count - BOOL mValidInstance; // TRUE if the instance is managed by the map + bool mValidInstance; // true if the instance is managed by the map std::vector< std::string > mMetricStrings ; // Metrics strings // Static members managing the collection of testers @@ -144,15 +144,15 @@ public: static void deleteTester(std::string name); /** - * @return Returns TRUE if that metric *or* the default catch all metric has been requested to be logged + * @return Returns true if that metric *or* the default catch all metric has been requested to be logged * @param[in] name - Name of the tester queried. */ - static BOOL isMetricLogRequested(std::string name); + static bool isMetricLogRequested(std::string name); /** - * @return Returns TRUE if there's a tester defined, FALSE otherwise. + * @return Returns true if there's a tester defined, false otherwise. */ - static BOOL hasMetricPerformanceTesters() { return !sTesterMap.empty() ;} + static bool hasMetricPerformanceTesters() { return !sTesterMap.empty() ;} /** * @brief Delete all testers and reset the tester map */ @@ -160,7 +160,7 @@ public: private: // Add a tester to the map. Returns false if adding fails. - static BOOL addTester(LLMetricPerformanceTesterBasic* tester) ; + static bool addTester(LLMetricPerformanceTesterBasic* tester) ; }; /** diff --git a/indra/llcommon/llmortician.cpp b/indra/llcommon/llmortician.cpp index 00d4a32553..578d72388c 100644 --- a/indra/llcommon/llmortician.cpp +++ b/indra/llcommon/llmortician.cpp @@ -30,7 +30,7 @@ std::list<LLMortician*> LLMortician::sGraveyard; -BOOL LLMortician::sDestroyImmediate = FALSE; +bool LLMortician::sDestroyImmediate = false; LLMortician::~LLMortician() { @@ -88,19 +88,19 @@ void LLMortician::die() if (sDestroyImmediate) { // *NOTE: This is a hack to ensure destruction order on shutdown (relative to non-mortician controlled classes). - mIsDead = TRUE; + mIsDead = true; delete this; return; } else if (!mIsDead) { - mIsDead = TRUE; + mIsDead = true; sGraveyard.push_back(this); } } // static -void LLMortician::setZealous(BOOL b) +void LLMortician::setZealous(bool b) { sDestroyImmediate = b; } diff --git a/indra/llcommon/llmortician.h b/indra/llcommon/llmortician.h index 6dca4da0c9..b2d81fa1c5 100644 --- a/indra/llcommon/llmortician.h +++ b/indra/llcommon/llmortician.h @@ -33,21 +33,21 @@ class LL_COMMON_API LLMortician { public: - LLMortician() { mIsDead = FALSE; } + LLMortician() { mIsDead = false; } static auto graveyardCount() { return sGraveyard.size(); }; static size_t logClass(std::stringstream &str); static void updateClass(); virtual ~LLMortician(); void die(); - BOOL isDead() { return mIsDead; } + bool isDead() { return mIsDead; } // sets destroy immediate true - static void setZealous(BOOL b); + static void setZealous(bool b); private: - static BOOL sDestroyImmediate; + static bool sDestroyImmediate; - BOOL mIsDead; + bool mIsDead; static std::list<LLMortician*> sGraveyard; }; diff --git a/indra/llcommon/llmutex.cpp b/indra/llcommon/llmutex.cpp index db14abb1fe..be1ae89a25 100644 --- a/indra/llcommon/llmutex.cpp +++ b/indra/llcommon/llmutex.cpp @@ -28,23 +28,35 @@ #include "llmutex.h" #include "llthread.h" #include "lltimer.h" +#include "llcoros.h" -//============================================================================ +//--------------------------------------------------------------------- +// +// LLMutex +// LLMutex::LLMutex() : mCount(0) { } - LLMutex::~LLMutex() { } - void LLMutex::lock() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + + // LLMutex is not coroutine aware and should not be used from a coroutine + // If your code is running in a coroutine, you should use LLCoros::Mutex instead + // NOTE: If the stack trace you're staring at contains non-thread-safe code, + // you should use LLAppViewer::instance().postToMainThread() to shuttle execution + // back to the main loop. + // NOTE: If you got here from seeing this assert in your log and you're not seeing + // a stack trace that points here, put a breakpoint in on_main_coro and try again. + llassert(LLCoros::on_main_coro()); + if(isSelfLocked()) { //redundant lock mCount++; @@ -56,9 +68,9 @@ void LLMutex::lock() #if MUTEX_DEBUG // Have to have the lock before we can access the debug info auto id = LLThread::currentID(); - if (mIsLocked[id] != FALSE) + if (mIsLocked[id]) LL_ERRS() << "Already locked in Thread: " << id << LL_ENDL; - mIsLocked[id] = TRUE; + mIsLocked[id] = true; #endif mLockingThread = LLThread::currentID(); @@ -66,7 +78,8 @@ void LLMutex::lock() void LLMutex::unlock() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + if (mCount > 0) { //not the root unlock mCount--; @@ -76,9 +89,9 @@ void LLMutex::unlock() #if MUTEX_DEBUG // Access the debug info while we have the lock auto id = LLThread::currentID(); - if (mIsLocked[id] != TRUE) + if (!mIsLocked[id]) LL_ERRS() << "Not locked in Thread: " << id << LL_ENDL; - mIsLocked[id] = FALSE; + mIsLocked[id] = false; #endif mLockingThread = LLThread::id_t(); @@ -87,7 +100,7 @@ void LLMutex::unlock() bool LLMutex::isLocked() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; if (!mMutex.try_lock()) { return true; @@ -111,8 +124,8 @@ LLThread::id_t LLMutex::lockingThread() const bool LLMutex::trylock() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD - if(isSelfLocked()) + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + if (isSelfLocked()) { //redundant lock mCount++; return true; @@ -126,54 +139,232 @@ bool LLMutex::trylock() #if MUTEX_DEBUG // Have to have the lock before we can access the debug info auto id = LLThread::currentID(); - if (mIsLocked[id] != FALSE) + if (mIsLocked[id]) LL_ERRS() << "Already locked in Thread: " << id << LL_ENDL; - mIsLocked[id] = TRUE; + mIsLocked[id] = true; #endif mLockingThread = LLThread::currentID(); return true; } -//============================================================================ +//--------------------------------------------------------------------- +// +// LLSharedMutex +// +LLSharedMutex::LLSharedMutex() +: mLockingThreads(2) // Reserve 2 slots in the map hash table +, mIsShared(false) +{ +} + +bool LLSharedMutex::isLocked() const +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + std::lock_guard<std::mutex> lock(mLockMutex); + + return !mLockingThreads.empty(); +} + +bool LLSharedMutex::isThreadLocked() const +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + LLThread::id_t current_thread = LLThread::currentID(); + std::lock_guard<std::mutex> lock(mLockMutex); + + const_iterator it = mLockingThreads.find(current_thread); + return it != mLockingThreads.end(); +} + +void LLSharedMutex::lockShared() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + LLThread::id_t current_thread = LLThread::currentID(); + + mLockMutex.lock(); + iterator it = mLockingThreads.find(current_thread); + if (it != mLockingThreads.end()) + { + it->second++; + } + else + { + // Acquire the mutex immediately if the mutex is not locked exclusively + // or enter a locking state if the mutex is already locked exclusively + mLockMutex.unlock(); + mSharedMutex.lock_shared(); + mLockMutex.lock(); + // Continue after acquiring the mutex + mLockingThreads.emplace(std::make_pair(current_thread, 1)); + mIsShared = true; + } + mLockMutex.unlock(); +} + +void LLSharedMutex::lockExclusive() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + LLThread::id_t current_thread = LLThread::currentID(); + + mLockMutex.lock(); + iterator it = mLockingThreads.find(current_thread); + if (it != mLockingThreads.end()) + { + if (mIsShared) + { + // The mutex is already locked in the current thread + // but this lock is SHARED (not EXCLISIVE) + // We can't lock it again, the lock stays shared + // This can lead to a collision (theoretically) + llassert_always(!"The current thread is already locked SHARED and can't be locked EXCLUSIVE"); + } + it->second++; + } + else + { + // Acquire the mutex immediately if mLockingThreads is empty + // or enter a locking state if mLockingThreads is not empty + mLockMutex.unlock(); + mSharedMutex.lock(); + mLockMutex.lock(); + // Continue after acquiring the mutex (and possible quitting the locking state) + mLockingThreads.emplace(std::make_pair(current_thread, 1)); + mIsShared = false; + } + mLockMutex.unlock(); +} + +bool LLSharedMutex::trylockShared() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + LLThread::id_t current_thread = LLThread::currentID(); + std::lock_guard<std::mutex> lock(mLockMutex); + + iterator it = mLockingThreads.find(current_thread); + if (it != mLockingThreads.end()) + { + it->second++; + } + else + { + if (!mSharedMutex.try_lock_shared()) + return false; + + mLockingThreads.emplace(std::make_pair(current_thread, 1)); + mIsShared = true; + } + + return true; +} + +bool LLSharedMutex::trylockExclusive() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + LLThread::id_t current_thread = LLThread::currentID(); + std::lock_guard<std::mutex> lock(mLockMutex); + + if (mLockingThreads.size() == 1 && mLockingThreads.begin()->first == current_thread) + { + mLockingThreads.begin()->second++; + } + else + { + if (!mSharedMutex.try_lock()) + return false; + + mLockingThreads.emplace(std::make_pair(current_thread, 1)); + mIsShared = false; + } + + return true; +} + +void LLSharedMutex::unlockShared() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + LLThread::id_t current_thread = LLThread::currentID(); + std::lock_guard<std::mutex> lock(mLockMutex); + + iterator it = mLockingThreads.find(current_thread); + if (it != mLockingThreads.end()) + { + if (it->second > 1) + { + it->second--; + } + else + { + mLockingThreads.erase(it); + mSharedMutex.unlock_shared(); + } + } +} + +void LLSharedMutex::unlockExclusive() +{ + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; + LLThread::id_t current_thread = LLThread::currentID(); + std::lock_guard<std::mutex> lock(mLockMutex); + + iterator it = mLockingThreads.find(current_thread); + if (it != mLockingThreads.end()) + { + if (it->second > 1) + { + it->second--; + } + else + { + mLockingThreads.erase(it); + mSharedMutex.unlock(); + } + } +} + + +//--------------------------------------------------------------------- +// +// LLCondition +// LLCondition::LLCondition() : LLMutex() { } - LLCondition::~LLCondition() { } - void LLCondition::wait() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; std::unique_lock< std::mutex > lock(mMutex); mCond.wait(lock); } void LLCondition::signal() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; mCond.notify_one(); } void LLCondition::broadcast() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; mCond.notify_all(); } - +//--------------------------------------------------------------------- +// +// LLMutexTrylock +// LLMutexTrylock::LLMutexTrylock(LLMutex* mutex) : mMutex(mutex), mLocked(false) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; if (mMutex) mLocked = mMutex->trylock(); } @@ -182,7 +373,7 @@ LLMutexTrylock::LLMutexTrylock(LLMutex* mutex, U32 aTries, U32 delay_ms) : mMutex(mutex), mLocked(false) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; if (!mMutex) return; @@ -197,7 +388,7 @@ LLMutexTrylock::LLMutexTrylock(LLMutex* mutex, U32 aTries, U32 delay_ms) LLMutexTrylock::~LLMutexTrylock() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; if (mMutex && mLocked) mMutex->unlock(); } @@ -209,7 +400,7 @@ LLMutexTrylock::~LLMutexTrylock() // LLScopedLock::LLScopedLock(std::mutex* mutex) : mMutex(mutex) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; if(mutex) { mutex->lock(); @@ -228,7 +419,7 @@ LLScopedLock::~LLScopedLock() void LLScopedLock::unlock() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; if(mLocked) { mMutex->unlock(); diff --git a/indra/llcommon/llmutex.h b/indra/llcommon/llmutex.h index 9a888f1220..6e8cf9643b 100644 --- a/indra/llcommon/llmutex.h +++ b/indra/llcommon/llmutex.h @@ -32,6 +32,8 @@ #include <boost/noncopyable.hpp> #include "mutex.h" +#include <shared_mutex> +#include <unordered_map> #include <condition_variable> //============================================================================ @@ -62,10 +64,79 @@ protected: mutable LLThread::id_t mLockingThread; #if MUTEX_DEBUG - std::unordered_map<LLThread::id_t, BOOL> mIsLocked; + std::unordered_map<LLThread::id_t, bool> mIsLocked; #endif }; +//============================================================================ + +class LL_COMMON_API LLSharedMutex +{ +public: + LLSharedMutex(); + + bool isLocked() const; + bool isThreadLocked() const; + bool isShared() const { return mIsShared; } + + void lockShared(); + void lockExclusive(); + template<bool SHARED> void lock(); + + bool trylockShared(); + bool trylockExclusive(); + template<bool SHARED> bool trylock(); + + void unlockShared(); + void unlockExclusive(); + template<bool SHARED> void unlock(); + +private: + std::shared_mutex mSharedMutex; + mutable std::mutex mLockMutex; + std::unordered_map<LLThread::id_t, U32> mLockingThreads; + bool mIsShared; + + using iterator = std::unordered_map<LLThread::id_t, U32>::iterator; + using const_iterator = std::unordered_map<LLThread::id_t, U32>::const_iterator; +}; + +template<> +inline void LLSharedMutex::lock<true>() +{ + lockShared(); +} + +template<> +inline void LLSharedMutex::lock<false>() +{ + lockExclusive(); +} + +template<> +inline bool LLSharedMutex::trylock<true>() +{ + return trylockShared(); +} + +template<> +inline bool LLSharedMutex::trylock<false>() +{ + return trylockExclusive(); +} + +template<> +inline void LLSharedMutex::unlock<true>() +{ + unlockShared(); +} + +template<> +inline void LLSharedMutex::unlock<false>() +{ + unlockExclusive(); +} + // Actually a condition/mutex pair (since each condition needs to be associated with a mutex). class LL_COMMON_API LLCondition : public LLMutex { @@ -81,6 +152,8 @@ protected: std::condition_variable mCond; }; +//============================================================================ + class LLMutexLock { public: @@ -88,20 +161,48 @@ public: { mMutex = mutex; - if(mMutex) + if (mMutex) mMutex->lock(); } + ~LLMutexLock() { - if(mMutex) + if (mMutex) mMutex->unlock(); } + private: LLMutex* mMutex; }; //============================================================================ +template<bool SHARED> +class LLSharedMutexLockTemplate +{ +public: + LLSharedMutexLockTemplate(LLSharedMutex* mutex) + : mSharedMutex(mutex) + { + if (mSharedMutex) + mSharedMutex->lock<SHARED>(); + } + + ~LLSharedMutexLockTemplate() + { + if (mSharedMutex) + mSharedMutex->unlock<SHARED>(); + } + +private: + LLSharedMutex* mSharedMutex; +}; + +using LLSharedMutexLock = LLSharedMutexLockTemplate<true>; +using LLExclusiveMutexLock = LLSharedMutexLockTemplate<false>; + +//============================================================================ + // Scoped locking class similar in function to LLMutexLock but uses // the trylock() method to conditionally acquire lock without // blocking. Caller resolves the resulting condition by calling @@ -127,6 +228,8 @@ private: bool mLocked; }; +//============================================================================ + /** * @class LLScopedLock * @brief Small class to help lock and unlock mutexes. diff --git a/indra/llcommon/llnametable.h b/indra/llcommon/llnametable.h index b3a9df8fc3..0c4cc4c04d 100644 --- a/indra/llcommon/llnametable.h +++ b/indra/llcommon/llnametable.h @@ -55,16 +55,16 @@ public: mNameMap[tablename] = data; } - BOOL checkName(const std::string& name) const + bool checkName(const std::string& name) const { return checkName(name.c_str()); } // "logically const" even though it modifies the global nametable - BOOL checkName(const char *name) const + bool checkName(const char *name) const { char *tablename = gStringTable.addString(name); - return mNameMap.count(tablename) ? TRUE : FALSE; + return mNameMap.find(tablename) != mNameMap.end(); } DATA resolveName(const std::string& name) const diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h index f5916f9d58..6edff9fa5e 100644 --- a/indra/llcommon/llpointer.h +++ b/indra/llcommon/llpointer.h @@ -46,8 +46,11 @@ template <class Type> class LLPointer { public: + template<typename Subclass> + friend class LLPointer; + LLPointer() : - mPointer(NULL) + mPointer(nullptr) { } @@ -63,6 +66,12 @@ public: ref(); } + LLPointer(LLPointer<Type>&& ptr) noexcept + { + mPointer = ptr.mPointer; + ptr.mPointer = nullptr; + } + // Support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. template<typename Subclass> LLPointer(const LLPointer<Subclass>& ptr) : @@ -71,6 +80,13 @@ public: ref(); } + template<typename Subclass> + LLPointer(LLPointer<Subclass>&& ptr) noexcept : + mPointer(ptr.get()) + { + ptr.mPointer = nullptr; + } + ~LLPointer() { unref(); @@ -82,11 +98,11 @@ public: const Type& operator*() const { return *mPointer; } Type& operator*() { return *mPointer; } - operator BOOL() const { return (mPointer != NULL); } - operator bool() const { return (mPointer != NULL); } - bool operator!() const { return (mPointer == NULL); } - bool isNull() const { return (mPointer == NULL); } - bool notNull() const { return (mPointer != NULL); } + operator BOOL() const { return (mPointer != nullptr); } + operator bool() const { return (mPointer != nullptr); } + bool operator!() const { return (mPointer == nullptr); } + bool isNull() const { return (mPointer == nullptr); } + bool notNull() const { return (mPointer != nullptr); } operator Type*() const { return mPointer; } bool operator !=(Type* ptr) const { return (mPointer != ptr); } @@ -107,6 +123,17 @@ public: return *this; } + LLPointer<Type>& operator =(LLPointer<Type>&& ptr) + { + if (mPointer != ptr.mPointer) + { + unref(); + mPointer = ptr.mPointer; + ptr.mPointer = nullptr; + } + return *this; + } + // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. template<typename Subclass> LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr) @@ -115,6 +142,18 @@ public: return *this; } + template<typename Subclass> + LLPointer<Type>& operator =(LLPointer<Subclass>&& ptr) + { + if (mPointer != ptr.mPointer) + { + unref(); + mPointer = ptr.mPointer; + ptr.mPointer = nullptr; + } + return *this; + } + // Just exchange the pointers, which will not change the reference counts. static void swap(LLPointer<Type>& a, LLPointer<Type>& b) { @@ -141,9 +180,9 @@ protected: if (mPointer) { Type *temp = mPointer; - mPointer = NULL; + mPointer = nullptr; temp->unref(); - if (mPointer != NULL) + if (mPointer != nullptr) { LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL; unref(); @@ -168,9 +207,11 @@ protected: template <class Type> class LLConstPointer { + template<typename Subclass> + friend class LLConstPointer; public: LLConstPointer() : - mPointer(NULL) + mPointer(nullptr) { } @@ -186,6 +227,12 @@ public: ref(); } + LLConstPointer(LLConstPointer<Type>&& ptr) noexcept + { + mPointer = ptr.mPointer; + ptr.mPointer = nullptr; + } + // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. template<typename Subclass> LLConstPointer(const LLConstPointer<Subclass>& ptr) : @@ -194,6 +241,13 @@ public: ref(); } + template<typename Subclass> + LLConstPointer(LLConstPointer<Subclass>&& ptr) noexcept : + mPointer(ptr.get()) + { + ptr.mPointer = nullptr; + } + ~LLConstPointer() { unref(); @@ -203,11 +257,11 @@ public: const Type* operator->() const { return mPointer; } const Type& operator*() const { return *mPointer; } - operator BOOL() const { return (mPointer != NULL); } - operator bool() const { return (mPointer != NULL); } - bool operator!() const { return (mPointer == NULL); } - bool isNull() const { return (mPointer == NULL); } - bool notNull() const { return (mPointer != NULL); } + operator BOOL() const { return (mPointer != nullptr); } + operator bool() const { return (mPointer != nullptr); } + bool operator!() const { return (mPointer == nullptr); } + bool isNull() const { return (mPointer == nullptr); } + bool notNull() const { return (mPointer != nullptr); } operator const Type*() const { return mPointer; } bool operator !=(const Type* ptr) const { return (mPointer != ptr); } @@ -239,6 +293,17 @@ public: return *this; } + LLConstPointer<Type>& operator =(LLConstPointer<Type>&& ptr) + { + if (mPointer != ptr.mPointer) + { + unref(); + mPointer = ptr.mPointer; + ptr.mPointer = nullptr; + } + return *this; + } + // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. template<typename Subclass> LLConstPointer<Type>& operator =(const LLConstPointer<Subclass>& ptr) @@ -252,6 +317,18 @@ public: return *this; } + template<typename Subclass> + LLConstPointer<Type>& operator =(LLConstPointer<Subclass>&& ptr) + { + if (mPointer != ptr.mPointer) + { + unref(); + mPointer = ptr.mPointer; + ptr.mPointer = nullptr; + } + return *this; + } + // Just exchange the pointers, which will not change the reference counts. static void swap(LLConstPointer<Type>& a, LLConstPointer<Type>& b) { @@ -278,9 +355,9 @@ protected: if (mPointer) { const Type *temp = mPointer; - mPointer = NULL; + mPointer = nullptr; temp->unref(); - if (mPointer != NULL) + if (mPointer != nullptr) { LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL; unref(); @@ -313,7 +390,7 @@ public: : LLPointer<Type>(ptr), mStayUnique(false) { - if (ptr.mForceUnique) + if (ptr.mStayUnique) { makeUnique(); } diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index a54408a852..a528cc7fd8 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -74,9 +74,6 @@ #ifndef LL_MSVC #define LL_MSVC 1 #endif - #if _MSC_VER < 1400 - #define LL_MSVC7 //Visual C++ 2003 or earlier - #endif #endif // Deal with minor differences on Unixy OSes. @@ -120,44 +117,18 @@ #endif // LL_WINDOWS -// Deal with VC6 problems +// Deal with VC++ problems #if LL_MSVC -#pragma warning( 3 : 4701 ) // "local variable used without being initialized" Treat this as level 3, not level 4. -#pragma warning( 3 : 4702 ) // "unreachable code" Treat this as level 3, not level 4. -#pragma warning( 3 : 4189 ) // "local variable initialized but not referenced" Treat this as level 3, not level 4. -//#pragma warning( 3 : 4018 ) // "signed/unsigned mismatch" Treat this as level 3, not level 4. -#pragma warning( 3 : 4263 ) // 'function' : member function does not override any base class virtual member function -#pragma warning( 3 : 4264 ) // "'virtual_function' : no override available for virtual member function from base 'class'; function is hidden" -#pragma warning( 3 : 4265 ) // "class has virtual functions, but destructor is not virtual" -#pragma warning( 3 : 4266 ) // 'function' : no override available for virtual member function from base 'type'; function is hidden -#pragma warning (disable : 4180) // qualifier applied to function type has no meaning; ignored -//#pragma warning( disable : 4284 ) // silly MS warning deep inside their <map> include file - -#if ADDRESS_SIZE == 64 -// That one is all over the place for x64 builds. -#pragma warning( disable : 4267 ) // 'var' : conversion from 'size_t' to 'type', possible loss of data) +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS // disable warnings for methods considered unsafe +#endif +#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS +#define _WINSOCK_DEPRECATED_NO_WARNINGS // disable deprecated WinSock API warnings #endif - -#pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation. -#pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning) -#pragma warning( disable : 4996 ) // warning: deprecated - -// Linker optimization with "extern template" generates these warnings -#pragma warning( disable : 4231 ) // nonstandard extension used : 'extern' before template explicit instantiation -#pragma warning( disable : 4506 ) // no definition for inline function // level 4 warnings that we need to disable: -#pragma warning (disable : 4100) // unreferenced formal parameter -#pragma warning (disable : 4127) // conditional expression is constant (e.g. while(1) ) -#pragma warning (disable : 4244) // possible loss of data on conversions -#pragma warning (disable : 4396) // the inline specifier cannot be used when a friend declaration refers to a specialization of a function template -#pragma warning (disable : 4512) // assignment operator could not be generated -#pragma warning (disable : 4706) // assignment within conditional (even if((x = y)) ) - #pragma warning (disable : 4251) // member needs to have dll-interface to be used by clients of class #pragma warning (disable : 4275) // non dll-interface class used as base for dll-interface class -#pragma warning (disable : 4018) // '<' : signed/unsigned mismatch - #endif // LL_MSVC #if LL_WINDOWS diff --git a/indra/llcommon/llpriqueuemap.h b/indra/llcommon/llpriqueuemap.h index 79934d094b..2bdd39aac2 100644 --- a/indra/llcommon/llpriqueuemap.h +++ b/indra/llcommon/llpriqueuemap.h @@ -47,17 +47,17 @@ public: { if (mPriority > b.mPriority) { - return TRUE; + return true; } if (mPriority < b.mPriority) { - return FALSE; + return false; } if (mData > b.mData) { - return TRUE; + return true; } - return FALSE; + return false; } F32 mPriority; @@ -90,18 +90,18 @@ public: mMap.insert(pqm_pair(LLPQMKey<DATA_TYPE>(priority, data), data)); } - BOOL pop(DATA_TYPE *datap) + bool pop(DATA_TYPE *datap) { pqm_iter iter; iter = mMap.begin(); if (iter == mMap.end()) { - return FALSE; + return false; } *datap = (*(iter)).second; mMap.erase(iter); - return TRUE; + return true; } void reprioritize(const F32 new_priority, DATA_TYPE data) diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp index 2208b33b94..912e596c3f 100644 --- a/indra/llcommon/llprocess.cpp +++ b/indra/llcommon/llprocess.cpp @@ -561,9 +561,9 @@ LLProcess::LLProcess(const LLSDOrParams& params): // IQA-490, CHOP-900: On Windows, ask APR to jump through hoops to // constrain the set of handles passed to the child process. Before we // changed to APR, the Windows implementation of LLProcessLauncher called - // CreateProcess(bInheritHandles=FALSE), meaning to pass NO open handles + // CreateProcess(bInheritHandles=false), meaning to pass NO open handles // to the child process. Now that we support pipes, though, we must allow - // apr_proc_create() to pass bInheritHandles=TRUE. But without taking + // apr_proc_create() to pass bInheritHandles=true. But without taking // special pains, that causes trouble in a number of ways, due to the fact // that the viewer is constantly opening and closing files -- most of // which CreateProcess() passes to every child process! diff --git a/indra/llcommon/llprofiler.h b/indra/llcommon/llprofiler.h index af5e5777bf..732436cc4f 100644 --- a/indra/llcommon/llprofiler.h +++ b/indra/llcommon/llprofiler.h @@ -84,7 +84,7 @@ extern thread_local bool gProfilerEnabled; // #define TRACY_NO_BROADCAST 1 // #define TRACY_ONLY_LOCALHOST 1 #define TRACY_ONLY_IPV4 1 - #include "Tracy.hpp" + #include "tracy/Tracy.hpp" // Enable OpenGL profiling #define LL_PROFILER_ENABLE_TRACY_OPENGL 0 @@ -162,7 +162,7 @@ extern thread_local bool gProfilerEnabled; #define LL_LABEL_OBJECT_GL(type, name, length, label) -#if LL_PROFILER_CONFIGURATION > 1 +#if !LL_DARWIN && LL_PROFILER_CONFIGURATION > 1 #define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size) #define LL_PROFILE_FREE(ptr) TracyFree(ptr) #else diff --git a/indra/llcommon/llprofilercategories.h b/indra/llcommon/llprofilercategories.h index 617431f629..1c4f0f5624 100644 --- a/indra/llcommon/llprofilercategories.h +++ b/indra/llcommon/llprofilercategories.h @@ -1,5 +1,5 @@ /** - * @file llprofiler_ategories.h + * @file llprofilercategories.h * @brief Profiling categories to minimize Tracy memory usage when viewing captures. * * $LicenseInfo:firstyear=2022&license=viewerlgpl$ @@ -33,7 +33,7 @@ // LL_PROFILER_CATEGORY_ENABLE_DRAWPOOL // LL_PROFILER_CATEGORY_ENABLE_LLSD // LL_PROFILER_CATEGORY_ENABLE_MEMORY -// LL_PROFILER_CATEGORY_ENABLE_SHADERS +// LL_PROFILER_CATEGORY_ENABLE_SHADER // // NOTE: You can still manually use: // LL_PROFILE_ZONE_SCOPED(); @@ -67,6 +67,8 @@ #define LL_PROFILER_CATEGORY_ENABLE_VERTEX 1 #define LL_PROFILER_CATEGORY_ENABLE_VOLUME 1 #define LL_PROFILER_CATEGORY_ENABLE_WIN32 1 +#define LL_PROFILER_CATEGORY_ENABLE_GLTF 1 +#define LL_PROFILER_CATEGORY_ENABLE_VOICE 1 #if LL_PROFILER_CATEGORY_ENABLE_APP #define LL_PROFILE_ZONE_NAMED_CATEGORY_APP LL_PROFILE_ZONE_NAMED @@ -276,5 +278,20 @@ #define LL_PROFILE_ZONE_SCOPED_CATEGORY_WIN32 #endif +#if LL_PROFILER_CATEGORY_ENABLE_GLTF + #define LL_PROFILE_ZONE_NAMED_CATEGORY_GLTF LL_PROFILE_ZONE_NAMED + #define LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF LL_PROFILE_ZONE_SCOPED +#else + #define LL_PROFILE_ZONE_NAMED_CATEGORY_GLTF(name) + #define LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF +#endif +#if LL_PROFILER_CATEGORY_ENABLE_VOICE + #define LL_PROFILE_ZONE_NAMED_CATEGORY_VOICE LL_PROFILE_ZONE_NAMED + #define LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE LL_PROFILE_ZONE_SCOPED +#else + #define LL_PROFILE_ZONE_NAMED_CATEGORY_VOICE(name) + #define LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE +#endif + #endif // LL_PROFILER_CATEGORIES_H diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index aaf13ac796..1c4ac5a7bf 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -37,9 +37,9 @@ // MAIN THREAD LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool should_pause) : LLThread(name), - mIdleThread(TRUE), + mIdleThread(true), mNextHandle(0), - mStarted(FALSE), + mStarted(false), mThreaded(threaded), mRequestQueue(name, 1024 * 1024) { @@ -131,7 +131,7 @@ size_t LLQueuedThread::update(F32 max_time_ms) if (!mThreaded) { startThread(); - mStarted = TRUE; + mStarted = true; } } return updateQueue(max_time_ms); @@ -149,9 +149,9 @@ size_t LLQueuedThread::updateQueue(F32 max_time_ms) mRequestQueue.post([=]() { LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qt - update"); - mIdleThread = FALSE; + mIdleThread = false; threadedUpdate(); - mIdleThread = TRUE; + mIdleThread = true; } ); } @@ -210,7 +210,7 @@ void LLQueuedThread::waitOnPending() // MAIN thread void LLQueuedThread::printQueueStats() { - U32 size = mRequestQueue.size(); + auto size = mRequestQueue.size(); if (size > 0) { LL_INFOS() << llformat("Pending Requests:%d ", mRequestQueue.size()) << LL_ENDL; @@ -392,7 +392,7 @@ void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req) { LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; - mIdleThread = FALSE; + mIdleThread = false; //threadedUpdate(); // Get next request from pool @@ -483,7 +483,7 @@ void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req) if (sleep_time.count() > 0) { - ms_sleep(sleep_time.count()); + ms_sleep((U32)sleep_time.count()); } } processRequest(req); @@ -494,7 +494,7 @@ void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req) } } - mIdleThread = TRUE; + mIdleThread = true; } // virtual @@ -513,7 +513,7 @@ void LLQueuedThread::run() // call checPause() immediately so we don't try to do anything before the class is fully constructed checkPause(); startThread(); - mStarted = TRUE; + mStarted = true; /*while (1) @@ -522,7 +522,7 @@ void LLQueuedThread::run() // this will block on the condition until runCondition() returns true, the thread is unpaused, or the thread leaves the RUNNING state. checkPause(); - mIdleThread = FALSE; + mIdleThread = false; threadedUpdate(); @@ -531,7 +531,7 @@ void LLQueuedThread::run() if (pending_work == 0) { //LL_PROFILE_ZONE_NAMED("LLQueuedThread - sleep"); - mIdleThread = TRUE; + mIdleThread = true; //ms_sleep(1); } //LLThread::yield(); // thread should yield after each request diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h index 339299f081..02d3a96fcc 100644 --- a/indra/llcommon/llqueuedthread.h +++ b/indra/llcommon/llqueuedthread.h @@ -144,7 +144,7 @@ public: void printQueueStats(); virtual size_t getPending(); - bool getThreaded() { return mThreaded ? true : false; } + bool getThreaded() { return mThreaded; } // Request accessors status_t getRequestStatus(handle_t handle); @@ -159,8 +159,8 @@ public: bool check(); 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() + 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() 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; diff --git a/indra/llcommon/llrand.cpp b/indra/llcommon/llrand.cpp index 25d75af568..2c51e6f07f 100644 --- a/indra/llcommon/llrand.cpp +++ b/indra/llcommon/llrand.cpp @@ -85,7 +85,7 @@ inline F32 ll_internal_random<F32>() // Per Monty, it's important to clamp using the correct fmodf() rather // than expanding to F64 for fmod() and then truncating back to F32. Prior // to this change, we were getting sporadic ll_frand() == 1.0 results. - F32 rv{ narrow<F32>(gRandomGenerator()) }; + F32 rv{ narrow<F64>(gRandomGenerator()) }; if(!((rv >= 0.0f) && (rv < 1.0f))) return fmodf(rv, 1.0f); return rv; } diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h index 33c9e956b1..3a253d8fa6 100644 --- a/indra/llcommon/llrefcount.h +++ b/indra/llcommon/llrefcount.h @@ -89,13 +89,6 @@ private: class LL_COMMON_API LLThreadSafeRefCount { -public: - static void initThreadSafeRefCount(); // creates sMutex - static void cleanupThreadSafeRefCount(); // destroys sMutex - -private: - static LLMutex* sMutex; - protected: virtual ~LLThreadSafeRefCount(); // use unref() diff --git a/indra/llcommon/llregistry.h b/indra/llcommon/llregistry.h index 55dabd57a2..35335e1213 100644 --- a/indra/llcommon/llregistry.h +++ b/indra/llcommon/llregistry.h @@ -60,7 +60,7 @@ public: bool add(ref_const_key_t key, ref_const_value_t value) { - if (mMap.insert(std::make_pair(key, value)).second == false) + if (!mMap.insert(std::make_pair(key, value)).second) { LL_WARNS() << "Tried to register " << key << " but it was already registered!" << LL_ENDL; return false; diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp index 663ceac22b..77fe545c3f 100644 --- a/indra/llcommon/llsd.cpp +++ b/indra/llcommon/llsd.cpp @@ -30,6 +30,7 @@ #include "linden_common.h" #include "llsd.h" +#include "llbase64.h" #include "llerror.h" #include "../llmath/llmath.h" #include "llformat.h" @@ -105,6 +106,9 @@ public: static void reset(Impl*& var, Impl* impl); ///< safely set var to refer to the new impl (possibly shared) + static void move(Impl*& var, Impl*& impl); + ///< safely move impl from one object to another + static Impl& safe( Impl*); static const Impl& safe(const Impl*); ///< since a NULL Impl* is used for undefined, this ensures there is @@ -122,11 +126,17 @@ public: virtual void assign(Impl*& var, LLSD::Boolean); virtual void assign(Impl*& var, LLSD::Integer); virtual void assign(Impl*& var, LLSD::Real); + virtual void assign(Impl*& var, const char*); virtual void assign(Impl*& var, const LLSD::String&); virtual void assign(Impl*& var, const LLSD::UUID&); virtual void assign(Impl*& var, const LLSD::Date&); virtual void assign(Impl*& var, const LLSD::URI&); virtual void assign(Impl*& var, const LLSD::Binary&); + virtual void assign(Impl*& var, LLSD::String&&); + virtual void assign(Impl*& var, LLSD::UUID&&); + virtual void assign(Impl*& var, LLSD::Date&&); + virtual void assign(Impl*& var, LLSD::URI&&); + virtual void assign(Impl*& var, LLSD::Binary&&); ///< If the receiver is the right type and unshared, these are simple // data assignments, othewise the default implementation handless // constructing the proper Impl subclass @@ -142,11 +152,13 @@ public: virtual const String& asStringRef() const { static const std::string empty; return empty; } - virtual bool has(const String&) const { return false; } - virtual LLSD get(const String&) const { return LLSD(); } + virtual String asXMLRPCValue() const { return "<nil/>"; } + + virtual bool has(std::string_view) const { return false; } + virtual LLSD get(std::string_view) const { return LLSD(); } virtual LLSD getKeys() const { return LLSD::emptyArray(); } virtual void erase(const String&) { } - virtual const LLSD& ref(const String&) const{ return undef(); } + virtual const LLSD& ref(std::string_view) const{ return undef(); } virtual size_t size() const { return 0; } virtual LLSD get(size_t) const { return LLSD(); } @@ -182,7 +194,7 @@ namespace LLSDUnnamedNamespace namespace #endif { - template<LLSD::Type T, class Data, class DataRef = Data> + template<LLSD::Type T, class Data, class DataRef = Data, class DataMove = Data> class ImplBase : public LLSD::Impl ///< This class handles most of the work for a subclass of Impl // for a given simple data type. Subclasses of this provide the @@ -195,6 +207,7 @@ namespace public: ImplBase(DataRef value) : mValue(value) { } + ImplBase(DataMove value) : mValue(std::move(value)) { } virtual LLSD::Type type() const { return T; } @@ -209,11 +222,21 @@ namespace mValue = value; } } + virtual void assign(LLSD::Impl*& var, DataMove value) { + if (shared()) + { + Impl::assign(var, std::move(value)); + } + else + { + mValue = std::move(value); + } + } }; - class ImplBoolean - : public ImplBase<LLSD::TypeBoolean, LLSD::Boolean> + class ImplBoolean final + : public ImplBase<LLSD::TypeBoolean, LLSD::Boolean, LLSD::Boolean, LLSD::Boolean&&> { public: ImplBoolean(LLSD::Boolean v) : Base(v) { } @@ -222,6 +245,8 @@ namespace virtual LLSD::Integer asInteger() const { return mValue ? 1 : 0; } virtual LLSD::Real asReal() const { return mValue ? 1 : 0; } virtual LLSD::String asString() const; + + virtual LLSD::String asXMLRPCValue() const { return mValue ? "<boolean>1</boolean>" : "<boolean>0</boolean>"; } }; LLSD::String ImplBoolean::asString() const @@ -233,8 +258,8 @@ namespace { return mValue ? "true" : ""; } - class ImplInteger - : public ImplBase<LLSD::TypeInteger, LLSD::Integer> + class ImplInteger final + : public ImplBase<LLSD::TypeInteger, LLSD::Integer, LLSD::Integer, LLSD::Integer&&> { public: ImplInteger(LLSD::Integer v) : Base(v) { } @@ -243,14 +268,16 @@ namespace virtual LLSD::Integer asInteger() const { return mValue; } virtual LLSD::Real asReal() const { return mValue; } virtual LLSD::String asString() const; + + virtual LLSD::String asXMLRPCValue() const { return "<int>" + std::to_string(mValue) + "</int>"; } }; LLSD::String ImplInteger::asString() const { return llformat("%d", mValue); } - class ImplReal - : public ImplBase<LLSD::TypeReal, LLSD::Real> + class ImplReal final + : public ImplBase<LLSD::TypeReal, LLSD::Real, LLSD::Real, LLSD::Real&&> { public: ImplReal(LLSD::Real v) : Base(v) { } @@ -259,6 +286,8 @@ namespace virtual LLSD::Integer asInteger() const; virtual LLSD::Real asReal() const { return mValue; } virtual LLSD::String asString() const; + + virtual LLSD::String asXMLRPCValue() const { return "<double>" + std::to_string(mValue) + "</double>"; } }; LLSD::Boolean ImplReal::asBoolean() const @@ -271,11 +300,12 @@ namespace { return llformat("%lg", mValue); } - class ImplString - : public ImplBase<LLSD::TypeString, LLSD::String, const LLSD::String&> + class ImplString final + : public ImplBase<LLSD::TypeString, LLSD::String, const LLSD::String&, LLSD::String&&> { public: ImplString(const LLSD::String& v) : Base(v) { } + ImplString(LLSD::String&& v) : Base(std::move(v)) {} virtual LLSD::Boolean asBoolean() const { return !mValue.empty(); } virtual LLSD::Integer asInteger() const; @@ -286,9 +316,24 @@ namespace virtual LLSD::URI asURI() const { return LLURI(mValue); } virtual size_t size() const { return mValue.size(); } virtual const LLSD::String& asStringRef() const { return mValue; } + + virtual LLSD::String asXMLRPCValue() const { return "<string>" + LLStringFn::xml_encode(mValue) + "</string>"; } + + using LLSD::Impl::assign; // Unhiding base class virtuals... + virtual void assign(LLSD::Impl*& var, const char* value) + { + if (shared()) + { + Impl::assign(var, value); + } + else + { + mValue = value; + } + } }; - LLSD::Integer ImplString::asInteger() const + LLSD::Integer ImplString::asInteger() const { // This must treat "1.23" not as an error, but as a number, which is // then truncated down to an integer. Hence, this code doesn't call @@ -298,7 +343,7 @@ namespace return (int)asReal(); } - LLSD::Real ImplString::asReal() const + LLSD::Real ImplString::asReal() const { F64 v = 0.0; std::istringstream i_stream(mValue); @@ -315,25 +360,32 @@ namespace } - class ImplUUID - : public ImplBase<LLSD::TypeUUID, LLSD::UUID, const LLSD::UUID&> + class ImplUUID final + : public ImplBase<LLSD::TypeUUID, LLSD::UUID, const LLSD::UUID&, LLSD::UUID&&> { public: ImplUUID(const LLSD::UUID& v) : Base(v) { } + ImplUUID(LLSD::UUID&& v) : Base(std::move(v)) { } virtual LLSD::String asString() const{ return mValue.asString(); } virtual LLSD::UUID asUUID() const { return mValue; } + + virtual LLSD::String asXMLRPCValue() const { return "<string>" + mValue.asString() + "</string>"; } }; - class ImplDate - : public ImplBase<LLSD::TypeDate, LLSD::Date, const LLSD::Date&> + class ImplDate final + : public ImplBase<LLSD::TypeDate, LLSD::Date, const LLSD::Date&, LLSD::Date&&> { public: ImplDate(const LLSD::Date& v) - : ImplBase<LLSD::TypeDate, LLSD::Date, const LLSD::Date&>(v) + : ImplBase(v) { } + ImplDate(LLSD::Date&& v) + : ImplBase(std::move(v)) + { } + virtual LLSD::Integer asInteger() const { return (LLSD::Integer)(mValue.secondsSinceEpoch()); @@ -344,34 +396,42 @@ namespace } virtual LLSD::String asString() const{ return mValue.asString(); } virtual LLSD::Date asDate() const { return mValue; } + + virtual LLSD::String asXMLRPCValue() const { return "<dateTime.iso8601>" + mValue.toHTTPDateString("%FT%T") + "</dateTime.iso8601>"; } }; - class ImplURI - : public ImplBase<LLSD::TypeURI, LLSD::URI, const LLSD::URI&> + class ImplURI final + : public ImplBase<LLSD::TypeURI, LLSD::URI, const LLSD::URI&, LLSD::URI&&> { public: ImplURI(const LLSD::URI& v) : Base(v) { } + ImplURI(LLSD::URI&& v) : Base(std::move(v)) { } virtual LLSD::String asString() const{ return mValue.asString(); } virtual LLSD::URI asURI() const { return mValue; } + + virtual LLSD::String asXMLRPCValue() const { return "<string>" + LLStringFn::xml_encode(mValue.asString()) + "</string>"; } }; - class ImplBinary - : public ImplBase<LLSD::TypeBinary, LLSD::Binary, const LLSD::Binary&> + class ImplBinary final + : public ImplBase<LLSD::TypeBinary, LLSD::Binary, const LLSD::Binary&, LLSD::Binary&&> { public: ImplBinary(const LLSD::Binary& v) : Base(v) { } + ImplBinary(LLSD::Binary&& v) : Base(std::move(v)) { } virtual const LLSD::Binary& asBinary() const{ return mValue; } + + virtual LLSD::String asXMLRPCValue() const { return "<base64>" + LLBase64::encode(mValue.data(), mValue.size()) + "</base64>"; } }; - class ImplMap : public LLSD::Impl + class ImplMap final : public LLSD::Impl { private: - typedef std::map<LLSD::String, LLSD> DataMap; + typedef std::map<LLSD::String, LLSD, std::less<>> DataMap; DataMap mData; @@ -387,17 +447,30 @@ namespace virtual LLSD::Boolean asBoolean() const { return !mData.empty(); } - virtual bool has(const LLSD::String&) const; + virtual LLSD::String asXMLRPCValue() const + { + std::ostringstream os; + os << "<struct>"; + for (const auto& it : mData) + { + os << "<member><name>" << LLStringFn::xml_encode(it.first) << "</name>" + << it.second.asXMLRPCValue() << "</member>"; + } + os << "</struct>"; + return os.str(); + } + + virtual bool has(std::string_view) const; using LLSD::Impl::get; // Unhiding get(size_t) using LLSD::Impl::erase; // Unhiding erase(size_t) using LLSD::Impl::ref; // Unhiding ref(size_t) - virtual LLSD get(const LLSD::String&) const; + virtual LLSD get(std::string_view) const; virtual LLSD getKeys() const; - void insert(const LLSD::String& k, const LLSD& v); + void insert(std::string_view k, const LLSD& v); virtual void erase(const LLSD::String&); - LLSD& ref(const LLSD::String&); - virtual const LLSD& ref(const LLSD::String&) const; + LLSD& ref(std::string_view); + virtual const LLSD& ref(std::string_view) const; virtual size_t size() const { return mData.size(); } @@ -425,14 +498,14 @@ namespace } } - bool ImplMap::has(const LLSD::String& k) const + bool ImplMap::has(const std::string_view k) const { LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; DataMap::const_iterator i = mData.find(k); return i != mData.end(); } - LLSD ImplMap::get(const LLSD::String& k) const + LLSD ImplMap::get(const std::string_view k) const { LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; DataMap::const_iterator i = mData.find(k); @@ -452,10 +525,10 @@ namespace return keys; } - void ImplMap::insert(const LLSD::String& k, const LLSD& v) + void ImplMap::insert(std::string_view k, const LLSD& v) { LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; - mData.insert(DataMap::value_type(k, v)); + mData.emplace(k, v); } void ImplMap::erase(const LLSD::String& k) @@ -464,15 +537,21 @@ namespace mData.erase(k); } - LLSD& ImplMap::ref(const LLSD::String& k) + LLSD& ImplMap::ref(std::string_view k) { - return mData[k]; + DataMap::iterator i = mData.lower_bound(k); + if (i == mData.end() || mData.key_comp()(k, i->first)) + { + return mData.emplace_hint(i, std::make_pair(k, LLSD()))->second; + } + + return i->second; } - const LLSD& ImplMap::ref(const LLSD::String& k) const + const LLSD& ImplMap::ref(std::string_view k) const { DataMap::const_iterator i = mData.lower_bound(k); - if (i == mData.end() || mData.key_comp()(k, i->first)) + if (i == mData.end() || mData.key_comp()(k, i->first)) { return undef(); } @@ -500,7 +579,7 @@ namespace { //std::cout << " " << (*iter).first << ": " << (*iter).second << std::endl; Impl::calcStats((*iter).second, type_counts, share_counts); - iter++; + ++iter; } // Add in the values for this map @@ -511,7 +590,7 @@ namespace class ImplArray : public LLSD::Impl { private: - typedef std::vector<LLSD> DataVector; + typedef std::vector<LLSD> DataVector; DataVector mData; @@ -527,6 +606,18 @@ namespace virtual LLSD::Boolean asBoolean() const { return !mData.empty(); } + virtual LLSD::String asXMLRPCValue() const + { + std::ostringstream os; + os << "<array><data>"; + for (const auto& it : mData) + { + os << it.asXMLRPCValue(); + } + os << "</data></array>"; + return os.str(); + } + using LLSD::Impl::get; // Unhiding get(LLSD::String) using LLSD::Impl::erase; // Unhiding erase(LLSD::String) using LLSD::Impl::ref; // Unhiding ref(LLSD::String) @@ -647,7 +738,7 @@ namespace while (iter != endArray()) { // Add values for all items held in the array Impl::calcStats((*iter), type_counts, share_counts); - iter++; + ++iter; } // Add in the values for this array @@ -685,6 +776,16 @@ void LLSD::Impl::reset(Impl*& var, Impl* impl) var = impl; } +void LLSD::Impl::move(Impl*& var, Impl*& impl) +{ + if (var && var->mUseCount != STATIC_USAGE_COUNT && --var->mUseCount == 0) + { + delete var; // destroy var if usage falls to 0 and not static + } + var = impl; // Steal impl to var without incrementing use since this is a move + impl = nullptr; // null out old-impl pointer +} + LLSD::Impl& LLSD::Impl::safe(Impl* impl) { static Impl theUndefined(STATIC_USAGE_COUNT); @@ -738,6 +839,11 @@ void LLSD::Impl::assign(Impl*& var, LLSD::Real v) reset(var, new ImplReal(v)); } +void LLSD::Impl::assign(Impl*& var, const char* v) +{ + reset(var, new ImplString(v)); +} + void LLSD::Impl::assign(Impl*& var, const LLSD::String& v) { reset(var, new ImplString(v)); @@ -763,6 +869,31 @@ void LLSD::Impl::assign(Impl*& var, const LLSD::Binary& v) reset(var, new ImplBinary(v)); } +void LLSD::Impl::assign(Impl*& var, LLSD::String&& v) +{ + reset(var, new ImplString(std::move(v))); +} + +void LLSD::Impl::assign(Impl*& var, LLSD::UUID&& v) +{ + reset(var, new ImplUUID(std::move(v))); +} + +void LLSD::Impl::assign(Impl*& var, LLSD::Date&& v) +{ + reset(var, new ImplDate(std::move(v))); +} + +void LLSD::Impl::assign(Impl*& var, LLSD::URI&& v) +{ + reset(var, new ImplURI(std::move(v))); +} + +void LLSD::Impl::assign(Impl*& var, LLSD::Binary&& v) +{ + reset(var, new ImplBinary(std::move(v))); +} + const LLSD& LLSD::Impl::undef() { @@ -835,6 +966,9 @@ LLSD::~LLSD() { FREE_LLSD_OBJECT; Impl::reset(impl, 0) LLSD::LLSD(const LLSD& other) : impl(0) { ALLOC_LLSD_OBJECT; assign(other); } void LLSD::assign(const LLSD& other) { Impl::assign(impl, other.impl); } +LLSD::LLSD(LLSD&& other) noexcept : impl(nullptr) { ALLOC_LLSD_OBJECT; Impl::move(impl, other.impl); } +void LLSD::assign(LLSD&& other) { Impl::move(impl, other.impl); } +LLSD& LLSD::operator=(LLSD&& other) noexcept { Impl::move(impl, other.impl); return *this; } void LLSD::clear() { Impl::assignUndefined(impl); } @@ -849,6 +983,11 @@ LLSD::LLSD(const String& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); } LLSD::LLSD(const Date& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); } LLSD::LLSD(const URI& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); } LLSD::LLSD(const Binary& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); } +LLSD::LLSD(UUID&& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(std::move(v)); } +LLSD::LLSD(String&& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(std::move(v)); } +LLSD::LLSD(Date&& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(std::move(v)); } +LLSD::LLSD(URI&& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(std::move(v)); } +LLSD::LLSD(Binary&& v) : impl(0) { ALLOC_LLSD_OBJECT; assign(std::move(v)); } // Scalar Assignment void LLSD::assign(Boolean v) { safe(impl).assign(impl, v); } @@ -859,6 +998,11 @@ void LLSD::assign(const UUID& v) { safe(impl).assign(impl, v); } void LLSD::assign(const Date& v) { safe(impl).assign(impl, v); } void LLSD::assign(const URI& v) { safe(impl).assign(impl, v); } void LLSD::assign(const Binary& v) { safe(impl).assign(impl, v); } +void LLSD::assign(String&& v) { safe(impl).assign(impl, std::move(v)); } +void LLSD::assign(UUID&& v) { safe(impl).assign(impl, std::move(v)); } +void LLSD::assign(Date&& v) { safe(impl).assign(impl, std::move(v)); } +void LLSD::assign(URI&& v) { safe(impl).assign(impl, std::move(v)); } +void LLSD::assign(Binary&& v) { safe(impl).assign(impl, std::move(v)); } // Scalar Accessors LLSD::Boolean LLSD::asBoolean() const { return safe(impl).asBoolean(); } @@ -872,11 +1016,13 @@ const LLSD::Binary& LLSD::asBinary() const { return safe(impl).asBinary(); } const LLSD::String& LLSD::asStringRef() const { return safe(impl).asStringRef(); } +LLSD::String LLSD::asXMLRPCValue() const { return "<value>" + safe(impl).asXMLRPCValue() + "</value>"; } + // const char * helpers LLSD::LLSD(const char* v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); } void LLSD::assign(const char* v) { - if(v) assign(std::string(v)); + if(v) safe(impl).assign(impl, v); else assign(std::string()); } @@ -888,24 +1034,24 @@ LLSD LLSD::emptyMap() return v; } -bool LLSD::has(const String& k) const { return safe(impl).has(k); } -LLSD LLSD::get(const String& k) const { return safe(impl).get(k); } +bool LLSD::has(const std::string_view k) const { return safe(impl).has(k); } +LLSD LLSD::get(const std::string_view k) const { return safe(impl).get(k); } LLSD LLSD::getKeys() const { return safe(impl).getKeys(); } -void LLSD::insert(const String& k, const LLSD& v) { makeMap(impl).insert(k, v); } +void LLSD::insert(std::string_view k, const LLSD& v) { makeMap(impl).insert(k, v); } -LLSD& LLSD::with(const String& k, const LLSD& v) +LLSD& LLSD::with(std::string_view k, const LLSD& v) { makeMap(impl).insert(k, v); return *this; } void LLSD::erase(const String& k) { makeMap(impl).erase(k); } -LLSD& LLSD::operator[](const String& k) +LLSD& LLSD::operator[](const std::string_view k) { LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; return makeMap(impl).ref(k); } -const LLSD& LLSD::operator[](const String& k) const +const LLSD& LLSD::operator[](const std::string_view k) const { LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; return safe(impl).ref(k); diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h index a5e735b561..d2b3548831 100644 --- a/indra/llcommon/llsd.h +++ b/indra/llcommon/llsd.h @@ -161,6 +161,13 @@ public: //@} + /** @name Movable */ + //@{ + LLSD(LLSD&& other) noexcept; + void assign(LLSD&& other); + LLSD& operator=(LLSD&& other) noexcept; + //@} + void clear(); ///< resets to Undefined @@ -188,6 +195,11 @@ public: LLSD(const Date&); LLSD(const URI&); LLSD(const Binary&); + LLSD(String&&); + LLSD(UUID&&); + LLSD(Date&&); + LLSD(URI&&); + LLSD(Binary&&); //@} /** @name Convenience Constructors */ @@ -215,6 +227,11 @@ public: void assign(const Date&); void assign(const URI&); void assign(const Binary&); + void assign(String&&); + void assign(UUID&&); + void assign(Date&&); + void assign(URI&&); + void assign(Binary&&); LLSD& operator=(Boolean v) { assign(v); return *this; } LLSD& operator=(Integer v) { assign(v); return *this; } @@ -224,6 +241,11 @@ public: LLSD& operator=(const Date& v) { assign(v); return *this; } LLSD& operator=(const URI& v) { assign(v); return *this; } LLSD& operator=(const Binary& v) { assign(v); return *this; } + LLSD& operator=(String&& v) { assign(std::move(v)); return *this; } + LLSD& operator=(UUID&& v) { assign(std::move(v)); return *this; } + LLSD& operator=(Date&& v) { assign(std::move(v)); return *this; } + LLSD& operator=(URI&& v) { assign(std::move(v)); return *this; } + LLSD& operator=(Binary&& v) { assign(std::move(v)); return *this; } //@} /** @@ -259,10 +281,14 @@ public: UUID asUUID() const; Date asDate() const; URI asURI() const; - const Binary& asBinary() const; + const Binary& asBinary() const; // asStringRef on any non-string type will return a ref to an empty string. - const String& asStringRef() const; + const String& asStringRef() const; + + // Return "<value><((type))>((scalar value or recursive calls))</((type))></value>" + // See http://xmlrpc.com/spec.md + String asXMLRPCValue() const; operator Boolean() const { return asBoolean(); } operator Integer() const { return asInteger(); } @@ -275,7 +301,7 @@ public: // This is needed because most platforms do not automatically // convert the boolean negation as a bool in an if statement. - bool operator!() const {return !asBoolean();} + bool operator!() const { return !asBoolean(); } //@} /** @name Character Pointer Helpers @@ -292,24 +318,22 @@ public: //@{ static LLSD emptyMap(); - bool has(const String&) const; - LLSD get(const String&) const; + bool has(const std::string_view) const; + LLSD get(const std::string_view) const; LLSD getKeys() const; // Return an LLSD array with keys as strings - void insert(const String&, const LLSD&); + void insert(std::string_view, const LLSD&); void erase(const String&); - LLSD& with(const String&, const LLSD&); + LLSD& with(std::string_view, const LLSD&); - LLSD& operator[](const String&); + LLSD& operator[](const std::string_view); LLSD& operator[](const char* c) { - LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; - return (*this)[String(c)]; + return c ? (*this)[std::string_view(c)] : *this; } - const LLSD& operator[](const String&) const; + const LLSD& operator[](const std::string_view) const; const LLSD& operator[](const char* c) const { - LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; - return (*this)[String(c)]; + return c ? (*this)[std::string_view(c)] : *this; } //@} diff --git a/indra/llcommon/llsdjson.cpp b/indra/llcommon/llsdjson.cpp index bb2b8681f7..e95d2e6c1c 100644 --- a/indra/llcommon/llsdjson.cpp +++ b/indra/llcommon/llsdjson.cpp @@ -31,46 +31,56 @@ #include "llsdjson.h" +#include "llsdutil.h" #include "llerror.h" #include "../llmath/llmath.h" +#if LL_WINDOWS +#pragma warning (push) +#pragma warning (disable : 4702) // compiler thinks unreachable code +#endif +#include <boost/json/src.hpp> +#if LL_WINDOWS +#pragma warning (pop) +#endif + + + //========================================================================= -LLSD LlsdFromJson(const Json::Value &val) +LLSD LlsdFromJson(const boost::json::value& val) { LLSD result; - switch (val.type()) + switch (val.kind()) { default: - case Json::nullValue: - break; - case Json::intValue: - result = LLSD(static_cast<LLSD::Integer>(val.asInt())); + case boost::json::kind::null: break; - case Json::uintValue: - result = LLSD(static_cast<LLSD::Integer>(val.asUInt())); + case boost::json::kind::int64: + case boost::json::kind::uint64: + result = LLSD(val.to_number<int64_t>()); break; - case Json::realValue: - result = LLSD(static_cast<LLSD::Real>(val.asDouble())); + case boost::json::kind::double_: + result = LLSD(val.to_number<double>()); break; - case Json::stringValue: - result = LLSD(static_cast<LLSD::String>(val.asString())); + case boost::json::kind::string: + result = LLSD(boost::json::value_to<std::string>(val)); break; - case Json::booleanValue: - result = LLSD(static_cast<LLSD::Boolean>(val.asBool())); + case boost::json::kind::bool_: + result = LLSD(val.as_bool()); break; - case Json::arrayValue: + case boost::json::kind::array: result = LLSD::emptyArray(); - for (Json::ValueConstIterator it = val.begin(); it != val.end(); ++it) + for (const auto &element : val.as_array()) { - result.append(LlsdFromJson((*it))); + result.append(LlsdFromJson(element)); } break; - case Json::objectValue: + case boost::json::kind::object: result = LLSD::emptyMap(); - for (Json::ValueConstIterator it = val.begin(); it != val.end(); ++it) + for (const auto& element : val.as_object()) { - result[it.memberName()] = LlsdFromJson((*it)); + result[element.key()] = LlsdFromJson(element.value()); } break; } @@ -78,44 +88,48 @@ LLSD LlsdFromJson(const Json::Value &val) } //========================================================================= -Json::Value LlsdToJson(const LLSD &val) +boost::json::value LlsdToJson(const LLSD &val) { - Json::Value result; + boost::json::value result; switch (val.type()) { case LLSD::TypeUndefined: - result = Json::Value::null; + result = nullptr; break; case LLSD::TypeBoolean: - result = Json::Value(static_cast<bool>(val.asBoolean())); + result = val.asBoolean(); break; case LLSD::TypeInteger: - result = Json::Value(static_cast<int>(val.asInteger())); + result = val.asInteger(); break; case LLSD::TypeReal: - result = Json::Value(static_cast<double>(val.asReal())); + result = val.asReal(); break; case LLSD::TypeURI: case LLSD::TypeDate: case LLSD::TypeUUID: case LLSD::TypeString: - result = Json::Value(val.asString()); + result = val.asString(); break; case LLSD::TypeMap: - result = Json::Value(Json::objectValue); - for (LLSD::map_const_iterator it = val.beginMap(); it != val.endMap(); ++it) + { + boost::json::object& obj = result.emplace_object(); + for (const auto& llsd_dat : llsd::inMap(val)) { - result[it->first] = LlsdToJson(it->second); + obj[llsd_dat.first] = LlsdToJson(llsd_dat.second); } break; + } case LLSD::TypeArray: - result = Json::Value(Json::arrayValue); - for (LLSD::array_const_iterator it = val.beginArray(); it != val.endArray(); ++it) + { + boost::json::array& json_array = result.emplace_array(); + for (const auto& llsd_dat : llsd::inArray(val)) { - result.append(LlsdToJson(*it)); + json_array.push_back(LlsdToJson(llsd_dat)); } break; + } case LLSD::TypeBinary: default: LL_ERRS("LlsdToJson") << "Unsupported conversion to JSON from LLSD type (" << val.type() << ")." << LL_ENDL; diff --git a/indra/llcommon/llsdjson.h b/indra/llcommon/llsdjson.h index 79bf2c56fa..415bbf4821 100644 --- a/indra/llcommon/llsdjson.h +++ b/indra/llcommon/llsdjson.h @@ -34,7 +34,7 @@ #include "stdtypes.h" #include "llsd.h" -#include "json/value.h" +#include <boost/json.hpp> /// Convert a parsed JSON structure into LLSD maintaining member names and /// array indexes. @@ -53,7 +53,7 @@ /// /// For maps and arrays child entries will be converted and added to the structure. /// Order is preserved for an array but not for objects. -LLSD LlsdFromJson(const Json::Value &val); +LLSD LlsdFromJson(const boost::json::value &val); /// Convert an LLSD object into Parsed JSON object maintaining member names and /// array indexs. @@ -72,6 +72,6 @@ LLSD LlsdFromJson(const Json::Value &val); /// TypeMap | object /// TypeArray | array /// TypeBinary | unsupported -Json::Value LlsdToJson(const LLSD &val); +boost::json::value LlsdToJson(const LLSD &val); #endif // LL_LLSDJSON_H diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp index b981be4d0a..3ae153a67c 100644 --- a/indra/llcommon/llsdparam.cpp +++ b/indra/llcommon/llsdparam.cpp @@ -149,7 +149,7 @@ bool LLParamSDParser::readF32(Parser& parser, void* val_ptr) { LLParamSDParser& self = static_cast<LLParamSDParser&>(parser); - *((F32*)val_ptr) = self.mCurReadSD->asReal(); + *((F32*)val_ptr) = (F32)self.mCurReadSD->asReal(); return true; } diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index d5af31a28e..37af366a20 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -231,7 +231,7 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, llssize max_bytes) } // Since we've already read 'inbuf' bytes into 'hdr_buf', prepend that // data to whatever remains in 'str'. - LLMemoryStreamBuf already(reinterpret_cast<const U8*>(hdr_buf), inbuf); + LLMemoryStreamBuf already(reinterpret_cast<const U8*>(hdr_buf), (S32)inbuf); cat_streambuf prebuff(&already, str.rdbuf()); std::istream prepend(&prebuff); #if 1 @@ -389,7 +389,7 @@ LLSDParser::~LLSDParser() S32 LLSDParser::parse(std::istream& istr, LLSD& data, llssize max_bytes, S32 max_depth) { - mCheckLimits = (LLSDSerialize::SIZE_UNLIMITED == max_bytes) ? false : true; + mCheckLimits = LLSDSerialize::SIZE_UNLIMITED != max_bytes; mMaxBytesLeft = max_bytes; return doParse(istr, data, max_depth); } @@ -475,7 +475,7 @@ LLSDNotationParser::~LLSDNotationParser() // virtual S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) const { - LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD + LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; // map: { string:object, string:object } // array: [ object, object, object ] // undef: ! @@ -566,7 +566,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) c data, NOTATION_FALSE_SERIAL, false); - if(PARSE_FAILURE == cnt) parse_count = cnt; + if(PARSE_FAILURE == cnt) parse_count = (S32)cnt; else account(cnt); } else @@ -592,7 +592,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) c if(isalpha(c)) { auto cnt = deserialize_boolean(istr,data,NOTATION_TRUE_SERIAL,true); - if(PARSE_FAILURE == cnt) parse_count = cnt; + if(PARSE_FAILURE == cnt) parse_count = (S32)cnt; else account(cnt); } else @@ -735,7 +735,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) c S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) const { - LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD + LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; // map: { string:object, string:object } map = LLSD::emptyMap(); S32 parse_count = 0; @@ -796,7 +796,7 @@ S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map, S32 max_depth) c S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array, S32 max_depth) const { - LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD + LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; // array: [ object, object, object ] array = LLSD::emptyArray(); S32 parse_count = 0; @@ -836,7 +836,7 @@ S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array, S32 max_dept bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const { - LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD + LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; std::string value; auto count = deserialize_string(istr, value, mMaxBytesLeft); if(PARSE_FAILURE == count) return false; @@ -847,7 +847,7 @@ bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const { - LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD + LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; // binary: b##"ff3120ab1" // or: b(len)"..." @@ -950,7 +950,7 @@ LLSDBinaryParser::~LLSDBinaryParser() // virtual S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data, S32 max_depth) const { - LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD + LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; /** * Undefined: '!'<br> * Boolean: '1' for true '0' for false<br> @@ -1546,7 +1546,7 @@ S32 LLSDBinaryFormatter::format_impl(const LLSD& data, std::ostream& ostr, case LLSD::TypeMap: { ostr.put('{'); - U32 size_nbo = htonl(data.size()); + U32 size_nbo = htonl(static_cast<u_long>(data.size())); ostr.write((const char*)(&size_nbo), sizeof(U32)); LLSD::map_const_iterator iter = data.beginMap(); LLSD::map_const_iterator end = data.endMap(); @@ -1563,7 +1563,7 @@ S32 LLSDBinaryFormatter::format_impl(const LLSD& data, std::ostream& ostr, case LLSD::TypeArray: { ostr.put('['); - U32 size_nbo = htonl(data.size()); + U32 size_nbo = htonl(static_cast<u_long>(data.size())); ostr.write((const char*)(&size_nbo), sizeof(U32)); LLSD::array_const_iterator iter = data.beginArray(); LLSD::array_const_iterator end = data.endArray(); @@ -1630,7 +1630,7 @@ S32 LLSDBinaryFormatter::format_impl(const LLSD& data, std::ostream& ostr, { ostr.put('b'); const std::vector<U8>& buffer = data.asBinary(); - U32 size_nbo = htonl(buffer.size()); + U32 size_nbo = htonl(static_cast<u_long>(buffer.size())); ostr.write((const char*)(&size_nbo), sizeof(U32)); if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size()); break; @@ -1648,7 +1648,7 @@ void LLSDBinaryFormatter::formatString( const std::string& string, std::ostream& ostr) const { - U32 size_nbo = htonl(string.size()); + U32 size_nbo = htonl(static_cast<u_long>(string.size())); ostr.write((const char*)(&size_nbo), sizeof(U32)); ostr.write(string.c_str(), string.size()); } diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp index 88cbb3b984..6396caf8d5 100644 --- a/indra/llcommon/llsdserialize_xml.cpp +++ b/indra/llcommon/llsdserialize_xml.cpp @@ -554,7 +554,7 @@ void LLSDXMLParser::Impl::parsePart(const char* buf, llssize len) if ( buf != NULL && len > 0 ) { - XML_Status status = XML_Parse(mParser, buf, len, false); + XML_Status status = XML_Parse(mParser, buf, (int)len, 0); if (status == XML_STATUS_ERROR) { LL_INFOS() << "Unexpected XML parsing error at start" << LL_ENDL; @@ -930,7 +930,7 @@ void LLSDXMLParser::parsePart(const char *buf, llssize len) // virtual S32 LLSDXMLParser::doParse(std::istream& input, LLSD& data, S32 max_depth) const { - LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD + LL_PROFILE_ZONE_SCOPED_CATEGORY_LLSD; #ifdef XML_PARSER_PERFORMANCE_TESTS XML_Timer timer( &parseTime ); diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp index efce458117..12f67208c1 100644 --- a/indra/llcommon/llsdutil.cpp +++ b/indra/llcommon/llsdutil.cpp @@ -51,7 +51,7 @@ // U32 LLSD ll_sd_from_U32(const U32 val) { - std::vector<U8> v; + LLSD::Binary v; U32 net_order = htonl(val); v.resize(4); @@ -63,7 +63,7 @@ LLSD ll_sd_from_U32(const U32 val) U32 ll_U32_from_sd(const LLSD& sd) { U32 ret; - std::vector<U8> v = sd.asBinary(); + const LLSD::Binary& v = sd.asBinary(); if (v.size() < 4) { return 0; @@ -76,7 +76,7 @@ U32 ll_U32_from_sd(const LLSD& sd) //U64 LLSD ll_sd_from_U64(const U64 val) { - std::vector<U8> v; + LLSD::Binary v; U32 high, low; high = (U32)(val >> 32); @@ -94,7 +94,7 @@ LLSD ll_sd_from_U64(const U64 val) U64 ll_U64_from_sd(const LLSD& sd) { U32 high, low; - std::vector<U8> v = sd.asBinary(); + const LLSD::Binary& v = sd.asBinary(); if (v.size() < 8) { @@ -112,7 +112,7 @@ U64 ll_U64_from_sd(const LLSD& sd) // IP Address (stored in net order in a U32, so don't need swizzling) LLSD ll_sd_from_ipaddr(const U32 val) { - std::vector<U8> v; + LLSD::Binary v; v.resize(4); memcpy(&(v[0]), &val, 4); /* Flawfinder: ignore */ @@ -123,7 +123,7 @@ LLSD ll_sd_from_ipaddr(const U32 val) U32 ll_ipaddr_from_sd(const LLSD& sd) { U32 ret; - std::vector<U8> v = sd.asBinary(); + const LLSD::Binary& v = sd.asBinary(); if (v.size() < 4) { return 0; @@ -135,17 +135,17 @@ U32 ll_ipaddr_from_sd(const LLSD& sd) // Converts an LLSD binary to an LLSD string LLSD ll_string_from_binary(const LLSD& sd) { - std::vector<U8> value = sd.asBinary(); + const LLSD::Binary& value = sd.asBinary(); std::string str; str.resize(value.size()); - memcpy(&str[0], &value[0], value.size()); + memcpy(&str[0], value.data(), value.size()); return str; } // Converts an LLSD string to an LLSD binary LLSD ll_binary_from_string(const LLSD& sd) { - std::vector<U8> binary_value; + LLSD::Binary binary_value; std::string string_value = sd.asString(); for (const U8 c : string_value) @@ -209,24 +209,24 @@ std::string ll_stream_notation_sd(const LLSD& sd) //are not of the same type, false is returned or if the LLSDs are not //of the same value. Ordering of arrays matters //Otherwise, returns true -BOOL compare_llsd_with_template( +bool compare_llsd_with_template( const LLSD& llsd_to_test, const LLSD& template_llsd, LLSD& resultant_llsd) { - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED; if ( llsd_to_test.isUndefined() && template_llsd.isDefined() ) { resultant_llsd = template_llsd; - return TRUE; + return true; } else if ( llsd_to_test.type() != template_llsd.type() ) { resultant_llsd = LLSD(); - return FALSE; + return false; } if ( llsd_to_test.isArray() ) @@ -255,7 +255,7 @@ BOOL compare_llsd_with_template( data) ) { resultant_llsd = LLSD(); - return FALSE; + return false; } else { @@ -298,7 +298,7 @@ BOOL compare_llsd_with_template( value) ) { resultant_llsd = LLSD(); - return FALSE; + return false; } else { @@ -321,7 +321,7 @@ BOOL compare_llsd_with_template( } - return TRUE; + return true; } // filter_llsd_with_template() is a direct clone (copy-n-paste) of @@ -337,7 +337,7 @@ bool filter_llsd_with_template( const LLSD & template_llsd, LLSD & resultant_llsd) { - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED; if (llsd_to_test.isUndefined() && template_llsd.isDefined()) { @@ -533,7 +533,7 @@ class TypeLookup public: TypeLookup() { - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED; for (const Data *di(boost::begin(typedata)), *dend(boost::end(typedata)); di != dend; ++di) { @@ -543,7 +543,7 @@ public: std::string lookup(LLSD::Type type) const { - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED; MapType::const_iterator found = mMap.find(type); if (found != mMap.end()) @@ -595,7 +595,7 @@ static std::string match_types(LLSD::Type expect, // prototype.type() LLSD::Type actual, // type we're checking const std::string& pfx) // as for llsd_matches { - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED; // Trivial case: if the actual type is exactly what we expect, we're good. if (actual == expect) @@ -634,7 +634,7 @@ static std::string match_types(LLSD::Type expect, // prototype.type() // see docstring in .h file std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::string& pfx) { - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED; // An undefined prototype means that any data is valid. // An undefined slot in an array or map prototype means that any data @@ -768,7 +768,7 @@ std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::str bool llsd_equals(const LLSD& lhs, const LLSD& rhs, int bits) { - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED; // We're comparing strict equality of LLSD representation rather than // performing any conversions. So if the types aren't equal, the LLSD @@ -878,7 +878,7 @@ namespace llsd LLSD& drill_ref(LLSD& blob, const LLSD& rawPath) { - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED; // Treat rawPath uniformly as an array. If it's not already an array, // store it as the only entry in one. (But let's say Undefined means an @@ -905,7 +905,7 @@ LLSD& drill_ref(LLSD& blob, const LLSD& rawPath) // path entry that's bad. for (LLSD::Integer i = 0; i < path.size(); ++i) { - LL_PROFILE_ZONE_NUM( i ) + LL_PROFILE_ZONE_NUM(i); const LLSD& key{path[i]}; if (key.isString()) @@ -935,7 +935,7 @@ LLSD& drill_ref(LLSD& blob, const LLSD& rawPath) LLSD drill(const LLSD& blob, const LLSD& path) { - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED; // drill_ref() does exactly what we want. Temporarily cast away // const-ness and use that. @@ -949,7 +949,7 @@ LLSD drill(const LLSD& blob, const LLSD& path) // filter may be include to exclude/include keys in a map. LLSD llsd_clone(LLSD value, LLSD filter) { - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED; LLSD clone; bool has_filter(filter.isMap()); @@ -990,8 +990,7 @@ LLSD llsd_clone(LLSD value, LLSD filter) case LLSD::TypeBinary: { - LLSD::Binary bin(value.asBinary().begin(), value.asBinary().end()); - clone = LLSD::Binary(bin); + clone = LLSD::Binary(value.asBinary().begin(), value.asBinary().end()); break; } default: diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h index aa497c53c7..38bbe19ddd 100644 --- a/indra/llcommon/llsdutil.h +++ b/indra/llcommon/llsdutil.h @@ -72,7 +72,7 @@ LL_COMMON_API std::string ll_stream_notation_sd(const LLSD& sd); //Returns false if the test is of same type but values differ in type //Otherwise, returns true -LL_COMMON_API BOOL compare_llsd_with_template( +LL_COMMON_API bool compare_llsd_with_template( const LLSD& llsd_to_test, const LLSD& template_llsd, LLSD& resultant_llsd); diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 91c05bd5ed..316831cd74 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -36,6 +36,11 @@ #include "llthread.h" // on_main_thread() #include "llmainthreadtask.h" +#ifdef LL_WINDOWS +#pragma warning(push) +#pragma warning(disable : 4506) // no definition for inline function +#endif + class LLSingletonBase: private boost::noncopyable { public: @@ -528,6 +533,7 @@ public: classname<DERIVED_TYPE>(), " -- creating new instance"}); // fall through + [[fallthrough]]; case UNINITIALIZED: case QUEUED: // QUEUED means some secondary thread has already requested an @@ -807,17 +813,6 @@ private: \ DERIVED_CLASS(__VA_ARGS__) /** - * A slight variance from the above, but includes the "override" keyword - */ -#define LLSINGLETON_C11(DERIVED_CLASS) \ -private: \ - /* implement LLSingleton pure virtual method whose sole purpose */ \ - /* is to remind people to use this macro */ \ - virtual void you_must_use_LLSINGLETON_macro() override {} \ - friend class LLSingleton<DERIVED_CLASS>; \ - DERIVED_CLASS() - -/** * Use LLSINGLETON_EMPTY_CTOR(Foo); at the start of an LLSingleton<Foo> * subclass body when the constructor is trivial: * @@ -835,10 +830,6 @@ private: \ /* LLSINGLETON() is carefully implemented to permit exactly this */ \ LLSINGLETON(DERIVED_CLASS) {} -#define LLSINGLETON_EMPTY_CTOR_C11(DERIVED_CLASS) \ - /* LLSINGLETON() is carefully implemented to permit exactly this */ \ - LLSINGLETON_C11(DERIVED_CLASS) {} - // Relatively unsafe singleton implementation that is much faster // and simpler than LLSingleton, but has no dependency tracking // or inherent thread safety and requires manual invocation of @@ -871,4 +862,8 @@ private: template <class T> T* LLSimpleton<T>::sInstance{ nullptr }; +#ifdef LL_WINDOWS +#pragma warning(pop) +#endif + #endif diff --git a/indra/llcommon/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp index 1fe7f0f25f..bda3579f60 100644 --- a/indra/llcommon/llstacktrace.cpp +++ b/indra/llcommon/llstacktrace.cpp @@ -53,8 +53,8 @@ bool ll_get_stack_trace(std::vector<std::string>& lines) const S32 MAX_STACK_DEPTH = 32; const S32 STRING_NAME_LENGTH = 200; const S32 FRAME_SKIP = 2; - static BOOL symbolsLoaded = false; - static BOOL firstCall = true; + static bool symbolsLoaded = false; + static bool firstCall = true; HANDLE hProc = GetCurrentProcess(); @@ -92,7 +92,7 @@ bool ll_get_stack_trace(std::vector<std::string>& lines) for(S32 i=0; i < depth; i++) { std::stringstream stack_line; - BOOL ret; + bool ret; DWORD64 addr = (DWORD64)frames[i]; ret = SymGetSymFromAddr64(hProc, addr, 0, pSym); @@ -134,7 +134,7 @@ void ll_get_stack_trace_internal(std::vector<std::string>& lines) const S32 STRING_NAME_LENGTH = 256; HANDLE process = GetCurrentProcess(); - SymInitialize( process, NULL, TRUE ); + SymInitialize( process, NULL, true ); void *stack[MAX_STACK_DEPTH]; diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h index 3a6efd7d34..7d41c42ba7 100644 --- a/indra/llcommon/llstl.h +++ b/indra/llcommon/llstl.h @@ -226,11 +226,11 @@ void delete_and_clear_array(T*& ptr) // foo[2] = "hello"; // const char* bar = get_ptr_in_map(foo, 2); // bar -> "hello" // const char* baz = get_ptr_in_map(foo, 3); // baz == NULL -template <typename K, typename T> -inline T* get_ptr_in_map(const std::map<K,T*>& inmap, const K& key) +template <typename T> +inline typename T::mapped_type get_ptr_in_map(const T& inmap, typename T::key_type const& key) { // Typedef here avoids warnings because of new c++ naming rules. - typedef typename std::map<K,T*>::const_iterator map_iter; + typedef typename T::const_iterator map_iter; map_iter iter = inmap.find(key); if(iter == inmap.end()) { @@ -326,7 +326,7 @@ inline bool vector_replace_with_last(std::vector<T>& invec, const T& val) template <typename T> inline T* vector_append(std::vector<T>& invec, S32 N) { - U32 sz = invec.size(); + auto sz = invec.size(); invec.resize(sz+N); return &(invec[sz]); } @@ -532,7 +532,7 @@ bool before(const std::type_info* lhs, const std::type_info* rhs) return strcmp(lhs->name(), rhs->name()) < 0; #else // not Linux, or gcc 4.4+ // Just use before(), as we normally would - return lhs->before(*rhs) ? true : false; + return lhs->before(*rhs); #endif } diff --git a/indra/llcommon/llstreamqueue.h b/indra/llcommon/llstreamqueue.h index a09bf4cb4b..01689457dd 100644 --- a/indra/llcommon/llstreamqueue.h +++ b/indra/llcommon/llstreamqueue.h @@ -216,7 +216,7 @@ std::streamsize LLGenericStreamQueue<Ch>::skip(std::streamsize n) { typename BufferList::iterator bli(mBuffer.begin()), blend(mBuffer.end()); std::streamsize toskip(n), skipped(0); - while (bli != blend && toskip >= bli->length()) + while (bli != blend && (size_t)toskip >= bli->length()) { std::streamsize chunk(bli->length()); typename BufferList::iterator zap(bli++); diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 6512bbc392..c57f8b1e96 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -250,7 +250,7 @@ LLWString utf16str_to_wstring(const U16* utf16str, size_t len) while (i < len) { llwchar cur_char; - i += utf16chars_to_wchar(chars16+i, &cur_char); + i += (S32)utf16chars_to_wchar(chars16+i, &cur_char); wout += cur_char; } return wout; @@ -308,10 +308,10 @@ S32 wstring_utf16_length(const LLWString &wstr, const S32 woffset, const S32 wle // Given a wstring and an offset in it, returns the length as wstring (i.e., // number of llwchars) of the longest substring that starts at the offset // and whose equivalent utf-16 string does not exceeds the given utf16_length. -S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, const S32 woffset, const S32 utf16_length, BOOL *unaligned) +S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, const S32 woffset, const S32 utf16_length, bool *unaligned) { const auto end = wstr.length(); - BOOL u = FALSE; + bool u{ false }; S32 n = woffset + utf16_length; S32 i = woffset; while (i < end) @@ -758,7 +758,7 @@ std::string utf8str_showBytesUTF8(const std::string& utf8str) } // Search for any emoji symbol, return true if found -bool wstring_has_emoji(const LLWString& wstr) +bool wstring_has_emoji(LLWStringView wstr) { for (const llwchar& wch : wstr) { @@ -809,7 +809,7 @@ std::string ll_convert_wide_to_string(const wchar_t* in, size_t len_in, unsigned code_page, 0, in, - len_in, + static_cast<int>(len_in), NULL, 0, 0, @@ -824,7 +824,7 @@ std::string ll_convert_wide_to_string(const wchar_t* in, size_t len_in, unsigned code_page, 0, in, - len_in, + static_cast<int>(len_in), pout, len_out, 0, @@ -851,8 +851,8 @@ std::wstring ll_convert_string_to_wide(const char* in, size_t len, unsigned int std::vector<wchar_t> w_out(len + 1); memset(&w_out[0], 0, w_out.size()); - int real_output_str_len = MultiByteToWideChar(code_page, 0, in, len, - &w_out[0], w_out.size() - 1); + int real_output_str_len = MultiByteToWideChar(code_page, 0, in, static_cast<int>(len), + &w_out[0], static_cast<int>(w_out.size() - 1)); //looks like MultiByteToWideChar didn't add null terminator to converted string, see EXT-4858. w_out[real_output_str_len] = 0; @@ -938,12 +938,12 @@ std::wstring windows_message<std::wstring>(DWORD error) return out.str(); } -boost::optional<std::wstring> llstring_getoptenv(const std::string& key) +std::optional<std::wstring> llstring_getoptenv(const std::string& key) { auto wkey = ll_convert_string_to_wide(key); // Take a wild guess as to how big the buffer should be. std::vector<wchar_t> buffer(1024); - auto n = GetEnvironmentVariableW(wkey.c_str(), &buffer[0], buffer.size()); + auto n = GetEnvironmentVariableW(wkey.c_str(), &buffer[0], static_cast<DWORD>(buffer.size())); // If our initial guess was too short, n will indicate the size (in // wchar_t's) that buffer should have been, including the terminating nul. if (n > (buffer.size() - 1)) @@ -951,13 +951,13 @@ boost::optional<std::wstring> llstring_getoptenv(const std::string& key) // make it big enough buffer.resize(n); // and try again - n = GetEnvironmentVariableW(wkey.c_str(), &buffer[0], buffer.size()); + n = GetEnvironmentVariableW(wkey.c_str(), &buffer[0], static_cast<DWORD>(buffer.size())); } // did that (ultimately) succeed? if (n) { - // great, return populated boost::optional - return boost::optional<std::wstring>(&buffer[0]); + // great, return populated std::optional + return std::make_optional<std::wstring>(&buffer[0]); } // not successful @@ -968,23 +968,23 @@ boost::optional<std::wstring> llstring_getoptenv(const std::string& key) LL_WARNS() << "GetEnvironmentVariableW('" << key << "') failed: " << windows_message<std::string>(last_error) << LL_ENDL; } - // return empty boost::optional + // return empty std::optional return {}; } #else // ! LL_WINDOWS -boost::optional<std::string> llstring_getoptenv(const std::string& key) +std::optional<std::string> llstring_getoptenv(const std::string& key) { auto found = getenv(key.c_str()); if (found) { - // return populated boost::optional - return boost::optional<std::string>(found); + // return populated std::optional + return std::make_optional<std::string>(found); } else { - // return empty boost::optional + // return empty std::optional return {}; } } @@ -1017,7 +1017,7 @@ bool LLStringOps::isEmoji(llwchar a) // These are indeed "genuine" emojis, we *do want* rendered as such. HB return a >= 0x1f000 && a < 0x20000; #endif -} + } S32 LLStringOps::collate(const llwchar* a, const llwchar* b) { @@ -1208,6 +1208,75 @@ namespace LLStringFn return output; } + using literals_t = std::map<char, std::string>; + static const literals_t xml_elem_literals = + { + { '<', "<" }, + { '>', ">" }, + { '&', "&" } + }; + static const literals_t xml_attr_literals = + { + { '"', """ }, + { '\'', "'" } + }; + + static void literals_encode(std::string& text, const literals_t& literals) + { + for (const std::pair<char, std::string> it : literals) + { + std::string::size_type pos = 0; + while ((pos = text.find(it.first, pos)) != std::string::npos) + { + text.replace(pos, 1, it.second); + pos += it.second.size(); + } + } + } + + static void literals_decode(std::string& text, const literals_t& literals) + { + for (const std::pair<char, std::string> it : literals) + { + std::string::size_type pos = 0; + while ((pos = text.find(it.second, pos)) != std::string::npos) + { + text[pos++] = it.first; + text.erase(pos, it.second.size() - 1); + } + } + } + + /** + * @brief Replace all characters that are not allowed in XML 1.0 + * with corresponding literals: [ < > & ] => [ < > & ] + */ + std::string xml_encode(const std::string& input, bool for_attribute) + { + std::string result(input); + literals_encode(result, xml_elem_literals); + if (for_attribute) + { + literals_encode(result, xml_attr_literals); + } + return result; + } + + /** + * @brief Replace some of XML literals that are defined in XML 1.0 + * with corresponding characters: [ < > & ] => [ < > & ] + */ + std::string xml_decode(const std::string& input, bool for_attribute) + { + std::string result(input); + literals_decode(result, xml_elem_literals); + if (for_attribute) + { + literals_decode(result, xml_attr_literals); + } + return result; + } + /** * @brief Replace all control characters (c < 0x20) with replacement in * string. @@ -1552,7 +1621,7 @@ S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions) if (iter != substitutions.end()) { S32 secFromEpoch = 0; - BOOL r = LLStringUtil::convertToS32(iter->second, secFromEpoch); + bool r = LLStringUtil::convertToS32(iter->second, secFromEpoch); if (r) { found_replacement = formatDatetime(replacement, tokens[0], param, secFromEpoch); diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 6503da2e77..b69a068830 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -28,8 +28,9 @@ #define LL_LLSTRING_H #include <boost/call_traits.hpp> -#include <boost/optional/optional.hpp> +#include <optional> #include <string> +#include <string_view> #include <cstdio> #include <cwchar> // std::wcslen() //#include <locale> @@ -317,7 +318,7 @@ public: static void toLower(string_type& string); // True if this is the head of s. - static BOOL isHead( const string_type& string, const T* s ); + static bool isHead( const string_type& string, const T* s ); /** * @brief Returns true if string starts with substr @@ -348,7 +349,7 @@ public: * (key is always UTF-8) * detect absence by (! return value) */ - static boost::optional<string_type> getoptenv(const std::string& key); + static std::optional<string_type> getoptenv(const std::string& key); static void addCRLF(string_type& string); static void removeCRLF(string_type& string); @@ -361,7 +362,7 @@ public: static string_type capitalize(const string_type& str); static void capitalize(string_type& str); - static BOOL containsNonprintable(const string_type& string); + static bool containsNonprintable(const string_type& string); static void stripNonprintable(string_type& string); /** @@ -387,15 +388,15 @@ public: static void _makeASCII(string_type& string); // Conversion to other data types - static BOOL convertToBOOL(const string_type& string, BOOL& value); - static BOOL convertToU8(const string_type& string, U8& value); - static BOOL convertToS8(const string_type& string, S8& value); - static BOOL convertToS16(const string_type& string, S16& value); - static BOOL convertToU16(const string_type& string, U16& value); - static BOOL convertToU32(const string_type& string, U32& value); - static BOOL convertToS32(const string_type& string, S32& value); - static BOOL convertToF32(const string_type& string, F32& value); - static BOOL convertToF64(const string_type& string, F64& value); + static bool convertToBOOL(const string_type& string, bool& value); + static bool convertToU8(const string_type& string, U8& value); + static bool convertToS8(const string_type& string, S8& value); + static bool convertToS16(const string_type& string, S16& value); + static bool convertToU16(const string_type& string, U16& value); + static bool convertToU32(const string_type& string, U32& value); + static bool convertToS32(const string_type& string, S32& value); + static bool convertToF32(const string_type& string, F32& value); + static bool convertToF64(const string_type& string, F64& value); ///////////////////////////////////////////////////////////////////////////////////////// // Utility functions for working with char*'s and strings @@ -420,7 +421,7 @@ public: static S32 compareDictInsensitive(const string_type& a, const string_type& b); // Puts compareDict() in a form appropriate for LL container classes to use for sorting. - static BOOL precedesDict( const string_type& a, const string_type& b ); + static bool precedesDict( const string_type& a, const string_type& b ); // A replacement for strncpy. // If the dst buffer is dst_size bytes long or more, ensures that dst is null terminated and holds @@ -447,6 +448,7 @@ template<class T> std::string LLStringUtilBase<T>::sLocale; typedef LLStringUtilBase<char> LLStringUtil; typedef LLStringUtilBase<llwchar> LLWStringUtil; typedef std::basic_string<llwchar> LLWString; +typedef std::basic_string_view<llwchar> LLWStringView; //@ Use this where we want to disallow input in the form of "foo" // This is used to catch places where english text is embedded in the code @@ -464,7 +466,7 @@ struct LLDictionaryLess public: bool operator()(const std::string& a, const std::string& b) const { - return (LLStringUtil::precedesDict(a, b) ? true : false); + return (LLStringUtil::precedesDict(a, b)); } }; @@ -694,7 +696,7 @@ LL_COMMON_API S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len LL_COMMON_API S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen); // Length in wstring (i.e., llwchar count) of a part of a wstring specified by utf16 length (i.e., utf16 units.) -LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = NULL); +LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, bool *unaligned = nullptr); /** * @brief Properly truncate a utf8 string to a maximum byte count. @@ -748,7 +750,7 @@ LL_COMMON_API llwchar utf8str_to_wchar(const std::string& utf8str, size_t offset LL_COMMON_API std::string utf8str_showBytesUTF8(const std::string& utf8str); -LL_COMMON_API bool wstring_has_emoji(const LLWString& wstr); +LL_COMMON_API bool wstring_has_emoji(LLWStringView wstr); LL_COMMON_API bool wstring_remove_emojis(LLWString& wstr); @@ -835,11 +837,11 @@ STRING windows_message() { return windows_message<STRING>(GetLastError()); } //@} -LL_COMMON_API boost::optional<std::wstring> llstring_getoptenv(const std::string& key); +LL_COMMON_API std::optional<std::wstring> llstring_getoptenv(const std::string& key); #else // ! LL_WINDOWS -LL_COMMON_API boost::optional<std::string> llstring_getoptenv(const std::string& key); +LL_COMMON_API std::optional<std::string> llstring_getoptenv(const std::string& key); #endif // ! LL_WINDOWS @@ -888,6 +890,20 @@ namespace LLStringFn /** + * @brief Replace all characters that are not allowed in XML 1.0 + * with corresponding literals: [ < > & ] => [ < > & ] + */ + LL_COMMON_API std::string xml_encode(const std::string& input, bool for_attribute = false); + + + /** + * @brief Replace some of XML literals that are defined in XML 1.0 + * with corresponding characters: [ < > & ] => [ < > & ] + */ + LL_COMMON_API std::string xml_decode(const std::string& input, bool for_attribute = false); + + + /** * @brief Replace all control characters (0 <= c < 0x20) with replacement in * string. This is safe for utf-8 * @@ -1378,7 +1394,7 @@ S32 LLStringUtilBase<T>::compareDictInsensitive(const string_type& astr, const s // Puts compareDict() in a form appropriate for LL container classes to use for sorting. // static template<class T> -BOOL LLStringUtilBase<T>::precedesDict( const string_type& a, const string_type& b ) +bool LLStringUtilBase<T>::precedesDict( const string_type& a, const string_type& b ) { if( a.size() && b.size() ) { @@ -1634,15 +1650,15 @@ void LLStringUtilBase<T>::capitalize(string_type& str) //static template<class T> -BOOL LLStringUtilBase<T>::containsNonprintable(const string_type& string) +bool LLStringUtilBase<T>::containsNonprintable(const string_type& string) { const char MIN = 32; - BOOL rv = FALSE; + bool rv = false; for (size_type i = 0; i < string.size(); i++) { if(string[i] < MIN) { - rv = TRUE; + rv = true; break; } } @@ -1771,12 +1787,12 @@ void LLStringUtilBase<T>::copyInto(string_type& dst, const string_type& src, siz // True if this is the head of s. //static template<class T> -BOOL LLStringUtilBase<T>::isHead( const string_type& string, const T* s ) +bool LLStringUtilBase<T>::isHead( const string_type& string, const T* s ) { if( string.empty() ) { // Early exit - return FALSE; + return false; } else { @@ -1812,17 +1828,17 @@ bool LLStringUtilBase<T>::endsWith( // static template<class T> -auto LLStringUtilBase<T>::getoptenv(const std::string& key) -> boost::optional<string_type> +auto LLStringUtilBase<T>::getoptenv(const std::string& key) -> std::optional<string_type> { auto found(llstring_getoptenv(key)); if (found) { - // return populated boost::optional + // return populated std::optional return { ll_convert<string_type>(*found) }; } else { - // empty boost::optional + // empty std::optional return {}; } } @@ -1843,11 +1859,11 @@ auto LLStringUtilBase<T>::getenv(const std::string& key, const string_type& dflt } template<class T> -BOOL LLStringUtilBase<T>::convertToBOOL(const string_type& string, BOOL& value) +bool LLStringUtilBase<T>::convertToBOOL(const string_type& string, bool& value) { if( string.empty() ) { - return FALSE; + return false; } string_type temp( string ); @@ -1860,8 +1876,8 @@ BOOL LLStringUtilBase<T>::convertToBOOL(const string_type& string, BOOL& value) (temp == "true") || (temp == "True") ) { - value = TRUE; - return TRUE; + value = true; + return true; } else if( @@ -1872,71 +1888,71 @@ BOOL LLStringUtilBase<T>::convertToBOOL(const string_type& string, BOOL& value) (temp == "false") || (temp == "False") ) { - value = FALSE; - return TRUE; + value = false; + return true; } - return FALSE; + return false; } template<class T> -BOOL LLStringUtilBase<T>::convertToU8(const string_type& string, U8& value) +bool LLStringUtilBase<T>::convertToU8(const string_type& string, U8& value) { S32 value32 = 0; - BOOL success = convertToS32(string, value32); + bool success = convertToS32(string, value32); if( success && (U8_MIN <= value32) && (value32 <= U8_MAX) ) { value = (U8) value32; - return TRUE; + return true; } - return FALSE; + return false; } template<class T> -BOOL LLStringUtilBase<T>::convertToS8(const string_type& string, S8& value) +bool LLStringUtilBase<T>::convertToS8(const string_type& string, S8& value) { S32 value32 = 0; - BOOL success = convertToS32(string, value32); + bool success = convertToS32(string, value32); if( success && (S8_MIN <= value32) && (value32 <= S8_MAX) ) { value = (S8) value32; - return TRUE; + return true; } - return FALSE; + return false; } template<class T> -BOOL LLStringUtilBase<T>::convertToS16(const string_type& string, S16& value) +bool LLStringUtilBase<T>::convertToS16(const string_type& string, S16& value) { S32 value32 = 0; - BOOL success = convertToS32(string, value32); + bool success = convertToS32(string, value32); if( success && (S16_MIN <= value32) && (value32 <= S16_MAX) ) { value = (S16) value32; - return TRUE; + return true; } - return FALSE; + return false; } template<class T> -BOOL LLStringUtilBase<T>::convertToU16(const string_type& string, U16& value) +bool LLStringUtilBase<T>::convertToU16(const string_type& string, U16& value) { S32 value32 = 0; - BOOL success = convertToS32(string, value32); + bool success = convertToS32(string, value32); if( success && (U16_MIN <= value32) && (value32 <= U16_MAX) ) { value = (U16) value32; - return TRUE; + return true; } - return FALSE; + return false; } template<class T> -BOOL LLStringUtilBase<T>::convertToU32(const string_type& string, U32& value) +bool LLStringUtilBase<T>::convertToU32(const string_type& string, U32& value) { if( string.empty() ) { - return FALSE; + return false; } string_type temp( string ); @@ -1946,17 +1962,17 @@ BOOL LLStringUtilBase<T>::convertToU32(const string_type& string, U32& value) if(i_stream >> v) { value = v; - return TRUE; + return true; } - return FALSE; + return false; } template<class T> -BOOL LLStringUtilBase<T>::convertToS32(const string_type& string, S32& value) +bool LLStringUtilBase<T>::convertToS32(const string_type& string, S32& value) { if( string.empty() ) { - return FALSE; + return false; } string_type temp( string ); @@ -1969,34 +1985,34 @@ BOOL LLStringUtilBase<T>::convertToS32(const string_type& string, S32& value) //if((LONG_MAX == v) || (LONG_MIN == v)) //{ // // Underflow or overflow - // return FALSE; + // return false; //} value = v; - return TRUE; + return true; } - return FALSE; + return false; } template<class T> -BOOL LLStringUtilBase<T>::convertToF32(const string_type& string, F32& value) +bool LLStringUtilBase<T>::convertToF32(const string_type& string, F32& value) { F64 value64 = 0.0; - BOOL success = convertToF64(string, value64); + bool success = convertToF64(string, value64); if( success && (-F32_MAX <= value64) && (value64 <= F32_MAX) ) { value = (F32) value64; - return TRUE; + return true; } - return FALSE; + return false; } template<class T> -BOOL LLStringUtilBase<T>::convertToF64(const string_type& string, F64& value) +bool LLStringUtilBase<T>::convertToF64(const string_type& string, F64& value) { if( string.empty() ) { - return FALSE; + return false; } string_type temp( string ); @@ -2009,13 +2025,13 @@ BOOL LLStringUtilBase<T>::convertToF64(const string_type& string, F64& value) //if( ((-HUGE_VAL == v) || (HUGE_VAL == v))) ) //{ // // Underflow or overflow - // return FALSE; + // return false; //} value = v; - return TRUE; + return true; } - return FALSE; + return false; } template<class T> diff --git a/indra/llcommon/llstringtable.h b/indra/llcommon/llstringtable.h index e41701ce9c..97f95369e5 100644 --- a/indra/llcommon/llstringtable.h +++ b/indra/llcommon/llstringtable.h @@ -51,7 +51,7 @@ public: ~LLStringTableEntry(); void incCount() { mCount++; } - BOOL decCount() { return --mCount; } + bool decCount() { return --mCount != 0; } char *mString; S32 mCount; diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index b7ffddc023..79625ad9f8 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -74,6 +74,8 @@ using namespace llsd; # include <mach/mach_host.h> # include <mach/task.h> # include <mach/task_info.h> +# include <sys/types.h> +# include <mach/mach_init.h> #elif LL_LINUX # include <errno.h> # include <sys/utsname.h> @@ -85,6 +87,7 @@ const char MEMINFO_FILE[] = "/proc/meminfo"; #endif LLCPUInfo gSysCPU; +LLMemoryInfo gSysMemory; // Don't log memory info any more often than this. It also serves as our // framerate sample size. @@ -213,7 +216,7 @@ LLOSInfo::LLOSInfo() : 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); + LSTATUS 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); @@ -226,16 +229,8 @@ LLOSInfo::LLOSInfo() : if (mBuild >= 22000) { // At release Windows 11 version was 10.0.22000.194 - // Windows 10 version was 10.0.19043.1266 - // There is no warranty that Win10 build won't increase, - // so until better solution is found or Microsoft updates - // SDK with IsWindows11OrGreater(), indicate "10/11" - // - // Current alternatives: - // Query WMI's Win32_OperatingSystem for OS string. Slow - // and likely to return 'compatibility' string. - // Check presence of dlls/libs or may be their version. - mOSStringSimple = "Microsoft Windows 10/11 "; + // According to microsoft win 10 won't ever get that far. + mOSStringSimple = "Microsoft Windows 11 "; } } @@ -268,9 +263,9 @@ LLOSInfo::LLOSInfo() : #elif LL_DARWIN // Initialize mOSStringSimple to something like: - // "Mac OS X 10.6.7" + // "macOS 10.13.1" { - const char * DARWIN_PRODUCT_NAME = "Mac OS X"; + const char * DARWIN_PRODUCT_NAME = "macOS"; int64_t major_version, minor_version, bugfix_version = 0; @@ -293,7 +288,7 @@ LLOSInfo::LLOSInfo() : } // Initialize mOSString to something like: - // "Mac OS X 10.6.7 Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 i386" + // "macOS 10.13.1 Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 i386" struct utsname un; if(uname(&un) != -1) { @@ -570,7 +565,7 @@ bool LLOSInfo::is64Bit() return true; #elif defined(_WIN32) // 32-bit viewer may be run on both 32-bit and 64-bit Windows, need to elaborate - BOOL f64 = FALSE; + bool f64 = false; return IsWow64Process(GetCurrentProcess(), &f64) && f64; #else return false; @@ -805,33 +800,32 @@ U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const } //static -void LLMemoryInfo::getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb) +void LLMemoryInfo::getAvailableMemoryKB(U32Kilobytes& avail_mem_kb) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY; #if LL_WINDOWS // Sigh, this shouldn't be a static method, then we wouldn't have to // reload this data separately from refresh() LLSD statsMap(loadStatsMap()); - avail_physical_mem_kb = (U32Kilobytes)statsMap["Avail Physical KB"].asInteger(); - avail_virtual_mem_kb = (U32Kilobytes)statsMap["Avail Virtual KB"].asInteger(); + avail_mem_kb = (U32Kilobytes)statsMap["Avail Physical KB"].asInteger(); #elif LL_DARWIN - // mStatsMap is derived from vm_stat, look for (e.g.) "kb free": - // $ vm_stat - // Mach Virtual Memory Statistics: (page size of 4096 bytes) - // Pages free: 462078. - // Pages active: 142010. - // Pages inactive: 220007. - // Pages wired down: 159552. - // "Translation faults": 220825184. - // Pages copy-on-write: 2104153. - // Pages zero filled: 167034876. - // Pages reactivated: 65153. - // Pageins: 2097212. - // Pageouts: 41759. - // Object cache: 841598 hits of 7629869 lookups (11% hit rate) - avail_physical_mem_kb = (U32Kilobytes)-1 ; - avail_virtual_mem_kb = (U32Kilobytes)-1 ; + // use host_statistics64 to get memory info + vm_statistics64_data_t vmstat; + mach_msg_type_number_t count = HOST_VM_INFO64_COUNT; + mach_port_t host = mach_host_self(); + vm_size_t page_size; + host_page_size(host, &page_size); + kern_return_t result = host_statistics64(host, HOST_VM_INFO64, reinterpret_cast<host_info_t>(&vmstat), &count); + if (result == KERN_SUCCESS) + { + avail_mem_kb = U64Bytes((vmstat.free_count + vmstat.inactive_count) * page_size); + } + else + { + avail_mem_kb = (U32Kilobytes)-1; + } #elif LL_LINUX // mStatsMap is derived from MEMINFO_FILE: @@ -882,15 +876,14 @@ void LLMemoryInfo::getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32 // DirectMap4k: 434168 kB // DirectMap2M: 477184 kB // (could also run 'free', but easier to read a file than run a program) - avail_physical_mem_kb = (U32Kilobytes)-1 ; - avail_virtual_mem_kb = (U32Kilobytes)-1 ; + LLSD statsMap(loadStatsMap()); + avail_mem_kb = (U32Kilobytes)statsMap["MemFree"].asInteger(); #else //do not know how to collect available memory info for other systems. //leave it blank here for now. - avail_physical_mem_kb = (U32Kilobytes)-1 ; - avail_virtual_mem_kb = (U32Kilobytes)-1 ; + avail_mem_kb = (U32Kilobytes)-1 ; #endif } @@ -936,7 +929,7 @@ LLSD LLMemoryInfo::getStatsMap() const LLMemoryInfo& LLMemoryInfo::refresh() { - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED; mStatsMap = loadStatsMap(); LL_DEBUGS("LLMemoryInfo") << "Populated mStatsMap:\n"; @@ -985,7 +978,7 @@ LLSD LLMemoryInfo::loadStatsMap() // specifically accepts PROCESS_MEMORY_COUNTERS*, and since this is a // classic-C API, PROCESS_MEMORY_COUNTERS_EX isn't a subclass. Cast the // pointer. - GetProcessMemoryInfo(GetCurrentProcess(), PPROCESS_MEMORY_COUNTERS(&pmem), sizeof(pmem)); + GetProcessMemoryInfo(GetCurrentProcess(), (PROCESS_MEMORY_COUNTERS*) &pmem, sizeof(pmem)); stats.add("Page Fault Count", pmem.PageFaultCount); stats.add("PeakWorkingSetSize KB", pmem.PeakWorkingSetSize/div); @@ -1319,11 +1312,11 @@ private: // Need an instance of FrameWatcher before it does any good static FrameWatcher sFrameWatcher; -BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile) +bool gunzip_file(const std::string& srcfile, const std::string& dstfile) { std::string tmpfile; const S32 UNCOMPRESS_BUFFER_SIZE = 32768; - BOOL retval = FALSE; + bool retval = false; gzFile src = NULL; U8 buffer[UNCOMPRESS_BUFFER_SIZE]; LLFILE *dst = NULL; @@ -1355,18 +1348,18 @@ BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile) LLFile::remove(dstfile, ENOENT); #endif if (LLFile::rename(tmpfile, dstfile) == -1) goto err; /* Flawfinder: ignore */ - retval = TRUE; + retval = true; err: if (src != NULL) gzclose(src); if (dst != NULL) fclose(dst); return retval; } -BOOL gzip_file(const std::string& srcfile, const std::string& dstfile) +bool gzip_file(const std::string& srcfile, const std::string& dstfile) { const S32 COMPRESS_BUFFER_SIZE = 32768; std::string tmpfile; - BOOL retval = FALSE; + bool retval = false; U8 buffer[COMPRESS_BUFFER_SIZE]; gzFile dst = NULL; LLFILE *src = NULL; @@ -1406,7 +1399,7 @@ BOOL gzip_file(const std::string& srcfile, const std::string& dstfile) LLFile::remove(dstfile); #endif if (LLFile::rename(tmpfile, dstfile) == -1) goto err; /* Flawfinder: ignore */ - retval = TRUE; + retval = true; err: if (src != NULL) fclose(src); if (dst != NULL) gzclose(dst); diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index 5c87ce6bf2..827b0dc048 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -134,8 +134,8 @@ public: static U32Kilobytes getHardwareMemSize(); // Because some Mac linkers won't let us reference extern gSysMemory from a different lib. #endif - //get the available memory infomation in KiloBytes. - static void getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb); + //get the available memory in KiloBytes. + static void getAvailableMemoryKB(U32Kilobytes& avail_mem_kb); // Retrieve a map of memory statistics. The keys of the map are platform- // dependent. The values are in kilobytes to try to avoid integer overflow. @@ -164,11 +164,12 @@ LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLOSInfo& info); LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLCPUInfo& info); LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLMemoryInfo& info); -// gunzip srcfile into dstfile. Returns FALSE on error. -BOOL LL_COMMON_API gunzip_file(const std::string& srcfile, const std::string& dstfile); -// gzip srcfile into dstfile. Returns FALSE on error. -BOOL LL_COMMON_API gzip_file(const std::string& srcfile, const std::string& dstfile); +// gunzip srcfile into dstfile. Returns false on error. +bool LL_COMMON_API gunzip_file(const std::string& srcfile, const std::string& dstfile); +// gzip srcfile into dstfile. Returns false on error. +bool LL_COMMON_API gzip_file(const std::string& srcfile, const std::string& dstfile); +extern LL_COMMON_API LLMemoryInfo gSysMemory; extern LL_COMMON_API LLCPUInfo gSysCPU; #endif // LL_LLSYS_H diff --git a/indra/llcommon/llsys_objc.mm b/indra/llcommon/llsys_objc.mm index 3fd85fb1c9..1393ccea50 100644 --- a/indra/llcommon/llsys_objc.mm +++ b/indra/llcommon/llsys_objc.mm @@ -27,38 +27,12 @@ #import "llsys_objc.h" #import <AppKit/AppKit.h> -static auto intAtStringIndex(NSArray *array, int index) -{ - return [(NSString *)[array objectAtIndex:index] integerValue]; -} - bool LLGetDarwinOSInfo(int64_t &major, int64_t &minor, int64_t &patch) { - if (NSAppKitVersionNumber > NSAppKitVersionNumber10_8) - { NSOperatingSystemVersion osVersion = [[NSProcessInfo processInfo] operatingSystemVersion]; major = osVersion.majorVersion; minor = osVersion.minorVersion; patch = osVersion.patchVersion; - } - else - { - NSString* versionString = [[NSDictionary dictionaryWithContentsOfFile: - @"/System/Library/CoreServices/SystemVersion.plist"] objectForKey:@"ProductVersion"]; - NSArray* versions = [versionString componentsSeparatedByString:@"."]; - NSUInteger count = [versions count]; - if (count > 0) - { - major = intAtStringIndex(versions, 0); - if (count > 1) - { - minor = intAtStringIndex(versions, 1); - if (count > 2) - { - patch = intAtStringIndex(versions, 2); - } - } - } - } + return true; } diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index e6b0c03371..e5d25b52f0 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -189,7 +189,7 @@ void LLThread::threadRun() } LLThread::LLThread(const std::string& name, apr_pool_t *poolp) : - mPaused(FALSE), + mPaused(false), mName(name), mThreadp(NULL), mStatus(STOPPED), @@ -269,6 +269,7 @@ void LLThread::shutdown() mStatus = STOPPED; return; } + delete mThreadp; mThreadp = NULL; } @@ -299,6 +300,7 @@ void LLThread::start() { mThreadp = new std::thread(std::bind(&LLThread::threadRun, this)); mNativeHandle = mThreadp->native_handle(); + mThreadp->detach(); } catch (std::system_error& ex) { @@ -344,7 +346,7 @@ bool LLThread::runCondition(void) // Stop thread execution if requested until unpaused. void LLThread::checkPause() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; mDataLock->lock(); // This is in a while loop because the pthread API allows for spurious wakeups. @@ -376,20 +378,20 @@ void LLThread::setQuitting() // static LLThread::id_t LLThread::currentID() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; return std::this_thread::get_id(); } // static void LLThread::yield() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; std::this_thread::yield(); } void LLThread::wake() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; mDataLock->lock(); if(!shouldSleep()) { @@ -400,7 +402,7 @@ void LLThread::wake() void LLThread::wakeLocked() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; if(!shouldSleep()) { mRunCondition->signal(); @@ -409,42 +411,18 @@ void LLThread::wakeLocked() void LLThread::lockData() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; mDataLock->lock(); } void LLThread::unlockData() { - LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD + LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD; mDataLock->unlock(); } //============================================================================ -//---------------------------------------------------------------------------- - -//static -LLMutex* LLThreadSafeRefCount::sMutex = 0; - -//static -void LLThreadSafeRefCount::initThreadSafeRefCount() -{ - if (!sMutex) - { - sMutex = new LLMutex(); - } -} - -//static -void LLThreadSafeRefCount::cleanupThreadSafeRefCount() -{ - delete sMutex; - sMutex = NULL; -} - - -//---------------------------------------------------------------------------- - LLThreadSafeRefCount::LLThreadSafeRefCount() : mRef(0) { diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index e21e6265ea..4194e0014d 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -68,7 +68,7 @@ public: // Called from MAIN THREAD. void pause(); void unpause(); - bool isPaused() { return isStopped() || mPaused == TRUE; } + bool isPaused() { return isStopped() || mPaused; } // Cause the thread to wake up and check its condition void wake(); diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index 6f74bf3fc8..28d6e4e4cc 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -91,17 +91,17 @@ U32 micro_sleep(U64 us, U32 max_yields) U32 micro_sleep(U64 us, U32 max_yields) { - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED; #if 0 LARGE_INTEGER ft; ft.QuadPart = -static_cast<S64>(us * 10); // '-' using relative time - HANDLE timer = CreateWaitableTimer(NULL, TRUE, NULL); + HANDLE timer = CreateWaitableTimer(NULL, true, NULL); SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); WaitForSingleObject(timer, INFINITE); CloseHandle(timer); #else - Sleep(us / 1000); + Sleep((DWORD)(us / 1000)); #endif return 0; @@ -109,7 +109,7 @@ U32 micro_sleep(U64 us, U32 max_yields) void ms_sleep(U32 ms) { - LL_PROFILE_ZONE_SCOPED + LL_PROFILE_ZONE_SCOPED; micro_sleep(ms * 1000, 0); } @@ -324,7 +324,7 @@ LLTimer::LLTimer() get_timer_info().update(); } - mStarted = TRUE; + mStarted = true; reset(); } @@ -424,7 +424,7 @@ F32SecondsImplicit LLTimer::getElapsedTimeAndResetF32() /////////////////////////////////////////////////////////////////////////////// -void LLTimer::setTimerExpirySec(F32SecondsImplicit expiration) +void LLTimer::setTimerExpirySec(F32SecondsImplicit expiration) { mExpirationTicks = get_clock_count() + (U64)((F32)(expiration * get_timer_info().mClockFrequency.value())); @@ -441,31 +441,30 @@ F32SecondsImplicit LLTimer::getRemainingTimeF32() const } -BOOL LLTimer::checkExpirationAndReset(F32 expiration) +bool LLTimer::checkExpirationAndReset(F32 expiration) { U64 cur_ticks = get_clock_count(); if (cur_ticks < mExpirationTicks) { - return FALSE; + return false; } mExpirationTicks = cur_ticks + (U64)((F32)(expiration * get_timer_info().mClockFrequency)); - return TRUE; + return true; } -BOOL LLTimer::hasExpired() const +bool LLTimer::hasExpired() const { - return (get_clock_count() >= mExpirationTicks) - ? TRUE : FALSE; + return get_clock_count() >= mExpirationTicks; } /////////////////////////////////////////////////////////////////////////////// -BOOL LLTimer::knownBadTimer() +bool LLTimer::knownBadTimer() { - BOOL failed = FALSE; + bool failed = false; #if LL_WINDOWS WCHAR bad_pci_list[][10] = {L"1039:0530", @@ -507,7 +506,7 @@ BOOL LLTimer::knownBadTimer() if (!wcscmp(pci_id, bad_pci_list[check])) { // LL_WARNS() << "unreliable PCI chipset found!! " << pci_id << endl; - failed = TRUE; + failed = true; break; } } @@ -533,7 +532,7 @@ time_t time_corrected() // Is the current computer (in its current time zone) // observing daylight savings time? -BOOL is_daylight_savings() +bool is_daylight_savings() { time_t now = time(NULL); @@ -547,7 +546,7 @@ BOOL is_daylight_savings() } -struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time) +struct tm* utc_to_pacific_time(time_t utc_time, bool pacific_daylight_time) { S32Hours pacific_offset_hours; if (pacific_daylight_time) diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h index fe4a3afc7a..d79f250585 100644 --- a/indra/llcommon/lltimer.h +++ b/indra/llcommon/lltimer.h @@ -87,19 +87,19 @@ public: // MANIPULATORS - void start() { reset(); mStarted = TRUE; } - void stop() { mStarted = FALSE; } + void start() { reset(); mStarted = true; } + void stop() { mStarted = false; } void reset(); // Resets the timer void setLastClockCount(U64 current_count); // Sets the timer so that the next elapsed call will be relative to this time void setTimerExpirySec(F32SecondsImplicit expiration); - BOOL checkExpirationAndReset(F32 expiration); - BOOL hasExpired() const; + bool checkExpirationAndReset(F32 expiration); + bool hasExpired() const; F32SecondsImplicit getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset F64SecondsImplicit getElapsedTimeAndResetF64(); F32SecondsImplicit getRemainingTimeF32() const; - static BOOL knownBadTimer(); + static bool knownBadTimer(); // ACCESSORS F32SecondsImplicit getElapsedTimeF32() const; // Returns elapsed time in seconds @@ -171,14 +171,14 @@ extern LL_COMMON_API S32 gUTCOffset; // Is the current computer (in its current time zone) // observing daylight savings time? -LL_COMMON_API BOOL is_daylight_savings(); +LL_COMMON_API bool is_daylight_savings(); // Converts internal "struct tm" time buffer to Pacific Standard/Daylight Time // Usage: // S32 utc_time; // utc_time = time_corrected(); // struct tm* internal_time = utc_to_pacific_time(utc_time, gDaylight); -LL_COMMON_API struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time); +LL_COMMON_API struct tm* utc_to_pacific_time(time_t utc_time, bool pacific_daylight_time); LL_COMMON_API void microsecondsToTimecodeString(U64MicrosecondsImplicit current_time, std::string& tcstring); LL_COMMON_API void secondsToTimecodeString(F32SecondsImplicit current_time, std::string& tcstring); diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp index 8741087f3a..dc9a87eb80 100644 --- a/indra/llcommon/lltraceaccumulators.cpp +++ b/indra/llcommon/lltraceaccumulators.cpp @@ -100,7 +100,7 @@ bool AccumulatorBufferGroup::isCurrent() const return mCounts.isCurrent(); } -void AccumulatorBufferGroup::append( const AccumulatorBufferGroup& other ) +void AccumulatorBufferGroup::append(const AccumulatorBufferGroup& other) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; mCounts.addSamples(other.mCounts, SEQUENTIAL); @@ -109,7 +109,7 @@ void AccumulatorBufferGroup::append( const AccumulatorBufferGroup& other ) mStackTimers.addSamples(other.mStackTimers, SEQUENTIAL); } -void AccumulatorBufferGroup::merge( const AccumulatorBufferGroup& other) +void AccumulatorBufferGroup::merge(const AccumulatorBufferGroup& other) { LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; mCounts.addSamples(other.mCounts, NON_SEQUENTIAL); @@ -140,7 +140,7 @@ void AccumulatorBufferGroup::sync() F64 SampleAccumulator::mergeSumsOfSquares(const SampleAccumulator& a, const SampleAccumulator& b) { - const F64 epsilon = 0.0000001; + constexpr F64 epsilon = 0.0000001; if (a.getSamplingTime() > epsilon && b.getSamplingTime() > epsilon) { @@ -170,7 +170,7 @@ F64 SampleAccumulator::mergeSumsOfSquares(const SampleAccumulator& a, const Samp return a.getSumOfSquares(); } -void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppendType append_type ) +void SampleAccumulator::addSamples(const SampleAccumulator& other, EBufferAppendType append_type) { if (append_type == NON_SEQUENTIAL) { @@ -205,7 +205,7 @@ void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppen } } -void SampleAccumulator::reset( const SampleAccumulator* other ) +void SampleAccumulator::reset(const SampleAccumulator* other) { mLastValue = other ? other->mLastValue : NaN; mHasValue = other ? other->mHasValue : false; @@ -243,7 +243,7 @@ F64 EventAccumulator::mergeSumsOfSquares(const EventAccumulator& a, const EventA return a.mSumOfSquares; } -void EventAccumulator::addSamples( const EventAccumulator& other, EBufferAppendType append_type ) +void EventAccumulator::addSamples(const EventAccumulator& other, EBufferAppendType append_type) { if (other.mNumSamples) { @@ -269,12 +269,12 @@ void EventAccumulator::addSamples( const EventAccumulator& other, EBufferAppendT } } -void EventAccumulator::reset( const EventAccumulator* other ) +void EventAccumulator::reset(const EventAccumulator* other) { mNumSamples = 0; mSum = 0; - mMin = F32(NaN); - mMax = F32(NaN); + mMin = NaN; + mMax = NaN; mMean = NaN; mSumOfSquares = 0; mLastValue = other ? other->mLastValue : NaN; diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h index 692bbe5acf..0a2e2bf997 100644 --- a/indra/llcommon/lltraceaccumulators.h +++ b/indra/llcommon/lltraceaccumulators.h @@ -39,7 +39,7 @@ namespace LLTrace { - const F64 NaN = std::numeric_limits<double>::quiet_NaN(); + constexpr F64 NaN = std::numeric_limits<double>::quiet_NaN(); enum EBufferAppendType { @@ -251,8 +251,8 @@ namespace LLTrace EventAccumulator() : mSum(0), - mMin(F32(NaN)), - mMax(F32(NaN)), + mMin(NaN), + mMax(NaN), mMean(NaN), mSumOfSquares(0), mNumSamples(0), @@ -288,11 +288,11 @@ namespace LLTrace void sync(F64SecondsImplicit) {} F64 getSum() const { return mSum; } - F32 getMin() const { return mMin; } - F32 getMax() const { return mMax; } + F64 getMin() const { return mMin; } + F64 getMax() const { return mMax; } F64 getLastValue() const { return mLastValue; } F64 getMean() const { return mMean; } - F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mNumSamples); } + F64 getStandardDeviation() const { return sqrt(mSumOfSquares / mNumSamples); } F64 getSumOfSquares() const { return mSumOfSquares; } S32 getSampleCount() const { return mNumSamples; } bool hasValue() const { return mNumSamples > 0; } @@ -307,7 +307,7 @@ namespace LLTrace F64 mMean, mSumOfSquares; - F32 mMin, + F64 mMin, mMax; S32 mNumSamples; @@ -322,8 +322,8 @@ namespace LLTrace SampleAccumulator() : mSum(0), - mMin(F32(NaN)), - mMax(F32(NaN)), + mMin(NaN), + mMax(NaN), mMean(NaN), mSumOfSquares(0), mLastSampleTimeStamp(0), @@ -378,11 +378,11 @@ namespace LLTrace } F64 getSum() const { return mSum; } - F32 getMin() const { return mMin; } - F32 getMax() const { return mMax; } + F64 getMin() const { return mMin; } + F64 getMax() const { return mMax; } F64 getLastValue() const { return mLastValue; } F64 getMean() const { return mMean; } - F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mTotalSamplingTime); } + F64 getStandardDeviation() const { return sqrt(mSumOfSquares / mTotalSamplingTime); } F64 getSumOfSquares() const { return mSumOfSquares; } F64SecondsImplicit getSamplingTime() const { return mTotalSamplingTime; } S32 getSampleCount() const { return mNumSamples; } @@ -402,7 +402,7 @@ namespace LLTrace mLastSampleTimeStamp, mTotalSamplingTime; - F32 mMin, + F64 mMin, mMax; S32 mNumSamples; @@ -522,9 +522,9 @@ namespace LLTrace struct BlockTimerStackRecord { - class BlockTimer* mActiveTimer; - class BlockTimerStatHandle* mTimeBlock; - U64 mChildTime; + class BlockTimer* mActiveTimer{ nullptr }; + class BlockTimerStatHandle* mTimeBlock{ nullptr }; + U64 mChildTime{ 0 }; }; struct AccumulatorBufferGroup : public LLRefCount diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index 1ec83be7cb..c23adca7e8 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -229,7 +229,7 @@ F32 Recording::getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& s update(); const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL; - return (F32)(accumulator.mCalls + (active_accumulator ? active_accumulator->mCalls : 0)) / mElapsedSeconds.value(); + return (F32)(accumulator.mCalls + (active_accumulator ? active_accumulator->mCalls : 0)) / (F32)mElapsedSeconds.value(); } bool Recording::hasValue(const StatType<CountAccumulator>& stat) @@ -296,11 +296,11 @@ F64 Recording::getMean( const StatType<SampleAccumulator>& stat ) const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL; if (active_accumulator && active_accumulator->hasValue()) { - F32 t = 0.0f; + F64 t = 0.0; S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount(); if (div > 0) { - t = active_accumulator->getSampleCount() / div; + t = (F64)active_accumulator->getSampleCount() / (F64)div; } return lerp(accumulator.getMean(), active_accumulator->getMean(), t); } @@ -319,7 +319,7 @@ F64 Recording::getStandardDeviation( const StatType<SampleAccumulator>& stat ) if (active_accumulator && active_accumulator->hasValue()) { F64 sum_of_squares = SampleAccumulator::mergeSumsOfSquares(accumulator, *active_accumulator); - return sqrtf(sum_of_squares / (accumulator.getSamplingTime() + active_accumulator->getSamplingTime())); + return sqrt(sum_of_squares / (F64)(accumulator.getSamplingTime() + active_accumulator->getSamplingTime())); } else { @@ -382,11 +382,11 @@ F64 Recording::getMean( const StatType<EventAccumulator>& stat ) const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL; if (active_accumulator && active_accumulator->hasValue()) { - F32 t = 0.0f; + F64 t = 0.0; S32 div = accumulator.getSampleCount() + active_accumulator->getSampleCount(); if (div > 0) { - t = active_accumulator->getSampleCount() / div; + t = (F64)active_accumulator->getSampleCount() / (F64)div; } return lerp(accumulator.getMean(), active_accumulator->getMean(), t); } @@ -405,7 +405,7 @@ F64 Recording::getStandardDeviation( const StatType<EventAccumulator>& stat ) if (active_accumulator && active_accumulator->hasValue()) { F64 sum_of_squares = EventAccumulator::mergeSumsOfSquares(accumulator, *active_accumulator); - return sqrtf(sum_of_squares / (accumulator.getSampleCount() + active_accumulator->getSampleCount())); + return sqrt(sum_of_squares / (F64)(accumulator.getSampleCount() + active_accumulator->getSampleCount())); } else { diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index 985f06cd59..ad4c91d85b 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -35,6 +35,11 @@ #include "llpointer.h" #include <limits> +#ifdef LL_WINDOWS +#pragma warning(push) +#pragma warning(disable : 4244) // possible loss of data on conversions +#endif + class LLStopWatchControlsMixinCommon { public: @@ -714,4 +719,8 @@ namespace LLTrace }; } +#ifdef LL_WINDOWS +#pragma warning(pop) +#endif + #endif // LL_LLTRACERECORDING_H diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h index 83ce0d05a8..bb1408609a 100644 --- a/indra/llcommon/llunittype.h +++ b/indra/llcommon/llunittype.h @@ -31,6 +31,11 @@ #include "llpreprocessor.h" #include "llerror.h" +#ifdef LL_WINDOWS +#pragma warning(push) +#pragma warning(disable : 4244) // possible loss of data on conversions +#endif + //lightweight replacement of type traits for simple type equality check template<typename S, typename T> struct LLIsSameType @@ -846,4 +851,8 @@ LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, un typedef LLUnit<U64, ns::unit_name> U64##unit_name; \ typedef LLUnitImplicit<U64, ns::unit_name> U64##unit_name##Implicit +#ifdef LL_WINDOWS +#pragma warning(pop) +#endif + #endif //LL_UNITTYPE_H diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp index e93238f0e9..df82276cd2 100644 --- a/indra/llcommon/lluri.cpp +++ b/indra/llcommon/lluri.cpp @@ -330,7 +330,7 @@ LLURI::LLURI(const std::string& escaped_str) } } -static BOOL isDefault(const std::string& scheme, U16 port) +static bool isDefault(const std::string& scheme, U16 port) { if (scheme == "http") return port == 80; @@ -339,7 +339,7 @@ static BOOL isDefault(const std::string& scheme, U16 port) if (scheme == "ftp") return port == 21; - return FALSE; + return false; } void LLURI::parseAuthorityAndPathUsingOpaque() @@ -627,7 +627,7 @@ std::string LLURI::password() const return unescape(pass); } -BOOL LLURI::defaultPort() const +bool LLURI::defaultPort() const { return isDefault(mScheme, hostPort()); } diff --git a/indra/llcommon/lluri.h b/indra/llcommon/lluri.h index 95c119dee9..37ee0a0ac7 100644 --- a/indra/llcommon/lluri.h +++ b/indra/llcommon/lluri.h @@ -99,7 +99,7 @@ public: std::string userName() const; std::string password() const; U16 hostPort() const; // ex.: 80, will include implicit port - BOOL defaultPort() const; // true if port is default for scheme + bool defaultPort() const; // true if port is default for scheme const std::string& escapedPath() const { return mEscapedPath; } std::string path() const; // ex.: "/abc/def", includes leading slash LLSD pathArray() const; // above decoded into an array of strings diff --git a/indra/llcommon/lluriparser.cpp b/indra/llcommon/lluriparser.cpp index 2ebb7fc742..33a48d970d 100644 --- a/indra/llcommon/lluriparser.cpp +++ b/indra/llcommon/lluriparser.cpp @@ -29,12 +29,7 @@ #include "linden_common.h" #include "lluriparser.h" -#if LL_DARWIN -#include <signal.h> -#include <setjmp.h> -#endif - -LLUriParser::LLUriParser(const std::string& u) : mTmpScheme(false), mNormalizedTmp(false), mRes(0) +LLUriParser::LLUriParser(const std::string& u) : mTmpScheme(false), mNormalizedTmp(false), mRes(false) { if (u.find("://") == std::string::npos) { @@ -42,36 +37,52 @@ LLUriParser::LLUriParser(const std::string& u) : mTmpScheme(false), mNormalizedT mTmpScheme = true; } - mNormalizedUri += u.c_str(); + mNormalizedUri.append(u); mRes = parse(); } LLUriParser::~LLUriParser() { - uriFreeUriMembersA(&mUri); } -S32 LLUriParser::parse() +bool LLUriParser::parse() { - mRes = uriParseSingleUriA(&mUri, mNormalizedUri.c_str(), NULL); + try + { + auto res = boost::urls::parse_uri(mNormalizedUri); + if (res) + { + mUri = *res; + mRes = true; + } + else + { + mRes = false; + } + } + catch (const std::length_error&) + { + LL_WARNS() << "Failed to parse uri due to exceeding uri_view max_size" << LL_ENDL; + mRes = false; + } return mRes; } -const char * LLUriParser::scheme() const +const std::string& LLUriParser::scheme() const { - return mScheme.c_str(); + return mScheme; } -void LLUriParser::sheme(const std::string& s) +void LLUriParser::scheme(const std::string& s) { mTmpScheme = !s.size(); mScheme = s; } -const char * LLUriParser::port() const +const std::string& LLUriParser::port() const { - return mPort.c_str(); + return mPort; } void LLUriParser::port(const std::string& s) @@ -79,9 +90,9 @@ void LLUriParser::port(const std::string& s) mPort = s; } -const char * LLUriParser::host() const +const std::string& LLUriParser::host() const { - return mHost.c_str(); + return mHost; } void LLUriParser::host(const std::string& s) @@ -89,9 +100,9 @@ void LLUriParser::host(const std::string& s) mHost = s; } -const char * LLUriParser::path() const +const std::string& LLUriParser::path() const { - return mPath.c_str(); + return mPath; } void LLUriParser::path(const std::string& s) @@ -99,9 +110,9 @@ void LLUriParser::path(const std::string& s) mPath = s; } -const char * LLUriParser::query() const +const std::string& LLUriParser::query() const { - return mQuery.c_str(); + return mQuery; } void LLUriParser::query(const std::string& s) @@ -109,9 +120,9 @@ void LLUriParser::query(const std::string& s) mQuery = s; } -const char * LLUriParser::fragment() const +const std::string& LLUriParser::fragment() const { - return mFragment.c_str(); + return mFragment; } void LLUriParser::fragment(const std::string& s) @@ -119,19 +130,6 @@ void LLUriParser::fragment(const std::string& s) mFragment = s; } -void LLUriParser::textRangeToString(UriTextRangeA& textRange, std::string& str) -{ - if (textRange.first != NULL && textRange.afterLast != NULL && textRange.first < textRange.afterLast) - { - const ptrdiff_t len = textRange.afterLast - textRange.first; - str.assign(textRange.first, static_cast<std::string::size_type>(len)); - } - else - { - str = LLStringUtil::null; - } -} - void LLUriParser::extractParts() { if (mTmpScheme || mNormalizedTmp) @@ -140,96 +138,24 @@ void LLUriParser::extractParts() } else { - textRangeToString(mUri.scheme, mScheme); + mScheme = mUri.scheme(); } - textRangeToString(mUri.hostText, mHost); - textRangeToString(mUri.portText, mPort); - textRangeToString(mUri.query, mQuery); - textRangeToString(mUri.fragment, mFragment); - - UriPathSegmentA * pathHead = mUri.pathHead; - while (pathHead) - { - std::string partOfPath; - textRangeToString(pathHead->text, partOfPath); - - mPath += '/'; - mPath += partOfPath; - - pathHead = pathHead->next; - } + mHost = mUri.host(); + mPort = mUri.port(); + mQuery = mUri.query(); + mFragment = mUri.fragment(); + mPath = mUri.path(); } -#if LL_DARWIN -typedef void(*sighandler_t)(int); -jmp_buf return_to_normalize; -static int sLastSignal = 0; -void uri_signal_handler(int signal) -{ - sLastSignal = signal; - // Apparently signal handler throwing an exception doesn't work. - // This is ugly and unsafe due to not unwinding content of uriparser library, - // but unless we have a way to catch this as NSexception, jump appears to be the only option. - longjmp(return_to_normalize, 1 /*setjmp will return this value*/); -} -#endif - -S32 LLUriParser::normalize() +bool LLUriParser::normalize() { mNormalizedTmp = mTmpScheme; - if (!mRes) + if (mRes) { -#if LL_DARWIN - sighandler_t last_sigill_handler, last_sigbus_handler; - last_sigill_handler = signal(SIGILL, &uri_signal_handler); // illegal instruction - last_sigbus_handler = signal(SIGBUS, &uri_signal_handler); - - if (setjmp(return_to_normalize)) - { - // Issue: external library crashed via signal - // If you encountered this, please try to figure out what's wrong: - // 1. Verify that library's input is 'sane' - // 2. Check if we have an NSexception to work with (unlikely) - // 3. See if passing same string causes exception to repeat - // - // Crash happens at uriNormalizeSyntaxExA - // Warning!!! This does not properly unwind stack, - // if this can be handled by NSexception, it needs to be remade - llassert(0); - - LL_WARNS() << "Uriparser crashed with " << sLastSignal << " , while processing: " << mNormalizedUri << LL_ENDL; - signal(SIGILL, last_sigill_handler); - signal(SIGBUS, last_sigbus_handler); - return 1; - } -#endif - - mRes = uriNormalizeSyntaxExA(&mUri, URI_NORMALIZE_SCHEME | URI_NORMALIZE_HOST); - -#if LL_DARWIN - signal(SIGILL, last_sigill_handler); - signal(SIGBUS, last_sigbus_handler); -#endif - - if (!mRes) - { - S32 chars_required; - mRes = uriToStringCharsRequiredA(&mUri, &chars_required); - - if (!mRes) - { - chars_required++; - std::vector<char> label_buf(chars_required); - mRes = uriToStringA(&label_buf[0], &mUri, chars_required, NULL); - - if (!mRes) - { - mNormalizedUri = &label_buf[mTmpScheme ? 7 : 0]; - mTmpScheme = false; - } - } - } + mUri.normalize_scheme().normalize_authority(); + mNormalizedUri = mUri.buffer().substr(mTmpScheme ? 7 : 0); + mTmpScheme = false; } if(mTmpScheme && mNormalizedUri.size() > 7) @@ -302,7 +228,7 @@ bool LLUriParser::test() const return uri == mNormalizedUri; } -const char * LLUriParser::normalizedUri() const +const std::string& LLUriParser::normalizedUri() const { - return mNormalizedUri.c_str(); + return mNormalizedUri; } diff --git a/indra/llcommon/lluriparser.h b/indra/llcommon/lluriparser.h index 77eb4031d5..61d613f399 100644 --- a/indra/llcommon/lluriparser.h +++ b/indra/llcommon/lluriparser.h @@ -30,7 +30,7 @@ #define LL_LLURIPARSER_H #include <string> -#include "uriparser/Uri.h" +#include "boost/url.hpp" class LL_COMMON_API LLUriParser { @@ -38,36 +38,35 @@ public: LLUriParser(const std::string& u); ~LLUriParser(); - const char * scheme() const; - void sheme (const std::string& s); + const std::string& scheme() const; + void scheme (const std::string& s); - const char * port() const; + const std::string& port() const; void port (const std::string& s); - const char * host() const; + const std::string& host() const; void host (const std::string& s); - const char * path() const; + const std::string& path() const; void path (const std::string& s); - const char * query() const; + const std::string& query() const; void query (const std::string& s); - const char * fragment() const; + const std::string& fragment() const; void fragment (const std::string& s); - const char * normalizedUri() const; + const std::string& normalizedUri() const; void extractParts(); void glue(std::string& uri) const; void glueFirst(std::string& uri, bool use_scheme = true) const; void glueSecond(std::string& uri) const; bool test() const; - S32 normalize(); + bool normalize(); private: - S32 parse(); - void textRangeToString(UriTextRangeA& textRange, std::string& str); + bool parse(); std::string mScheme; std::string mHost; std::string mPort; @@ -76,9 +75,9 @@ private: std::string mFragment; std::string mNormalizedUri; - UriUriA mUri; + boost::url mUri; - S32 mRes; + bool mRes; bool mTmpScheme; bool mNormalizedTmp; }; diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index ab66fa6ddc..3b37365ec7 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -211,20 +211,20 @@ std::string LLUUID::asString() const return str; } -BOOL LLUUID::set(const char* in_string, BOOL emit) +bool LLUUID::set(const char* in_string, bool emit) { return set(ll_safe_string(in_string), emit); } -BOOL LLUUID::set(const std::string& in_string, BOOL emit) +bool LLUUID::set(const std::string& in_string, bool emit) { - BOOL broken_format = FALSE; + bool broken_format = false; // empty strings should make NULL uuid if (in_string.empty()) { setNull(); - return TRUE; + return true; } if (in_string.length() != (UUID_STR_LENGTH - 1)) /* Flawfinder: ignore */ @@ -237,7 +237,7 @@ BOOL LLUUID::set(const std::string& in_string, BOOL emit) { LL_WARNS() << "Warning! Using broken UUID string format" << LL_ENDL; } - broken_format = TRUE; + broken_format = true; } else { @@ -248,7 +248,7 @@ BOOL LLUUID::set(const std::string& in_string, BOOL emit) LL_WARNS() << "Bad UUID string: " << in_string << LL_ENDL; } setNull(); - return FALSE; + return false; } } @@ -287,7 +287,7 @@ BOOL LLUUID::set(const std::string& in_string, BOOL emit) LL_WARNS() << "Invalid UUID string character" << LL_ENDL; } setNull(); - return FALSE; + return false; } mData[i] = mData[i] << 4; @@ -312,27 +312,27 @@ BOOL LLUUID::set(const std::string& in_string, BOOL emit) LL_WARNS() << "Invalid UUID string character" << LL_ENDL; } setNull(); - return FALSE; + return false; } cur_pos++; } - return TRUE; + return true; } -BOOL LLUUID::validate(const std::string& in_string) +bool LLUUID::validate(const std::string& in_string) { - BOOL broken_format = FALSE; + bool broken_format = false; if (in_string.length() != (UUID_STR_LENGTH - 1)) /* Flawfinder: ignore */ { // I'm a moron. First implementation didn't have the right UUID format. if (in_string.length() == (UUID_STR_LENGTH - 2)) /* Flawfinder: ignore */ { - broken_format = TRUE; + broken_format = true; } else { - return FALSE; + return false; } } @@ -360,7 +360,7 @@ BOOL LLUUID::validate(const std::string& in_string) } else { - return FALSE; + return false; } cur_pos++; @@ -376,11 +376,11 @@ BOOL LLUUID::validate(const std::string& in_string) } else { - return FALSE; + return false; } cur_pos++; } - return TRUE; + return true; } const LLUUID& LLUUID::operator^=(const LLUUID& rhs) @@ -510,7 +510,7 @@ S32 LLUUID::getNodeID(unsigned char* node_id) } #elif LL_DARWIN -// Mac OS X version of the UUID generation code... +// macOS version of the UUID generation code... /* * Get an ethernet hardware address, if we can find it... */ @@ -736,12 +736,12 @@ void LLUUID::getCurrentTime(uuid_time_t* timestamp) static uuid_time_t time_last; static U32 uuids_this_tick; - static BOOL init = FALSE; + static bool init = false; if (!init) { getSystemTime(&time_last); uuids_this_tick = uuids_per_tick; - init = TRUE; + init = true; mMutex = new LLMutex(); } @@ -889,11 +889,11 @@ U32 LLUUID::getRandomSeed() return U32(seed64) ^ U32(seed64 >> 32); } -BOOL LLUUID::parseUUID(const std::string& buf, LLUUID* value) +bool LLUUID::parseUUID(const std::string& buf, LLUUID* value) { if (buf.empty() || value == NULL) { - return FALSE; + return false; } std::string temp(buf); @@ -901,9 +901,9 @@ BOOL LLUUID::parseUUID(const std::string& buf, LLUUID* value) if (LLUUID::validate(temp)) { value->set(temp); - return TRUE; + return true; } - return FALSE; + return false; } //static @@ -989,7 +989,7 @@ bool LLUUID::operator!=(const LLUUID& rhs) const } */ -BOOL LLUUID::notNull() const +bool LLUUID::notNull() const { U32* word = (U32*)mData; return (word[0] | word[1] | word[2] | word[3]) > 0; @@ -997,10 +997,10 @@ BOOL LLUUID::notNull() const // Faster than == LLUUID::null because doesn't require // as much memory access. -BOOL LLUUID::isNull() const +bool LLUUID::isNull() const { U32* word = (U32*)mData; - // If all bits are zero, return !0 == TRUE + // If all bits are zero, return !0 == true return !(word[0] | word[1] | word[2] | word[3]); } diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h index eea5e39c61..bd4edc7993 100644 --- a/indra/llcommon/lluuid.h +++ b/indra/llcommon/lluuid.h @@ -37,8 +37,8 @@ class LLMutex; const S32 UUID_BYTES = 16; const S32 UUID_WORDS = 4; -const S32 UUID_STR_LENGTH = 37; // actually wrong, should be 36 and use size below -const S32 UUID_STR_SIZE = 37; +const S32 UUID_STR_LENGTH = 37; // number of bytes needed to store a UUID as a string +const S32 UUID_STR_SIZE = 36; // .size() of a UUID in a std::string const S32 UUID_BASE85_LENGTH = 21; // including the trailing NULL. struct uuid_time_t { @@ -65,8 +65,8 @@ public: static LLUUID generateNewID(std::string stream = ""); //static version of above for use in initializer expressions such as constructor params, etc. - BOOL set(const char *in_string, BOOL emit = TRUE); // Convert from string, if emit is FALSE, do not emit warnings - BOOL set(const std::string& in_string, BOOL emit = TRUE); // Convert from string, if emit is FALSE, do not emit warnings + bool set(const char *in_string, bool emit = true); // Convert from string, if emit is false, do not emit warnings + bool set(const std::string& in_string, bool emit = true); // Convert from string, if emit is false, do not emit warnings void setNull(); // Faster than setting to LLUUID::null. S32 cmpTime(uuid_time_t *t1, uuid_time_t *t2); @@ -76,14 +76,12 @@ public: // // ACCESSORS // - BOOL isNull() const; // Faster than comparing to LLUUID::null. - BOOL notNull() const; // Faster than comparing to LLUUID::null. + bool isNull() const; // Faster than comparing to LLUUID::null. + bool notNull() const; // Faster than comparing to LLUUID::null. // JC: This is dangerous. It allows UUIDs to be cast automatically // to integers, among other things. Use isNull() or notNull(). // operator bool() const; - // JC: These must return real bool's (not BOOLs) or else use of the STL - // will generate bool-to-int performance warnings. bool operator==(const LLUUID &rhs) const; bool operator!=(const LLUUID &rhs) const; bool operator<(const LLUUID &rhs) const; @@ -124,7 +122,7 @@ public: return tmp[0] ^ tmp[1]; } - static BOOL validate(const std::string& in_string); // Validate that the UUID string is legal. + static bool validate(const std::string& in_string); // Validate that the UUID string is legal. static const LLUUID null; static LLMutex * mMutex; @@ -132,7 +130,7 @@ public: static U32 getRandomSeed(); static S32 getNodeID(unsigned char * node_id); - static BOOL parseUUID(const std::string& buf, LLUUID* value); + static bool parseUUID(const std::string& buf, LLUUID* value); U8 mData[UUID_BYTES]; }; @@ -153,7 +151,7 @@ struct lluuid_less { bool operator()(const LLUUID& lhs, const LLUUID& rhs) const { - return (lhs < rhs) ? true : false; + return lhs < rhs; } }; diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp index 67df2b5840..b751c95679 100644 --- a/indra/llcommon/llworkerthread.cpp +++ b/indra/llcommon/llworkerthread.cpp @@ -284,7 +284,7 @@ bool LLWorkerClass::yield() mWorkerThread->checkPause(); bool res; mMutex.lock(); - res = (getFlags() & WCF_ABORT_REQUESTED) ? true : false; + res = (getFlags() & WCF_ABORT_REQUESTED) != 0; mMutex.unlock(); return res; } diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h index 01c96852d3..2a68584ab3 100644 --- a/indra/llcommon/llworkerthread.h +++ b/indra/llcommon/llworkerthread.h @@ -137,7 +137,7 @@ public: LLWorkerClass(LLWorkerThread* workerthread, const std::string& name); virtual ~LLWorkerClass(); - // pure virtual, called from WORKER THREAD, returns TRUE if done + // pure virtual, called from WORKER THREAD, returns true if done virtual bool doWork(S32 param)=0; // Called from WorkRequest::processRequest() // virtual, called from finishRequest() after completed or aborted virtual void finishWork(S32 param, bool completed); // called from finishRequest() (WORK THREAD) @@ -178,7 +178,7 @@ private: void clearFlags(U32 flags) { mWorkFlags = mWorkFlags & ~flags; } U32 getFlags() { return mWorkFlags; } public: - bool getFlags(U32 flags) { return mWorkFlags & flags ? true : false; } + bool getFlags(U32 flags) { return (mWorkFlags & flags) != 0; } private: // pure virtuals diff --git a/indra/llcommon/tests/commonmisc_test.cpp b/indra/llcommon/tests/commonmisc_test.cpp index 3deb864c0c..0057a1f639 100644 --- a/indra/llcommon/tests/commonmisc_test.cpp +++ b/indra/llcommon/tests/commonmisc_test.cpp @@ -67,7 +67,7 @@ namespace tut std::ostringstream resp; resp << "{'connect':true, 'position':[r128,r128,r128], 'look_at':[r0,r1,r0], 'agent_access':'M', 'region_x':i8192, 'region_y':i8192}"; std::string str = resp.str(); - LLMemoryStream mstr((U8*)str.c_str(), str.size()); + LLMemoryStream mstr((U8*)str.c_str(), static_cast<S32>(str.size())); LLSD response; S32 count = LLSDSerialize::fromNotation(response, mstr, str.size()); ensure("stream parsed", response.isDefined()); @@ -252,7 +252,7 @@ namespace tut resp << "{'label':'short binary test', 'singlebinary':b(1)\"A\", 'singlerawstring':s(1)\"A\", 'endoftest':'end' }"; std::string str = resp.str(); LLSD sd; - LLMemoryStream mstr((U8*)str.c_str(), str.size()); + LLMemoryStream mstr((U8*)str.c_str(), static_cast<S32>(str.size())); S32 count = LLSDSerialize::fromNotation(sd, mstr, str.size()); ensure_equals("parse count", count, 5); ensure("sd created", sd.isDefined()); @@ -456,7 +456,7 @@ namespace tut void mem_object::test<1>() { const char HELLO_WORLD[] = "hello world"; - LLMemoryStream mem((U8*)&HELLO_WORLD[0], strlen(HELLO_WORLD)); /* Flawfinder: ignore */ + LLMemoryStream mem((U8*)&HELLO_WORLD[0], static_cast<S32>(strlen(HELLO_WORLD))); /* Flawfinder: ignore */ std::string hello; std::string world; mem >> hello >> world; diff --git a/indra/llcommon/tests/lleventdispatcher_test.cpp b/indra/llcommon/tests/lleventdispatcher_test.cpp index a99acba848..44f772e322 100644 --- a/indra/llcommon/tests/lleventdispatcher_test.cpp +++ b/indra/llcommon/tests/lleventdispatcher_test.cpp @@ -491,7 +491,7 @@ namespace tut // Partial defaults arrays. for (LLSD::String a: ab) { - LLSD::Integer partition(std::min(partial_offset, dft_array_full[a].size())); + LLSD::Integer partition(static_cast<LLSD::Integer>(std::min(partial_offset, dft_array_full[a].size()))); dft_array_partial[a] = llsd_copy_array(dft_array_full[a].beginArray() + partition, dft_array_full[a].endArray()); @@ -508,7 +508,7 @@ namespace tut // (params, dft_array_full). Part of the point of using map-style // defaults is to allow any subset of the target function's // parameters to be optional, not just the rightmost. - for (LLSD::Integer ix = 0, ixend = params[a].size(); ix < ixend; ix += 2) + for (LLSD::Integer ix = 0, ixend = static_cast<LLSD::Integer>(params[a].size()); ix < ixend; ix += 2) { dft_map_partial[a][params[a][ix].asString()] = dft_array_full[a][ix]; } @@ -696,7 +696,7 @@ namespace tut LLSD zipmap(const LLSD& keys, const LLSD& values) { LLSD map; - for (LLSD::Integer i = 0, iend = keys.size(); i < iend; ++i) + for (LLSD::Integer i = 0, iend = static_cast<LLSD::Integer>(keys.size()); i < iend; ++i) { // Have to select asString() since you can index an LLSD // object with either String or Integer. @@ -955,7 +955,7 @@ namespace tut allreq[a] = zipmap(params[a], LLSD::emptyArray()); // Same for leftreq, save that we use the subset of the params not // supplied by dft_array_partial[a]. - LLSD::Integer partition(params[a].size() - dft_array_partial[a].size()); + LLSD::Integer partition(static_cast<LLSD::Integer>(params[a].size() - dft_array_partial[a].size())); leftreq[a] = zipmap(llsd_copy_array(params[a].beginArray(), params[a].beginArray() + partition), LLSD::emptyArray()); diff --git a/indra/llcommon/tests/lleventfilter_test.cpp b/indra/llcommon/tests/lleventfilter_test.cpp index a01d7fe415..d7b80e2545 100644 --- a/indra/llcommon/tests/lleventfilter_test.cpp +++ b/indra/llcommon/tests/lleventfilter_test.cpp @@ -81,13 +81,13 @@ class TestEventThrottle: public LLEventThrottleBase public: TestEventThrottle(F32 interval): LLEventThrottleBase(interval), - mAlarmRemaining(-1), - mTimerRemaining(-1) + mAlarmRemaining(-1.f), + mTimerRemaining(-1.f) {} TestEventThrottle(LLEventPump& source, F32 interval): LLEventThrottleBase(source, interval), - mAlarmRemaining(-1), - mTimerRemaining(-1) + mAlarmRemaining(-1.f), + mTimerRemaining(-1.f) {} /*----- implementation of LLEventThrottleBase timing functionality -----*/ @@ -100,12 +100,12 @@ public: virtual bool alarmRunning() const /*override*/ { // decrementing to exactly 0 should mean the alarm fires - return mAlarmRemaining > 0; + return mAlarmRemaining > 0.f; } virtual void alarmCancel() /*override*/ { - mAlarmRemaining = -1; + mAlarmRemaining = -1.f; } virtual void timerSet(F32 interval) /*override*/ @@ -116,7 +116,7 @@ public: virtual F32 timerGetRemaining() const /*override*/ { // LLTimer.getRemainingTimeF32() never returns negative; 0.0 means expired - return (mTimerRemaining > 0.0)? mTimerRemaining : 0.0; + return (mTimerRemaining > 0.0f)? mTimerRemaining : 0.0f; } /*------------------- methods for manipulating time --------------------*/ diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp index 56fdc51e82..fae9f7023f 100644 --- a/indra/llcommon/tests/llsdserialize_test.cpp +++ b/indra/llcommon/tests/llsdserialize_test.cpp @@ -701,7 +701,7 @@ namespace tut "<key>cam</key><real>1.23</real>" "</map></llsd>", v, - v.size() + 1); + static_cast<S32>(v.size()) + 1); } template<> template<> @@ -721,7 +721,7 @@ namespace tut "<key>cam</key><real>1.23</real>" "</map></llsd>", v, - v.size() + 1); + static_cast<S32>(v.size()) + 1); v.clear(); v["amy"] = 23; @@ -734,7 +734,7 @@ namespace tut "<key>cam</key><real>1.23</real>" "</map></llsd>", v, - v.size() + 1); + static_cast<S32>(v.size()) + 1); v.clear(); v["amy"] = 23; @@ -751,7 +751,7 @@ namespace tut "<key>cam</key><real>1.23</real>" "</map></llsd>", v, - v.size() + 1); + static_cast<S32>(v.size()) + 1); v.clear(); v[0] = 23; @@ -766,7 +766,7 @@ namespace tut "<real>1.23</real>" "</array></llsd>", v, - v.size() + 1); + static_cast<S32>(v.size()) + 1); v.clear(); v[0] = 23; @@ -782,7 +782,7 @@ namespace tut "<real>1.23</real>" "</array></llsd>", v, - v.size() + 1); + static_cast<S32>(v.size()) + 1); } template<> template<> @@ -1405,13 +1405,13 @@ namespace tut uint32_t size = htonl(1); memcpy(&vec[1], &size, sizeof(uint32_t)); vec.push_back('k'); - int key_size_loc = vec.size(); + auto key_size_loc = vec.size(); size = htonl(1); // 1 too short vec.resize(vec.size() + 4); memcpy(&vec[key_size_loc], &size, sizeof(uint32_t)); vec.push_back('a'); vec.push_back('m'); vec.push_back('y'); vec.push_back('i'); - int integer_loc = vec.size(); + auto integer_loc = vec.size(); vec.resize(vec.size() + 4); uint32_t val_int = htonl(23); memcpy(&vec[integer_loc], &val_int, sizeof(uint32_t)); @@ -1473,7 +1473,7 @@ namespace tut memcpy(&vec[1], &size, sizeof(uint32_t)); vec.push_back('"'); vec.push_back('a'); vec.push_back('m'); vec.push_back('y'); vec.push_back('"'); vec.push_back('i'); - int integer_loc = vec.size(); + auto integer_loc = vec.size(); vec.resize(vec.size() + 4); uint32_t val_int = htonl(23); memcpy(&vec[integer_loc], &val_int, sizeof(uint32_t)); @@ -1809,7 +1809,7 @@ namespace tut std::string q("\""); std::string qPYTHON(q + PYTHON + q); std::string qscript(q + scriptfile.getName() + q); - int rc = _spawnl(_P_WAIT, PYTHON.c_str(), qPYTHON.c_str(), qscript.c_str(), + int rc = (int)_spawnl(_P_WAIT, PYTHON.c_str(), qPYTHON.c_str(), qscript.c_str(), std::forward<ARGS>(args)..., NULL); if (rc == -1) { diff --git a/indra/llcommon/tests/llstring_test.cpp b/indra/llcommon/tests/llstring_test.cpp index 3fadfa5334..b18712b8e9 100644 --- a/indra/llcommon/tests/llstring_test.cpp +++ b/indra/llcommon/tests/llstring_test.cpp @@ -80,12 +80,12 @@ namespace tut void string_index_object_t::test<3>() { std::string str("Len=5"); - ensure("isValidIndex failed", LLStringUtil::isValidIndex(str, 0) == TRUE && - LLStringUtil::isValidIndex(str, 5) == TRUE && - LLStringUtil::isValidIndex(str, 6) == FALSE); + ensure("isValidIndex failed", LLStringUtil::isValidIndex(str, 0) == true && + LLStringUtil::isValidIndex(str, 5) == true && + LLStringUtil::isValidIndex(str, 6) == false); std::string str1; - ensure("isValidIndex failed fo rempty string", LLStringUtil::isValidIndex(str1, 0) == FALSE); + ensure("isValidIndex failed fo rempty string", LLStringUtil::isValidIndex(str1, 0) == false); } template<> template<> @@ -153,10 +153,10 @@ namespace tut void string_index_object_t::test<10>() { std::string str_val("Second"); - ensure("1. isHead failed", LLStringUtil::isHead(str_val, "SecondLife Source") == TRUE); - ensure("2. isHead failed", LLStringUtil::isHead(str_val, " SecondLife Source") == FALSE); + ensure("1. isHead failed", LLStringUtil::isHead(str_val, "SecondLife Source") == true); + ensure("2. isHead failed", LLStringUtil::isHead(str_val, " SecondLife Source") == false); std::string str_val2(""); - ensure("3. isHead failed", LLStringUtil::isHead(str_val2, "") == FALSE); + ensure("3. isHead failed", LLStringUtil::isHead(str_val2, "") == false); } template<> template<> @@ -206,10 +206,10 @@ namespace tut void string_index_object_t::test<15>() { std::string str_val("Hello.\n\r\t"); - ensure("containsNonprintable failed", LLStringUtil::containsNonprintable(str_val) == TRUE); + ensure("containsNonprintable failed", LLStringUtil::containsNonprintable(str_val) == true); str_val = "ABC "; - ensure("containsNonprintable failed", LLStringUtil::containsNonprintable(str_val) == FALSE); + ensure("containsNonprintable failed", LLStringUtil::containsNonprintable(str_val) == false); } template<> template<> @@ -231,7 +231,7 @@ namespace tut template<> template<> void string_index_object_t::test<17>() { - BOOL value; + bool value; std::string str_val("1"); ensure("convertToBOOL 1 failed", LLStringUtil::convertToBOOL(str_val, value) && value); str_val = "T"; @@ -457,17 +457,17 @@ namespace tut std::string lhs_str("PROgraM12files"); std::string rhs_str("PROgram12Files"); ensure("compareDict 1 failed", LLStringUtil::compareDict(lhs_str, rhs_str) < 0); - ensure("precedesDict 1 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == TRUE); + ensure("precedesDict 1 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == true); lhs_str = "PROgram12Files"; rhs_str = "PROgram12Files"; ensure("compareDict 2 failed", LLStringUtil::compareDict(lhs_str, rhs_str) == 0); - ensure("precedesDict 2 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == FALSE); + ensure("precedesDict 2 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == false); lhs_str = "PROgram12Files"; rhs_str = "PROgRAM12FILES"; ensure("compareDict 3 failed", LLStringUtil::compareDict(lhs_str, rhs_str) > 0); - ensure("precedesDict 3 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == FALSE); + ensure("precedesDict 3 failed", LLStringUtil::precedesDict(lhs_str, rhs_str) == false); } template<> template<> diff --git a/indra/llcommon/tests/lltrace_test.cpp b/indra/llcommon/tests/lltrace_test.cpp index 8851f87b91..923a67ac8e 100644 --- a/indra/llcommon/tests/lltrace_test.cpp +++ b/indra/llcommon/tests/lltrace_test.cpp @@ -32,6 +32,10 @@ #include "lltracerecording.h" #include "../test/lltut.h" +#ifdef LL_WINDOWS +#pragma warning(disable : 4244) // possible loss of data on conversions +#endif + namespace LLUnits { // using powers of 2 to allow strict floating point equality diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp index 49f2d3085a..98a58eb47e 100644 --- a/indra/llcommon/tests/llunits_test.cpp +++ b/indra/llcommon/tests/llunits_test.cpp @@ -262,7 +262,7 @@ namespace tut F32 float_val = quatloos_implicit; ensure("implicit units convert implicitly to regular values", float_val == 16); - S32 int_val = quatloos_implicit; + S32 int_val = (S32)quatloos_implicit; ensure("implicit units convert implicitly to regular values", int_val == 16); // conversion of implicits diff --git a/indra/llcommon/tests/threadsafeschedule_test.cpp b/indra/llcommon/tests/threadsafeschedule_test.cpp index f2f17dd2e6..5e5d6e1259 100644 --- a/indra/llcommon/tests/threadsafeschedule_test.cpp +++ b/indra/llcommon/tests/threadsafeschedule_test.cpp @@ -47,11 +47,11 @@ namespace tut // the timestamp for each one -- but since we're passing explicit // timestamps, make the queue reorder them. auto now{ Queue::Clock::now() }; - queue.push(Queue::TimeTuple(now + 200ms, "ghi")); + queue.push(Queue::TimeTuple(now + 200ms, "ghi"s)); // Given the various push() overloads, you have to match the type // exactly: conversions are ambiguous. - queue.push("abc"s); - queue.push(now + 100ms, "def"); + queue.push(now, "abc"s); + queue.push(now + 100ms, "def"s); queue.close(); auto entry = queue.pop(); ensure_equals("failed to pop first", std::get<0>(entry), "abc"s); diff --git a/indra/llcommon/threadpool.cpp b/indra/llcommon/threadpool.cpp index 302bbe6f8d..451e60c083 100644 --- a/indra/llcommon/threadpool.cpp +++ b/indra/llcommon/threadpool.cpp @@ -110,6 +110,10 @@ void LL::ThreadPoolBase::start() LL::ThreadPoolBase::~ThreadPoolBase() { close(); + if (!LLEventPumps::wasDeleted()) + { + LLEventPumps::instance().obtain("LLApp").stopListening(mName); + } } void LL::ThreadPoolBase::close() |