diff options
Diffstat (limited to 'indra/llcommon')
134 files changed, 2519 insertions, 2453 deletions
| diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 5f4ed2fffa..a504e71340 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) @@ -20,8 +18,6 @@ set(llcommon_SOURCE_FILES      commoncontrol.cpp      indra_constants.cpp      lazyeventapi.cpp -    llallocator.cpp -    llallocator_heap_profile.cpp      llapp.cpp      llapr.cpp      llassettype.cpp @@ -30,7 +26,6 @@ set(llcommon_SOURCE_FILES      llbase64.cpp      llbitpack.cpp      llcallbacklist.cpp -    llcallstack.cpp      llcleanup.cpp      llcommon.cpp      llcommonutils.cpp @@ -124,13 +119,12 @@ set(llcommon_HEADER_FILES      commoncontrol.h      ctype_workaround.h      fix_macros.h +    fsyspath.h      function_types.h      indra_constants.h      lazyeventapi.h      linden_common.h      llalignedarray.h -    llallocator.h -    llallocator_heap_profile.h      llapp.h      llapr.h      llassettype.h @@ -140,7 +134,6 @@ set(llcommon_HEADER_FILES      llbitpack.h      llboost.h      llcallbacklist.h -    llcallstack.h      llcleanup.h      llcommon.h      llcommonutils.h @@ -194,6 +187,7 @@ set(llcommon_HEADER_FILES      llmetrics.h      llmetricperformancetester.h      llmortician.h +    llmutex.h      llnametable.h      llpointer.h      llprofiler.h @@ -247,7 +241,6 @@ set(llcommon_HEADER_FILES      lluriparser.h      lluuid.h      llwin32headers.h -    llwin32headerslean.h      llworkerthread.h      hbxxh.h      lockstatic.h @@ -268,6 +261,10 @@ if (DARWIN)    list(APPEND llcommon_SOURCE_FILES llsys_objc.mm)  endif (DARWIN) +if (USE_TRACY) +  list(APPEND llcommon_SOURCE_FILES llprofiler.cpp) +endif () +  list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES})  add_library (llcommon ${llcommon_SOURCE_FILES}) @@ -276,10 +273,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/fsyspath.h b/indra/llcommon/fsyspath.h new file mode 100644 index 0000000000..e9c96edce3 --- /dev/null +++ b/indra/llcommon/fsyspath.h @@ -0,0 +1,83 @@ +/** + * @file   fsyspath.h + * @author Nat Goodspeed + * @date   2024-04-03 + * @brief  Adapt our UTF-8 std::strings for std::filesystem::path + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Copyright (c) 2024, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_FSYSPATH_H) +#define LL_FSYSPATH_H + +#include <filesystem> + +// While std::filesystem::path can be directly constructed from std::string on +// both Posix and Windows, that's not what we want on Windows. Per +// https://en.cppreference.com/w/cpp/filesystem/path/path: + +// ... the method of conversion to the native character set depends on the +// character type used by source. +// +// * If the source character type is char, the encoding of the source is +//   assumed to be the native narrow encoding (so no conversion takes place on +//   POSIX systems). +// * If the source character type is char8_t, conversion from UTF-8 to native +//   filesystem encoding is used. (since C++20) +// * If the source character type is wchar_t, the input is assumed to be the +//   native wide encoding (so no conversion takes places on Windows). + +// The trouble is that on Windows, from std::string ("source character type is +// char"), the "native narrow encoding" isn't UTF-8, so file paths containing +// non-ASCII characters get mangled. +// +// Once we're building with C++20, we could pass a UTF-8 std::string through a +// vector<char8_t> to engage std::filesystem::path's own UTF-8 conversion. But +// sigh, as of 2024-04-03 we're not yet there. +// +// Anyway, encapsulating the important UTF-8 conversions in our own subclass +// allows us to migrate forward to C++20 conventions without changing +// referencing code. + +class fsyspath: public std::filesystem::path +{ +    using super = std::filesystem::path; + +public: +    // default +    fsyspath() {} +    // construct from UTF-8 encoded std::string +    fsyspath(const std::string& path): super(std::filesystem::u8path(path)) {} +    // construct from UTF-8 encoded const char* +    fsyspath(const char* path): super(std::filesystem::u8path(path)) {} +    // construct from existing path +    fsyspath(const super& path): super(path) {} + +    fsyspath& operator=(const super& p) { super::operator=(p); return *this; } +    fsyspath& operator=(const std::string& p) +    { +        super::operator=(std::filesystem::u8path(p)); +        return *this; +    } +    fsyspath& operator=(const char* p) +    { +        super::operator=(std::filesystem::u8path(p)); +        return *this; +    } + +    // shadow base-class string() method with UTF-8 aware method +    std::string string() const +    { +        auto u8 = super::u8string(); +        return std::string(u8.begin(), u8.end()); +    } +    // On Posix systems, where value_type is already char, this operator +    // std::string() method shadows the base class operator string_type() +    // method. But on Windows, where value_type is wchar_t, the base class +    // doesn't have operator std::string(). Provide it. +    operator std::string() const { return string(); } +}; + +#endif /* ! defined(LL_FSYSPATH_H) */ diff --git a/indra/llcommon/hexdump.h b/indra/llcommon/hexdump.h new file mode 100755 index 0000000000..ab5ba2b16d --- /dev/null +++ b/indra/llcommon/hexdump.h @@ -0,0 +1,106 @@ +/** + * @file   hexdump.h + * @author Nat Goodspeed + * @date   2023-10-03 + * @brief  iostream manipulators to stream hex, or string with nonprinting chars + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Copyright (c) 2023, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_HEXDUMP_H) +#define LL_HEXDUMP_H + +#include <cctype> +#include <iomanip> +#include <iostream> +#include <string_view> + +namespace LL +{ + +// Format a given byte string as 2-digit hex values, no separators +// Usage: std::cout << hexdump(somestring) << ... +class hexdump +{ +public: +    hexdump(const std::string_view& data): +        hexdump(data.data(), data.length()) +    {} + +    hexdump(const char* data, size_t len): +        hexdump(reinterpret_cast<const unsigned char*>(data), len) +    {} + +    hexdump(const std::vector<unsigned char>& data): +        hexdump(data.data(), data.size()) +    {} + +    hexdump(const unsigned char* data, size_t len): +        mData(data, data + len) +    {} + +    friend std::ostream& operator<<(std::ostream& out, const hexdump& self) +    { +        auto oldfmt{ out.flags() }; +        auto oldfill{ out.fill() }; +        out.setf(std::ios_base::hex, std::ios_base::basefield); +        out.fill('0'); +        for (auto c : self.mData) +        { +            out << std::setw(2) << unsigned(c); +        } +        out.setf(oldfmt, std::ios_base::basefield); +        out.fill(oldfill); +        return out; +    } + +private: +    std::vector<unsigned char> mData; +}; + +// Format a given byte string as a mix of printable characters and, for each +// non-printable character, "\xnn" +// Usage: std::cout << hexmix(somestring) << ... +class hexmix +{ +public: +    hexmix(const std::string_view& data): +        mData(data) +    {} + +    hexmix(const char* data, size_t len): +        mData(data, len) +    {} + +    friend std::ostream& operator<<(std::ostream& out, const hexmix& self) +    { +        auto oldfmt{ out.flags() }; +        auto oldfill{ out.fill() }; +        out.setf(std::ios_base::hex, std::ios_base::basefield); +        out.fill('0'); +        for (auto c : self.mData) +        { +            // std::isprint() must be passed an unsigned char! +            if (std::isprint(static_cast<unsigned char>(c))) +            { +                out << c; +            } +            else +            { +                out << "\\x" << std::setw(2) << unsigned(c); +            } +        } +        out.setf(oldfmt, std::ios_base::basefield); +        out.fill(oldfill); +        return out; +    } + +private: +    std::string mData; +}; + +} // namespace LL + +#endif /* ! defined(LL_HEXDUMP_H) */ 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/llallocator.cpp b/indra/llcommon/llallocator.cpp deleted file mode 100644 index abe3779b85..0000000000 --- a/indra/llcommon/llallocator.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @file llallocator.cpp - * @brief Implementation of the LLAllocator class. - * - * $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$ - */ - -#include "linden_common.h" -#include "llallocator.h" - -// -// stub implementations for when tcmalloc is disabled -// - -void LLAllocator::setProfilingEnabled(bool should_enable) -{ -} - -// static -bool LLAllocator::isProfiling() -{ -    return false; -} - -std::string LLAllocator::getRawProfile() -{ -    return std::string(); -} - -LLAllocatorHeapProfile const & LLAllocator::getProfile() -{ -    mProf.mLines.clear(); - -    // *TODO - avoid making all these extra copies of things... -    std::string prof_text = getRawProfile(); -    //std::cout << prof_text << std::endl; -    mProf.parse(prof_text); -    return mProf; -} diff --git a/indra/llcommon/llallocator.h b/indra/llcommon/llallocator.h deleted file mode 100644 index aa3eead546..0000000000 --- a/indra/llcommon/llallocator.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @file llallocator.h - * @brief Declaration of the LLAllocator class. - * - * $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$ - */ - -#ifndef LL_LLALLOCATOR_H -#define LL_LLALLOCATOR_H - -#include <string> - -#include "llallocator_heap_profile.h" - -class LL_COMMON_API LLAllocator { -    friend class LLMemoryView; - -public: -    void setProfilingEnabled(bool should_enable); - -    static bool isProfiling(); - -    LLAllocatorHeapProfile const & getProfile(); - -private: -    std::string getRawProfile(); - -private: -    LLAllocatorHeapProfile mProf; -}; - -#endif // LL_LLALLOCATOR_H diff --git a/indra/llcommon/llallocator_heap_profile.cpp b/indra/llcommon/llallocator_heap_profile.cpp deleted file mode 100644 index 85e56b4db4..0000000000 --- a/indra/llcommon/llallocator_heap_profile.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/** - * @file llallocator_heap_profile.cpp - * @brief Implementation of the parser for tcmalloc heap profile data. - * @author Brad Kittenbrink - * - * $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$ - */ - -#include "linden_common.h" -#include "llallocator_heap_profile.h" - -#if LL_MSVC -// disable warning about boost::lexical_cast returning uninitialized data -// when it fails to parse the string -#pragma warning (disable:4701) -#pragma warning (disable:4702) -#endif - -#include <boost/algorithm/string/split.hpp> -#include <boost/bind.hpp> -#include <boost/lexical_cast.hpp> -#include <boost/range/iterator_range.hpp> - -static const std::string HEAP_PROFILE_MAGIC_STR = "heap profile:"; - -static bool is_separator(char c) -{ -    return isspace(c) || c == '[' || c == ']' || c == ':'; -} - -void LLAllocatorHeapProfile::parse(std::string const & prof_text) -{ -    // a typedef for handling a token in the string buffer -    // it's a begin/end pair of string::const_iterators -    typedef boost::iterator_range<std::string::const_iterator> range_t; - -    mLines.clear(); - -    if(prof_text.compare(0, HEAP_PROFILE_MAGIC_STR.length(), HEAP_PROFILE_MAGIC_STR) != 0) -    { -        // *TODO - determine if there should be some better error state than -        // mLines being empty. -brad -        LL_WARNS() << "invalid heap profile data passed into parser." << LL_ENDL; -        return; -    } - -    std::vector< range_t > prof_lines; - -    std::string::const_iterator prof_begin = prof_text.begin() + HEAP_PROFILE_MAGIC_STR.length(); - -    range_t prof_range(prof_begin, prof_text.end()); -    boost::algorithm::split(prof_lines, -        prof_range, -        boost::bind(std::equal_to<llwchar>(), '\n', _1)); - -    std::vector< range_t >::const_iterator i; -    for(i = prof_lines.begin(); i != prof_lines.end() && !i->empty(); ++i) -    { -        range_t const & line_text = *i; - -        std::vector<range_t> line_elems; - -        boost::algorithm::split(line_elems, -            line_text, -            is_separator); - -        std::vector< range_t >::iterator j; -        j = line_elems.begin(); - -        while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens -        llassert_always(j != line_elems.end()); -        U32 live_count = boost::lexical_cast<U32>(*j); -        ++j; - -        while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens -        llassert_always(j != line_elems.end()); -        U64 live_size = boost::lexical_cast<U64>(*j); -        ++j; - -        while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens -        llassert_always(j != line_elems.end()); -        U32 tot_count = boost::lexical_cast<U32>(*j); -        ++j; - -        while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens -        llassert_always(j != line_elems.end()); -        U64 tot_size = boost::lexical_cast<U64>(*j); -        ++j; - -        while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens -    llassert(j != line_elems.end()); -        if (j != line_elems.end()) -    { -        ++j; // skip the '@' - -        mLines.push_back(line(live_count, live_size, tot_count, tot_size)); -        line & current_line = mLines.back(); - -        for(; j != line_elems.end(); ++j) -        { -            if(!j->empty()) -            { -                U32 marker = boost::lexical_cast<U32>(*j); -                current_line.mTrace.push_back(marker); -            } -        } -    } -    } -    // *TODO - parse MAPPED_LIBRARIES section here if we're ever interested in it -} - -void LLAllocatorHeapProfile::dump(std::ostream & out) const -{ -    for (const LLAllocatorHeapProfile::line& line : mLines) -    { -        out << line.mLiveCount << ": " << line.mLiveSize << '[' << line.mTotalCount << ": " << line.mTotalSize << "] @"; - -        for (const stack_marker marker : line.mTrace) -        { -            out << ' ' << marker; -        } -        out << '\n'; -    } -    out.flush(); -} - diff --git a/indra/llcommon/llallocator_heap_profile.h b/indra/llcommon/llallocator_heap_profile.h deleted file mode 100644 index 22f284b703..0000000000 --- a/indra/llcommon/llallocator_heap_profile.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @file llallocator_heap_profile.h - * @brief Declaration of the parser for tcmalloc heap profile data. - * @author Brad Kittenbrink - * - * $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$ - */ - -#ifndef LL_LLALLOCATOR_HEAP_PROFILE_H -#define LL_LLALLOCATOR_HEAP_PROFILE_H - -#include "stdtypes.h" - -#include <map> -#include <vector> - -class LLAllocatorHeapProfile -{ -public: -    typedef int stack_marker; - -    typedef std::vector<stack_marker> stack_trace; - -    struct line { -        line(U32 live_count, U64 live_size, U32 tot_count, U64 tot_size) : -            mLiveSize(live_size), -            mTotalSize(tot_size), -            mLiveCount(live_count), -            mTotalCount(tot_count) -        { -        } -        U64 mLiveSize, mTotalSize; -        U32 mLiveCount, mTotalCount; -        stack_trace mTrace; -    }; - -    typedef std::vector<line> lines_t; - -    LLAllocatorHeapProfile() -    { -    } - -    void parse(std::string const & prof_text); - -    void dump(std::ostream & out) const; - -public: -    lines_t mLines; -}; - - -#endif // LL_LLALLOCATOR_HEAP_PROFILE_H diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 9729f68d23..08a43983d3 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,14 @@ 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; - -// Local flag for whether or not to do logging in signal handlers. -//static -BOOL LLApp::sLogInSignal = FALSE; +bool LLApp::sDisableCrashlogger = false;  // static  // Keeps track of application status @@ -207,9 +195,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) @@ -234,7 +222,7 @@ bool LLApp::parseCommandOptions(int argc, wchar_t** wargv)          if(wargv[ii][0] != '-')          {              LL_INFOS() << "Did not find option identifier while parsing token: " -                << wargv[ii] << LL_ENDL; +                << (intptr_t)wargv[ii] << LL_ENDL;              return false;          }          int offset = 1; @@ -272,9 +260,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 +314,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 +369,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 +380,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 +456,13 @@ bool LLApp::isExiting()  void LLApp::disableCrashlogger()  { -    sDisableCrashlogger = TRUE; +    sDisableCrashlogger = true;  }  // static  bool LLApp::isCrashloggerDisabled()  { -    return (sDisableCrashlogger == TRUE); +    return sDisableCrashlogger;  }  // static @@ -522,77 +475,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()  {      // @@ -682,6 +592,10 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)      // We do the somewhat sketchy operation of blocking in here until the error handler      // has gracefully stopped the app. +    // FIXME(brad) - we are using this handler for asynchronous signals as well, so sLogInSignal is currently +    // disabled for safety.  we need to find a way to selectively reenable it when it is safe. +    // see issue secondlife/viewer#2566 +      if (LLApp::sLogInSignal)      {          LL_INFOS() << "Signal handler - Got signal " << signum << " - " << apr_signal_description_get(signum) << LL_ENDL; @@ -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..3d18864b80 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]; @@ -335,8 +339,12 @@ private:      friend void default_unix_signal_handler(int signum, siginfo_t *info, void *);  #endif -public: -    static BOOL sLogInSignal; +private: +#ifdef LL_RELEASE_FOR_DOWNLOAD +    static constexpr bool sLogInSignal = false; +#else +    static constexpr bool sLogInSignal = true; +#endif  };  #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..693cd7c01f 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -34,7 +34,7 @@  #endif  #include <boost/noncopyable.hpp> -#include "llwin32headerslean.h" +#include "llwin32headers.h"  #include "apr_thread_proc.h"  #include "apr_getopt.h"  #include "apr_signal.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/llcallstack.cpp b/indra/llcommon/llcallstack.cpp deleted file mode 100644 index c0be4f598e..0000000000 --- a/indra/llcommon/llcallstack.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/** - * @file llcallstack.cpp - * @brief run-time extraction of the current callstack - * - * $LicenseInfo:firstyear=2016&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2016, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llcommon.h" -#include "llcallstack.h" -#include "StackWalker.h" -#include "llthreadlocalstorage.h" - -#if LL_WINDOWS -class LLCallStackImpl: public StackWalker -{ -public: -    LLCallStackImpl(): -        StackWalker(false,0) // non-verbose, options = 0 -    { -    } -    ~LLCallStackImpl() -    { -    } -    void getStack(std::vector<std::string>& stack, S32 skip_count=0, bool verbose=false) -    { -        m_stack.clear(); -        ShowCallstack(verbose); -        // Skip the first few lines because they're just bookkeeping for LLCallStack, -        // plus any additional lines requested to skip. -        S32 first_line = skip_count + 3; -        for (S32 i=first_line; i<m_stack.size(); ++i) -        { -            stack.push_back(m_stack[i]); -        } -    } -protected: -    virtual void OnOutput(LPCSTR szText) -    { -        m_stack.push_back(szText); -    } -    std::vector<std::string> m_stack; -}; -#else -// Stub - not implemented currently on other platforms. -class LLCallStackImpl -{ -public: -    LLCallStackImpl() {} -    ~LLCallStackImpl() {} -    void getStack(std::vector<std::string>& stack, S32 skip_count=0, bool verbose=false) -    { -        stack.clear(); -    } -}; -#endif - -LLCallStackImpl *LLCallStack::s_impl = NULL; - -LLCallStack::LLCallStack(S32 skip_count, bool verbose): -    m_skipCount(skip_count), -    m_verbose(verbose) -{ -    if (!s_impl) -    { -        s_impl = new LLCallStackImpl; -    } -    LLTimer t; -    s_impl->getStack(m_strings, m_skipCount, m_verbose); -} - -bool LLCallStack::contains(const std::string& str) -{ -    for (const std::string& src_str : m_strings) -    { -        if (src_str.find(str) != std::string::npos) -        { -            return true; -        } -    } -    return false; -} - -std::ostream& operator<<(std::ostream& s, const LLCallStack& call_stack) -{ -#ifndef LL_RELEASE_FOR_DOWNLOAD -    for (const std::string& str : call_stack.m_strings) -    { -        s << str; -    } -#else -    s << "UNAVAILABLE IN RELEASE"; -#endif -    return s; -} - -LLContextStrings::LLContextStrings() -{ -} - -// static -LLContextStrings* LLContextStrings::getThreadLocalInstance() -{ -    LLContextStrings *cons = LLThreadLocalSingletonPointer<LLContextStrings>::getInstance(); -    if (!cons) -    { -        LLThreadLocalSingletonPointer<LLContextStrings>::setInstance(new LLContextStrings); -    } -    return LLThreadLocalSingletonPointer<LLContextStrings>::getInstance(); -} - -// static -void LLContextStrings::addContextString(const std::string& str) -{ -    LLContextStrings *cons = getThreadLocalInstance(); -    //LL_INFOS() << "CTX " << (S32)cons << " ADD " << str << " CNT " << cons->m_contextStrings[str] << LL_ENDL; -    cons->m_contextStrings[str]++; -} - -// static -void LLContextStrings::removeContextString(const std::string& str) -{ -    LLContextStrings *cons = getThreadLocalInstance(); -    cons->m_contextStrings[str]--; -    //LL_INFOS() << "CTX " << (S32)cons << " REMOVE " << str << " CNT " << cons->m_contextStrings[str] << LL_ENDL; -    if (cons->m_contextStrings[str] == 0) -    { -        cons->m_contextStrings.erase(str); -    } -} - -// static -bool LLContextStrings::contains(const std::string& str) -{ -    const std::map<std::string,S32>& strings = -        LLThreadLocalSingletonPointer<LLContextStrings>::getInstance()->m_contextStrings; -    for (const std::map<std::string,S32>::value_type& str_pair : strings) -    { -        if (str_pair.first.find(str) != std::string::npos) -        { -            return true; -        } -    } -    return false; -} - -// static -void LLContextStrings::output(std::ostream& os) -{ -    const std::map<std::string,S32>& strings = -        LLThreadLocalSingletonPointer<LLContextStrings>::getInstance()->m_contextStrings; -    for (const std::map<std::string,S32>::value_type& str_pair : strings) -    { -        os << str_pair.first << "[" << str_pair.second << "]" << "\n"; -    } -} - -// static -std::ostream& operator<<(std::ostream& s, const LLContextStatus& context_status) -{ -    LLThreadLocalSingletonPointer<LLContextStrings>::getInstance()->output(s); -    return s; -} - -bool LLContextStatus::contains(const std::string& str) -{ -    return LLThreadLocalSingletonPointer<LLContextStrings>::getInstance()->contains(str); -} diff --git a/indra/llcommon/llcallstack.h b/indra/llcommon/llcallstack.h deleted file mode 100644 index ad10a9dbf7..0000000000 --- a/indra/llcommon/llcallstack.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @file llcallstack.h - * @brief run-time extraction of the current callstack - * - * $LicenseInfo:firstyear=2016&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2016, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#include <map> - -class LLCallStackImpl; - -class LLCallStack -{ -public: -    LLCallStack(S32 skip_count=0, bool verbose=false); -    std::vector<std::string> m_strings; -    bool m_verbose; -    bool contains(const std::string& str); -private: -    static LLCallStackImpl *s_impl; -    S32 m_skipCount; -}; - -LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLCallStack& call_stack); - -class LLContextStrings -{ -public: -    LLContextStrings(); -    static void addContextString(const std::string& str); -    static void removeContextString(const std::string& str); -    static void output(std::ostream& os); -    static LLContextStrings* getThreadLocalInstance(); -    static bool contains(const std::string& str); -private: -    std::map<std::string,S32> m_contextStrings; -}; - -class LLScopedContextString -{ -public: -    LLScopedContextString(const std::string& str): -        m_str(str) -    { -        LLContextStrings::addContextString(m_str); -    } -    ~LLScopedContextString() -    { -        LLContextStrings::removeContextString(m_str); -    } -private: -    std::string m_str; -}; - -// Mostly exists as a class to hook an ostream override to. -struct LLContextStatus -{ -    bool contains(const std::string& str); -}; - -LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLContextStatus& context_status); - -#define dumpStack(tag)                          \ -    LL_DEBUGS(tag) << "STACK:\n"                \ -                   << "====================\n"  \ -                   << LLCallStack()             \ -                   << "===================="    \ -                   << LL_ENDL; diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index 14bdeb5c60..84b35749cc 100644 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -54,7 +54,7 @@ void* ll_tracy_new(size_t size)      {          throw std::bad_alloc();      } -    TracyAlloc(ptr, size); +    LL_PROFILE_ALLOC(ptr, size);      return ptr;  } @@ -70,7 +70,7 @@ void* operator new[](std::size_t count)  void ll_tracy_delete(void* ptr)  { -    TracyFree(ptr); +    LL_PROFILE_FREE(ptr);      if (gProfilerEnabled)      {          //LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY; @@ -102,20 +102,20 @@ void operator delete[](void* ptr) noexcept  void *tracy_aligned_malloc(size_t size, size_t alignment)  {      auto ptr = ll_aligned_malloc_fallback(size, alignment); -    if (ptr) TracyAlloc(ptr, size); +    if (ptr) LL_PROFILE_ALLOC(ptr, size);      return ptr;  }  void tracy_aligned_free(void *memblock)  { -    TracyFree(memblock); +    LL_PROFILE_FREE(memblock);      ll_aligned_free_fallback(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 9392aa718b..5205699b92 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 67dfa1b5d1..ce42e7401a 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/lldoubledispatch.h b/indra/llcommon/lldoubledispatch.h index c8c566205a..25039c3e9c 100644 --- a/indra/llcommon/lldoubledispatch.h +++ b/indra/llcommon/lldoubledispatch.h @@ -30,7 +30,6 @@  #define LL_LLDOUBLEDISPATCH_H  #include <list> -#include <boost/shared_ptr.hpp>  #include <boost/function.hpp>  #include <boost/bind.hpp>  #include <boost/ref.hpp> diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index e4843a88eb..d834098994 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -55,6 +55,7 @@  #include "llsingleton.h"  #include "llstl.h"  #include "lltimer.h" +#include "llprofiler.h"  // On Mac, got:  // #error "Boost.Stacktrace requires `_Unwind_Backtrace` function. Define @@ -109,7 +110,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;              int syslogPriority = LOG_CRIT;              switch (level) {                  case LLError::LEVEL_DEBUG:  syslogPriority = LOG_DEBUG; break; @@ -167,7 +168,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 +235,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 +275,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 +312,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 +339,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 +507,7 @@ namespace          LLError::TimeFunction               mTimeFunction;          Recorders                           mRecorders; -        LLMutex                             mRecorderMutex; +        LL_PROFILE_MUTEX_NAMED(LLCoros::RMutex, mRecorderMutex, "Log Recorders");          int                                 mShouldLogCallCounter; @@ -529,7 +530,6 @@ namespace          mCrashFunction(NULL),          mTimeFunction(NULL),          mRecorders(), -        mRecorderMutex(),          mShouldLogCallCounter(0)      {      } @@ -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); LL_PROFILE_MUTEX_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); LL_PROFILE_MUTEX_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); LL_PROFILE_MUTEX_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); LL_PROFILE_MUTEX_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); LL_PROFILE_MUTEX_LOCK(s->mRecorderMutex);          for (LLError::RecorderPtr& r : s->mRecorders)          {              if (!r->enabled()) @@ -1280,24 +1280,21 @@ namespace  }  namespace { -    // We need a couple different mutexes, but we want to use the same mechanism -    // for both. Make getMutex() a template function with different instances -    // for different MutexDiscriminator values. -    enum MutexDiscriminator -    { -        LOG_MUTEX, -        STACKS_MUTEX -    };      // Some logging calls happen very early in processing -- so early that our      // module-static variables aren't yet initialized. getMutex() wraps a      // function-static LLMutex so that early calls can still have a valid      // LLMutex instance. -    template <MutexDiscriminator MTX> -    LLMutex* getMutex() +    auto getLogMutex() +    { +        // guaranteed to be initialized the first time control reaches here +        static LL_PROFILE_MUTEX_NAMED(std::recursive_mutex, sLogMutex, "Log Mutex"); +        return &sLogMutex; +    } +    auto getStacksMutex()      {          // guaranteed to be initialized the first time control reaches here -        static LLMutex sMutex; -        return &sMutex; +        static LL_PROFILE_MUTEX_NAMED(std::recursive_mutex, sStacksMutex, "Stacks Mutex"); +        return &sStacksMutex;      }      bool checkLevelMap(const LevelMap& map, const std::string& key, @@ -1346,9 +1343,9 @@ namespace LLError      bool Log::shouldLog(CallSite& site)      { -        LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING -        LLMutexTrylock lock(getMutex<LOG_MUTEX>(), 5); -        if (!lock.isLocked()) +        LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING; +        std::unique_lock lock(*getLogMutex(), std::try_to_lock); LL_PROFILE_MUTEX_LOCK(*getLogMutex()); +        if (!lock)          {              return false;          } @@ -1391,9 +1388,9 @@ namespace LLError      void Log::flush(const std::ostringstream& out, const CallSite& site)      { -        LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING -        LLMutexTrylock lock(getMutex<LOG_MUTEX>(),5); -        if (!lock.isLocked()) +        LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING; +        std::unique_lock lock(*getLogMutex(), std::try_to_lock); LL_PROFILE_MUTEX_LOCK(*getLogMutex()); +        if (!lock)          {              return;          } @@ -1523,8 +1520,8 @@ namespace LLError      //static      void LLCallStacks::push(const char* function, const int line)      { -        LLMutexTrylock lock(getMutex<STACKS_MUTEX>(), 5); -        if (!lock.isLocked()) +        std::unique_lock lock(*getStacksMutex(), std::try_to_lock); LL_PROFILE_MUTEX_LOCK(*getStacksMutex()); +        if (!lock)          {              return;          } @@ -1548,8 +1545,8 @@ namespace LLError      //static      void LLCallStacks::end(const std::ostringstream& out)      { -        LLMutexTrylock lock(getMutex<STACKS_MUTEX>(), 5); -        if (!lock.isLocked()) +        std::unique_lock lock(*getStacksMutex(), std::try_to_lock); LL_PROFILE_MUTEX_LOCK(*getStacksMutex()); +        if (!lock)          {              return;          } @@ -1565,8 +1562,8 @@ namespace LLError      //static      void LLCallStacks::print()      { -        LLMutexTrylock lock(getMutex<STACKS_MUTEX>(), 5); -        if (!lock.isLocked()) +        std::unique_lock lock(*getStacksMutex(), std::try_to_lock); LL_PROFILE_MUTEX_LOCK(*getStacksMutex()); +        if (!lock)          {              return;          } @@ -1607,11 +1604,11 @@ namespace LLError      std::string LLUserWarningMsg::sLocalizedOutOfMemoryWarning;      LLUserWarningMsg::Handler LLUserWarningMsg::sHandler; -    void LLUserWarningMsg::show(const std::string& message) +    void LLUserWarningMsg::show(const std::string& message, S32 error_code)      {          if (sHandler)          { -            sHandler(std::string(), message); +            sHandler(std::string(), message, error_code);          }      } @@ -1619,7 +1616,7 @@ namespace LLError      {          if (sHandler && !sLocalizedOutOfMemoryTitle.empty())          { -            sHandler(sLocalizedOutOfMemoryTitle, sLocalizedOutOfMemoryWarning); +            sHandler(sLocalizedOutOfMemoryTitle, sLocalizedOutOfMemoryWarning, ERROR_BAD_ALLOC);          }      } @@ -1630,7 +1627,7 @@ namespace LLError              "Second Life viewer couldn't access some of the files it needs and will be closed."              "\n\nPlease reinstall viewer from  https://secondlife.com/support/downloads/ and "              "contact https://support.secondlife.com if issue persists after reinstall."; -        sHandler("Missing Files", error_string); +        sHandler("Missing Files", error_string, ERROR_MISSING_FILES);      }      void LLUserWarningMsg::setHandler(const LLUserWarningMsg::Handler &handler) @@ -1644,19 +1641,3 @@ namespace LLError          sLocalizedOutOfMemoryWarning = message;      }  } - -void crashdriver(void (*callback)(int*)) -{ -    // The LLERROR_CRASH macro used to have inline code of the form: -    //int* make_me_crash = NULL; -    //*make_me_crash = 0; - -    // But compilers are getting smart enough to recognize that, so we must -    // assign to an address supplied by a separate source file. We could do -    // the assignment here in crashdriver() -- but then BugSplat would group -    // all LL_ERRS() crashes as the fault of this one function, instead of -    // identifying the specific LL_ERRS() source line. So instead, do the -    // assignment in a lambda in the caller's source. We just provide the -    // nullptr target. -    callback(nullptr); -} diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 6176ce0d1d..41893a35e5 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -308,7 +308,16 @@ namespace LLError      class LLUserWarningMsg      {      public: -        typedef std::function<void(const std::string&, const std::string&)> Handler; +        // error codes, tranlates to last_exec states like LAST_EXEC_OTHER_CRASH +        typedef enum +        { +            ERROR_OTHER = 0, +            ERROR_BAD_ALLOC = 1, +            ERROR_MISSING_FILES = 2, +        } eLastExecEvent; + +        // tittle, message and error code to include in error marker file +        typedef std::function<void(const std::string&, const std::string&, S32 error_code)> Handler;          static void setHandler(const Handler&);          static void setOutOfMemoryStrings(const std::string& title, const std::string& message); @@ -316,7 +325,7 @@ namespace LLError          static void showOutOfMemory();          static void showMissingFiles();          // Genering error -        static void show(const std::string&); +        static void show(const std::string&, S32 error_code = -1);      private:          // needs to be preallocated before viewer runs out of memory @@ -408,9 +417,11 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;  #define LL_NEWLINE '\n'  // Use this only in LL_ERRS or in a place that LL_ERRS may not be used -#define LLERROR_CRASH                                   \ -{                                                       \ -    crashdriver([](int* ptr){ *ptr = 0; exit(*ptr); }); \ +#define LLERROR_CRASH                                \ +{                                                    \ +    int* make_me_crash = (int*)0xDEADBEEFDEADBEEFUL; \ +    *make_me_crash = 0;                              \ +    exit(*make_me_crash);                            \  }  #define LL_ENDL                                         \ @@ -512,7 +523,4 @@ LL_DEBUGS("SomeTag") performs the locking and map-searching ONCE, then caches  the result in a static variable.  */ -// used by LLERROR_CRASH -void crashdriver(void (*)(int*)); -  #endif // LL_LLERROR_H diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index bf5a6df556..0a7b3d2046 100644 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -32,7 +32,6 @@  #include "llpointer.h"  #include "llrefcount.h"  #include "boost/function.hpp" -#include "boost/shared_ptr.hpp"  #include <string>  class LLSD; @@ -190,7 +189,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 +197,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..4bf1fa07a2 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -38,16 +38,8 @@  #include <vector>  #include <deque>  #include <functional> -#if LL_WINDOWS -    #pragma warning (push) -    #pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch -    #pragma warning (disable : 4264) -#endif -#include <boost/signals2.hpp> -#if LL_WINDOWS -    #pragma warning (pop) -#endif +#include <boost/signals2.hpp>  #include <boost/bind.hpp>  #include <boost/utility.hpp>        // noncopyable  #include <boost/optional/optional.hpp> @@ -61,6 +53,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 +594,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..d0bc8f7652 100644 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -27,20 +27,20 @@   * $/LicenseInfo$   */ +#include "linden_common.h" +#include "llfile.h" +#include "llstring.h" +#include "llerror.h" +#include "stringize.h" +  #if LL_WINDOWS -#include "llwin32headerslean.h" +#include "llwin32headers.h"  #include <stdlib.h>                 // Windows errno  #include <vector>  #else  #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)  { @@ -275,7 +293,7 @@ int LLFile::rename(const std::string& filename, const std::string& newname, int      return warnif(STRINGIZE("rename to '" << newname << "' from"), filename, rc, supress_error);  } -bool LLFile::copy(const std::string from, const std::string to) +bool LLFile::copy(const std::string& from, const std::string& to)  {      bool copied = false;      LLFILE* in = LLFile::fopen(from, "rb");     /* Flawfinder: ignore */ @@ -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 = '/'; @@ -406,7 +424,7 @@ LLFILE *    LLFile::_Fiopen(const std::string& filename,      if (valid[n] == 0)          return (0); // no valid mode -    else if (norepflag && mode & (ios_base::out || ios_base::app) +    else if (norepflag && mode & (ios_base::out | ios_base::app)          && (fp = LLFile::fopen(filename, "r")) != 0)    /* Flawfinder: ignore */          {   // file must not exist, close and fail          fclose(fp); diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h index 08a008c19a..1661cbeb55 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. @@ -75,7 +77,7 @@ public:      static  int     rmdir(const std::string& filename);      static  int     remove(const std::string& filename, int supress_error = 0);      static  int     rename(const std::string& filename,const std::string& newname, int supress_error = 0); -    static  bool    copy(const std::string from, const std::string to); +    static  bool    copy(const std::string& from, const std::string& to);      static  int     stat(const std::string& filename,llstat*    file_status);      static  bool    isdir(const std::string&    filename); @@ -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); @@ -158,7 +160,7 @@ private:   *  Does The Right Thing when passed a non-ASCII pathname. Sadly, that isn't   *  true of Microsoft's std::ifstream.   */ -class LL_COMMON_API llifstream  :   public  std::ifstream +class LL_COMMON_API llifstream : public std::ifstream  {      // input stream associated with a C stream    public: @@ -203,7 +205,7 @@ class LL_COMMON_API llifstream  :   public  std::ifstream   *  Right Thing when passed a non-ASCII pathname. Sadly, that isn't true of   *  Microsoft's std::ofstream.  */ -class LL_COMMON_API llofstream  :   public  std::ofstream +class LL_COMMON_API llofstream : public std::ofstream  {    public:      // Constructors: @@ -239,7 +241,7 @@ class LL_COMMON_API llofstream  :   public  std::ofstream  /** - * @breif filesize helpers. + * @brief filesize helpers.   *   * The file size helpers are not considered particularly efficient,   * and should only be used for config files and the like -- not in a diff --git a/indra/llcommon/llfindlocale.cpp b/indra/llcommon/llfindlocale.cpp index e39812bfc4..b4bcc80ac4 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      }    }  } @@ -177,7 +185,7 @@ canonise_fl(FL_Locale *l) {  #define RML(pn,sn) MAKELANGID(LANG_##pn, SUBLANG_##sn)  struct IDToCode {    LANGID id; -  char*  code; +  const char*  code;  };  static const IDToCode both_to_code[] = {    {ML(ENGLISH,US),           "en_US.ISO_8859-1"}, 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/llinitparam.h b/indra/llcommon/llinitparam.h index 206aa51ba3..32d7b17034 100644 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -31,7 +31,6 @@  #include <vector>  #include <list>  #include <boost/function.hpp> -#include <boost/shared_ptr.hpp>  #include <boost/type_traits/is_convertible.hpp>  #include <boost/type_traits/is_enum.hpp>  #include <boost/unordered_map.hpp> diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 3232a0e219..92b26354a1 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -52,7 +52,7 @@ namespace LLInstanceTrackerPrivate      struct StaticBase      {          // We need to be able to lock static data while manipulating it. -        std::mutex mMutex; +        LL_PROFILE_MUTEX_NAMED(std::mutex, mMutex, "InstanceTracker Data");      };      void logerrs(const char* cls, const std::string&, const std::string&, const std::string&); @@ -101,7 +101,8 @@ public:      static size_t instanceCount()      { -        return LockStatic()->mMap.size(); +        LockStatic lock; LL_PROFILE_MUTEX_LOCK(lock->mMutex); +        return lock->mMap.size();      }      // snapshot of std::pair<const KEY, std::shared_ptr<SUBCLASS>> pairs, for @@ -236,7 +237,7 @@ public:      static ptr_t getInstance(const KEY& k)      { -        LockStatic lock; +        LockStatic lock; LL_PROFILE_MUTEX_LOCK(lock->mMutex);          const InstanceMap& map(lock->mMap);          typename InstanceMap::const_iterator found = map.find(k);          return (found == map.end()) ? NULL : found->second; @@ -252,19 +253,19 @@ protected:          ptr_t ptr(static_cast<T*>(this), [](T*){});          // save corresponding weak_ptr for future reference          mSelf = ptr; -        LockStatic lock; +        LockStatic lock; LL_PROFILE_MUTEX_LOCK(lock->mMutex);          add_(lock, key, ptr);      }  public:      virtual ~LLInstanceTracker()      { -        LockStatic lock; +        LockStatic lock; LL_PROFILE_MUTEX_LOCK(lock->mMutex);          remove_(lock);      }  protected:      virtual void setKey(KEY key)      { -        LockStatic lock; +        LockStatic lock; LL_PROFILE_MUTEX_LOCK(lock->mMutex);          // Even though the shared_ptr we store in our map has a no-op deleter          // for T itself, letting the use count decrement to 0 will still          // delete the use-count object. Capture the shared_ptr we just removed @@ -376,7 +377,8 @@ public:      static size_t instanceCount()      { -        return LockStatic()->mSet.size(); +        LockStatic lock; LL_PROFILE_MUTEX_LOCK(lock->mMutex); +        return lock->mSet.size();      }      // snapshot of std::shared_ptr<SUBCLASS> pointers @@ -488,14 +490,16 @@ protected:          // save corresponding weak_ptr for future reference          mSelf = ptr;          // Also store it in our class-static set to track this instance. -        LockStatic()->mSet.emplace(ptr); +        LockStatic lock; LL_PROFILE_MUTEX_LOCK(lock->mMutex); +        lock->mSet.emplace(ptr);      }  public:      virtual ~LLInstanceTracker()      {          // convert weak_ptr to shared_ptr because that's what we store in our          // InstanceSet -        LockStatic()->mSet.erase(mSelf.lock()); +        LockStatic lock; LL_PROFILE_MUTEX_LOCK(lock->mMutex); +        lock->mSet.erase(mSelf.lock());      }  protected:      LLInstanceTracker(const LLInstanceTracker& other): 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..c3ed7fef52 100644 --- a/indra/llcommon/llmainthreadtask.h +++ b/indra/llcommon/llmainthreadtask.h @@ -79,20 +79,20 @@ 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 -        // redundant to have to add an argument list to engage result_of, then +        // redundant to have to add an argument list to engage invoke_result_t, then          // add the argument list again to complete the signature. At least we          // only support a nullary CALLABLE. -        std::packaged_task<typename std::result_of<CALLABLE()>::type()> mTask; +        std::packaged_task<std::invoke_result_t<CALLABLE>()> mTask;      };  }; diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp index f64f54c262..e999b8f597 100644 --- a/indra/llcommon/llmd5.cpp +++ b/indra/llcommon/llmd5.cpp @@ -68,10 +68,6 @@ documentation and/or software.   */ - - - -  #include "linden_common.h"  #include "llmd5.h" @@ -81,232 +77,203 @@ documentation and/or software.  // how many bytes to grab at a time when checking files  const int LLMD5::BLOCK_LEN = 4096; -  // LLMD5 simple initialization method -  LLMD5::LLMD5()  { -  init(); +    init();  } - - -  // MD5 block update operation. Continues an MD5 message-digest  // operation, processing another message block, and updating the  // context. +void LLMD5::update(const uint8_t* input, const size_t input_length) +{ +    size_t input_index, buffer_index; +    size_t buffer_space; // how much space is left in buffer -void LLMD5::update (const uint8_t *input, const size_t input_length) { - -  size_t input_index, buffer_index; -  size_t buffer_space;                // how much space is left in buffer - -  if (finalized){  // so we can't update! -      std::cerr << "LLMD5::update:  Can't update a finalized digest!" << std::endl; -    return; -  } - -  // Compute number of bytes mod 64 -  buffer_index = size_t((count >> 3) & 0x3F); +    if (finalized) +    { // so we can't update! +        std::cerr << "LLMD5::update:  Can't update a finalized digest!" << std::endl; +        return; +    } -  // Update number of bits -  count += input_length << 3; +    // Compute number of bytes mod 64 +    buffer_index = size_t((count >> 3) & 0x3F); -  buffer_space = 64 - buffer_index;  // how much space is left in buffer +    // Update number of bits +    count += input_length << 3; -  // now, transform each 64-byte piece of the input, bypassing the buffer -  if (input == NULL || input_length == 0){ -      std::cerr << "LLMD5::update:  Invalid input!" << std::endl; -      return; -  } +    buffer_space = 64 - buffer_index; // how much space is left in buffer -  // Transform as many times as possible. -  if (input_length >= buffer_space) { // ie. we have enough to fill the buffer -    // fill the rest of the buffer and transform -    memcpy( /* Flawfinder: ignore */ -        buffer + buffer_index, -        input, -        buffer_space); -    transform (buffer); +    // now, transform each 64-byte piece of the input, bypassing the buffer +    if (input == NULL || input_length == 0) +    { +        std::cerr << "LLMD5::update:  Invalid input!" << std::endl; +        return; +    } -    for (input_index = buffer_space; input_index + 63 < input_length; -     input_index += 64) -      transform (input+input_index); +    // Transform as many times as possible. +    if (input_length >= buffer_space) // ie. we have enough to fill the buffer +    { +        // fill the rest of the buffer and transform +        memcpy(/* Flawfinder: ignore */ +               buffer + buffer_index, +               input, +               buffer_space); +        transform(buffer); -    buffer_index = 0;  // so we can buffer remaining -  } -  else -    input_index=0;     // so we can buffer the whole input +        for (input_index = buffer_space; input_index + 63 < input_length; input_index += 64) +            transform(input + input_index); +        buffer_index = 0; // so we can buffer remaining +    } +    else +        input_index = 0; // so we can buffer the whole input -  // and here we do the buffering: -  memcpy(buffer+buffer_index, input+input_index, input_length-input_index);     /* Flawfinder: ignore */ +    // and here we do the buffering: +    memcpy(buffer + buffer_index, input + input_index, input_length - input_index); /* Flawfinder: ignore */  } - -  // MD5 update for files.  // Like above, except that it works on files (and uses above as a primitive.) +void LLMD5::update(FILE* file) +{ +    unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */ +    int len; -void LLMD5::update(FILE* file){ - -  unsigned char buffer[BLOCK_LEN];      /* Flawfinder: ignore */ -  int len; - -  while ( (len=(int)fread(buffer, 1, BLOCK_LEN, file)) ) -    update(buffer, len); - -  fclose (file); +    while ((len = (int)fread(buffer, 1, BLOCK_LEN, file))) +        update(buffer, len); +    fclose(file);  }  // MD5 update for istreams.  // Like update for files; see above. +void LLMD5::update(std::istream& stream) +{ +    unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */ +    int len; -void LLMD5::update(std::istream& stream){ - -  unsigned char buffer[BLOCK_LEN];      /* Flawfinder: ignore */ -  int len; - -  while (stream.good()){ -    stream.read( (char*)buffer, BLOCK_LEN);     /* Flawfinder: ignore */        // note that return value of read is unusable. -    len=(int)stream.gcount(); -    update(buffer, len); -  } - +    while (stream.good()) +    { +        stream.read((char*)buffer, BLOCK_LEN); /* Flawfinder: ignore */ // note that return value of read is unusable. +        len = (int)stream.gcount(); +        update(buffer, len); +    }  } -void  LLMD5::update(const std::string& s) +void LLMD5::update(const std::string& s)  { -    update((unsigned char *)s.c_str(),s.length()); +    update((unsigned char*)s.c_str(), s.length());  }  // MD5 finalization. Ends an MD5 message-digest operation, writing the  // the message digest and zeroizing the context. - - -void LLMD5::finalize (){ - -  unsigned char bits[8];        /* Flawfinder: ignore */ -  size_t index, padLen; -  static uint8_t PADDING[64]={ -    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +void LLMD5::finalize() +{ +    unsigned char bits[8]; /* Flawfinder: ignore */ +    size_t index, padLen; +    static uint8_t PADDING[64] = +    { +        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0      }; -  if (finalized){ -    std::cerr << "LLMD5::finalize:  Already finalized this digest!" << std::endl; -    return; -  } - -  // Save number of bits. -  // Treat count, a uint64_t, as uint32_t[2]. -  encode (bits, reinterpret_cast<uint32_t*>(&count), 8); +    if (finalized) +    { +        std::cerr << "LLMD5::finalize:  Already finalized this digest!" << std::endl; +        return; +    } -  // Pad out to 56 mod 64. -  index = size_t((count >> 3) & 0x3f); -  padLen = (index < 56) ? (56 - index) : (120 - index); -  update (PADDING, padLen); +    // Save number of bits. +    // Treat count, a uint64_t, as uint32_t[2]. +    encode(bits, reinterpret_cast<uint32_t*>(&count), 8); -  // Append length (before padding) -  update (bits, 8); +    // Pad out to 56 mod 64. +    index  = size_t((count >> 3) & 0x3f); +    padLen = (index < 56) ? (56 - index) : (120 - index); +    update(PADDING, padLen); -  // Store state in digest -  encode (digest, state, 16); +    // Append length (before padding) +    update(bits, 8); -  // Zeroize sensitive information -  memset (buffer, 0, sizeof(*buffer)); +    // Store state in digest +    encode(digest, state, 16); -  finalized=1; +    // Zeroize sensitive information +    memset(buffer, 0, sizeof(buffer)); +    finalized = true;  } - - - -LLMD5::LLMD5(FILE *file){ - -  init();  // must be called be all constructors -  update(file); -  finalize (); +LLMD5::LLMD5(FILE* file) +{ +    init(); // must be called be all constructors +    update(file); +    finalize();  } - - - -LLMD5::LLMD5(std::istream& stream){ - -  init();  // must called by all constructors -  update (stream); -  finalize(); +LLMD5::LLMD5(std::istream& stream) +{ +    init(); // must called by all constructors +    update(stream); +    finalize();  }  // Digest a string of the format ("%s:%i" % (s, number)) -LLMD5::LLMD5(const unsigned char *string, const unsigned int number) +LLMD5::LLMD5(const unsigned char* string, const unsigned int number)  { -    const char *colon = ":"; -    char tbuf[16];      /* Flawfinder: ignore */ +    const char* colon = ":"; +    char tbuf[16]; /* Flawfinder: ignore */      init(); -    update(string, (U32)strlen((const char *) string));     /* Flawfinder: ignore */ -    update((const unsigned char *) colon, (U32)strlen(colon));      /* Flawfinder: ignore */ -    snprintf(tbuf, sizeof(tbuf), "%i", number); /* Flawfinder: ignore */ -    update((const unsigned char *) tbuf, (U32)strlen(tbuf));    /* Flawfinder: ignore */ +    update(string, (U32)strlen((const char*)string));        /* Flawfinder: ignore */ +    update((const unsigned char*)colon, (U32)strlen(colon)); /* Flawfinder: ignore */ +    snprintf(tbuf, sizeof(tbuf), "%i", number);              /* Flawfinder: ignore */ +    update((const unsigned char*)tbuf, (U32)strlen(tbuf));   /* Flawfinder: ignore */      finalize();  }  // Digest a string -LLMD5::LLMD5(const unsigned char *s) +LLMD5::LLMD5(const unsigned char* s)  {      init(); -    update(s, (U32)strlen((const char *) s));       /* Flawfinder: ignore */ +    update(s, (U32)strlen((const char*)s)); /* Flawfinder: ignore */      finalize();  } -void LLMD5::raw_digest(unsigned char *s) const +void LLMD5::raw_digest(unsigned char* s) const  {      if (!finalized)      { -        std::cerr << "LLMD5::raw_digest:  Can't get digest if you haven't "<< -            "finalized the digest!" << std::endl; +        std::cerr << "LLMD5::raw_digest:  Can't get digest if you haven't " +                  << "finalized the digest!" << std::endl;          s[0] = '\0';          return;      } -    memcpy(s, digest, 16);      /* Flawfinder: ignore */ -    return; +    memcpy(s, digest, 16); /* Flawfinder: ignore */  } - - -void LLMD5::hex_digest(char *s) const +void LLMD5::hex_digest(char* s) const  { -    int i; -      if (!finalized)      { -        std::cerr << "LLMD5::hex_digest:  Can't get digest if you haven't "<< -          "finalized the digest!" <<std::endl; +        std::cerr << "LLMD5::hex_digest:  Can't get digest if you haven't " +                  << "finalized the digest!" << std::endl;          s[0] = '\0';          return;      } -    for (i=0; i<16; i++) +    for (int i = 0; i < 16; i++)      { -        sprintf(s+i*2, "%02x", digest[i]);      /* Flawfinder: ignore */ +        sprintf(s + i * 2, "%02x", digest[i]); /* Flawfinder: ignore */      } -    s[32]='\0'; - -    return; +    s[32] = '\0';  } - - - - - -std::ostream& operator<<(std::ostream &stream, LLMD5 context) +std::ostream& operator<<(std::ostream& stream, const LLMD5& context)  {      char s[33];     /* Flawfinder: ignore */      context.hex_digest(s); @@ -320,7 +287,7 @@ bool operator==(const LLMD5& a, const LLMD5& b)      unsigned char b_guts[16];      a.raw_digest(a_guts);      b.raw_digest(b_guts); -    if (memcmp(a_guts,b_guts,16)==0) +    if (memcmp(a_guts, b_guts, 16) == 0)          return true;      else          return false; @@ -328,30 +295,27 @@ bool operator==(const LLMD5& a, const LLMD5& b)  bool operator!=(const LLMD5& a, const LLMD5& b)  { -    return !(a==b); +    return !(a == b);  }  // PRIVATE METHODS: +void LLMD5::init() +{ +    finalized = false; // we just started! -void LLMD5::init(){ -  finalized=0;  // we just started! - -  // Nothing counted, so count=0 -  count = 0; +    // Nothing counted, so count=0 +    count = 0; -  // Load magic initialization constants. -  state[0] = 0x67452301; -  state[1] = 0xefcdab89; -  state[2] = 0x98badcfe; -  state[3] = 0x10325476; +    // Load magic initialization constants. +    state[0] = 0x67452301; +    state[1] = 0xefcdab89; +    state[2] = 0x98badcfe; +    state[3] = 0x10325476;  } - -  // Constants for MD5Transform routine.  // Although we could use C++ style constants, defines are actually better,  // since they let us easily evade scope clashes. -  #define S11 7  #define S12 12  #define S13 17 @@ -381,153 +345,144 @@ void LLMD5::init(){  /* ROTATE_LEFT rotates x left n bits.   */ -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))  /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.  Rotation is separate from addition to prevent recomputation.   */ -#define FF(a, b, c, d, x, s, ac) { \ - (a) += F ((b), (c), (d)) + (x) + (U32)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ -  } -#define GG(a, b, c, d, x, s, ac) { \ - (a) += G ((b), (c), (d)) + (x) + (U32)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ -  } -#define HH(a, b, c, d, x, s, ac) { \ - (a) += H ((b), (c), (d)) + (x) + (U32)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ -  } -#define II(a, b, c, d, x, s, ac) { \ - (a) += I ((b), (c), (d)) + (x) + (U32)(ac); \ - (a) = ROTATE_LEFT ((a), (s)); \ - (a) += (b); \ -  } - - +#define FF(a, b, c, d, x, s, ac)                   \ +    {                                              \ +        (a) += F((b), (c), (d)) + (x) + (U32)(ac); \ +        (a) = ROTATE_LEFT((a), (s));               \ +        (a) += (b);                                \ +    } +#define GG(a, b, c, d, x, s, ac)                   \ +    {                                              \ +        (a) += G((b), (c), (d)) + (x) + (U32)(ac); \ +        (a) = ROTATE_LEFT((a), (s));               \ +        (a) += (b);                                \ +    } +#define HH(a, b, c, d, x, s, ac)                   \ +    {                                              \ +        (a) += H((b), (c), (d)) + (x) + (U32)(ac); \ +        (a) = ROTATE_LEFT((a), (s));               \ +        (a) += (b);                                \ +    } +#define II(a, b, c, d, x, s, ac)                   \ +    {                                              \ +        (a) += I((b), (c), (d)) + (x) + (U32)(ac); \ +        (a) = ROTATE_LEFT((a), (s));               \ +        (a) += (b);                                \ +    }  // LLMD5 basic transformation. Transforms state based on block. -void LLMD5::transform (const U8 block[64]){ - -  uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; - -  decode (x, block, 64); - -  assert(!finalized);  // not just a user error, since the method is private - -  /* Round 1 */ -  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ -  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ -  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ -  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ -  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ -  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ -  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ -  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ -  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ -  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ -  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ -  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ -  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ -  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ -  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ -  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ - - /* Round 2 */ -  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ -  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ -  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ -  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ -  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ -  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */ -  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ -  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ -  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ -  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ -  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ -  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ -  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ -  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ -  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ -  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ - -  /* Round 3 */ -  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ -  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ -  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ -  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ -  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ -  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ -  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ -  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ -  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ -  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ -  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ -  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */ -  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ -  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ -  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ -  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ - -  /* Round 4 */ -  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ -  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ -  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ -  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ -  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ -  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ -  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ -  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ -  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ -  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ -  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ -  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ -  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ -  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ -  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ -  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ - -  state[0] += a; -  state[1] += b; -  state[2] += c; -  state[3] += d; - -  // Zeroize sensitive information. -  memset ( (uint8_t *) x, 0, sizeof(x)); - +void LLMD5::transform(const U8 block[64]) +{ +    uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + +    decode(x, block, 64); + +    assert(!finalized); // not just a user error, since the method is private + +    /* Round 1 */ +    FF(a, b, c, d, x[0], S11, 0xd76aa478);  /* 1 */ +    FF(d, a, b, c, x[1], S12, 0xe8c7b756);  /* 2 */ +    FF(c, d, a, b, x[2], S13, 0x242070db);  /* 3 */ +    FF(b, c, d, a, x[3], S14, 0xc1bdceee);  /* 4 */ +    FF(a, b, c, d, x[4], S11, 0xf57c0faf);  /* 5 */ +    FF(d, a, b, c, x[5], S12, 0x4787c62a);  /* 6 */ +    FF(c, d, a, b, x[6], S13, 0xa8304613);  /* 7 */ +    FF(b, c, d, a, x[7], S14, 0xfd469501);  /* 8 */ +    FF(a, b, c, d, x[8], S11, 0x698098d8);  /* 9 */ +    FF(d, a, b, c, x[9], S12, 0x8b44f7af);  /* 10 */ +    FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ +    FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ +    FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ +    FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ +    FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ +    FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + +    /* Round 2 */ +    GG(a, b, c, d, x[1], S21, 0xf61e2562);  /* 17 */ +    GG(d, a, b, c, x[6], S22, 0xc040b340);  /* 18 */ +    GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ +    GG(b, c, d, a, x[0], S24, 0xe9b6c7aa);  /* 20 */ +    GG(a, b, c, d, x[5], S21, 0xd62f105d);  /* 21 */ +    GG(d, a, b, c, x[10], S22, 0x2441453);  /* 22 */ +    GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ +    GG(b, c, d, a, x[4], S24, 0xe7d3fbc8);  /* 24 */ +    GG(a, b, c, d, x[9], S21, 0x21e1cde6);  /* 25 */ +    GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ +    GG(c, d, a, b, x[3], S23, 0xf4d50d87);  /* 27 */ +    GG(b, c, d, a, x[8], S24, 0x455a14ed);  /* 28 */ +    GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ +    GG(d, a, b, c, x[2], S22, 0xfcefa3f8);  /* 30 */ +    GG(c, d, a, b, x[7], S23, 0x676f02d9);  /* 31 */ +    GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + +    /* Round 3 */ +    HH(a, b, c, d, x[5], S31, 0xfffa3942);  /* 33 */ +    HH(d, a, b, c, x[8], S32, 0x8771f681);  /* 34 */ +    HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ +    HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ +    HH(a, b, c, d, x[1], S31, 0xa4beea44);  /* 37 */ +    HH(d, a, b, c, x[4], S32, 0x4bdecfa9);  /* 38 */ +    HH(c, d, a, b, x[7], S33, 0xf6bb4b60);  /* 39 */ +    HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ +    HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ +    HH(d, a, b, c, x[0], S32, 0xeaa127fa);  /* 42 */ +    HH(c, d, a, b, x[3], S33, 0xd4ef3085);  /* 43 */ +    HH(b, c, d, a, x[6], S34, 0x4881d05);   /* 44 */ +    HH(a, b, c, d, x[9], S31, 0xd9d4d039);  /* 45 */ +    HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ +    HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ +    HH(b, c, d, a, x[2], S34, 0xc4ac5665);  /* 48 */ + +    /* Round 4 */ +    II(a, b, c, d, x[0], S41, 0xf4292244);  /* 49 */ +    II(d, a, b, c, x[7], S42, 0x432aff97);  /* 50 */ +    II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ +    II(b, c, d, a, x[5], S44, 0xfc93a039);  /* 52 */ +    II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ +    II(d, a, b, c, x[3], S42, 0x8f0ccc92);  /* 54 */ +    II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ +    II(b, c, d, a, x[1], S44, 0x85845dd1);  /* 56 */ +    II(a, b, c, d, x[8], S41, 0x6fa87e4f);  /* 57 */ +    II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ +    II(c, d, a, b, x[6], S43, 0xa3014314);  /* 59 */ +    II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ +    II(a, b, c, d, x[4], S41, 0xf7537e82);  /* 61 */ +    II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ +    II(c, d, a, b, x[2], S43, 0x2ad7d2bb);  /* 63 */ +    II(b, c, d, a, x[9], S44, 0xeb86d391);  /* 64 */ + +    state[0] += a; +    state[1] += b; +    state[2] += c; +    state[3] += d; + +    // Zeroize sensitive information. +    memset(x, 0, sizeof(x));  } - -  // Encodes input (uint32_t) into output (unsigned char). Assumes len is  // a multiple of 4. -void LLMD5::encode (uint8_t *output, const uint32_t *input, const size_t len) { - -  size_t i, j; - -  for (i = 0, j = 0; j < len; i++, j += 4) { -    output[j]   = (uint8_t)  (input[i] & 0xff); -    output[j+1] = (uint8_t) ((input[i] >> 8) & 0xff); -    output[j+2] = (uint8_t) ((input[i] >> 16) & 0xff); -    output[j+3] = (uint8_t) ((input[i] >> 24) & 0xff); -  } +void LLMD5::encode(uint8_t* output, const uint32_t* input, const size_t len) +{ +    for (size_t i = 0, j = 0; j < len; i++, j += 4) +    { +        output[j] = (uint8_t)(input[i] & 0xff); +        output[j + 1] = (uint8_t)((input[i] >> 8) & 0xff); +        output[j + 2] = (uint8_t)((input[i] >> 16) & 0xff); +        output[j + 3] = (uint8_t)((input[i] >> 24) & 0xff); +    }  } - - -  // Decodes input (unsigned char) into output (uint32_t). Assumes len is  // a multiple of 4. -void LLMD5::decode (uint32_t *output, const uint8_t *input, const size_t len){ - -  size_t i, j; - -  for (i = 0, j = 0; j < len; i++, j += 4) -    output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) | -      (((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24); +void LLMD5::decode(uint32_t* output, const uint8_t* input, const size_t len) +{ +    for (size_t i = 0, j = 0; j < len; i++, j += 4) +        output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) | +        (((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24);  } - - diff --git a/indra/llcommon/llmd5.h b/indra/llcommon/llmd5.h index 46c79cf5a2..ad063fda46 100644 --- a/indra/llcommon/llmd5.h +++ b/indra/llcommon/llmd5.h @@ -67,59 +67,57 @@ documentation and/or software.  */ -#include <cstdint>                  // uint32_t et al. +#include <cstdint> // uint32_t et al.  // use for the raw digest output  const int MD5RAW_BYTES = 16;  // use for outputting hex digests -const int MD5HEX_STR_SIZE = 33;  // char hex[MD5HEX_STR_SIZE]; with null +const int MD5HEX_STR_SIZE  = 33; // char hex[MD5HEX_STR_SIZE]; with null  const int MD5HEX_STR_BYTES = 32; // message system fixed size -class LL_COMMON_API LLMD5 { -// how many bytes to grab at a time when checking files -  static const int BLOCK_LEN; +class LL_COMMON_API LLMD5 +{ +    // how many bytes to grab at a time when checking files +    static const int BLOCK_LEN;  public: -// methods for controlled operation: -  LLMD5              ();  // simple initializer -  void  update     (const uint8_t *input, const size_t input_length); -  void  update     (std::istream& stream); -  void  update     (FILE *file); -  void  update     (const std::string& str); -  void  finalize   (); - -// constructors for special circumstances.  All these constructors finalize -// the MD5 context. -  LLMD5              (const unsigned char *string); // digest string, finalize -  LLMD5              (std::istream& stream);       // digest stream, finalize -  LLMD5              (FILE *file);            // digest file, close, finalize -  LLMD5              (const unsigned char *string, const unsigned int number); - -// methods to acquire finalized result -  void              raw_digest(unsigned char *array) const; // provide 16-byte array for binary data -  void              hex_digest(char *string) const;         // provide 33-byte array for ascii-hex string - -  friend LL_COMMON_API std::ostream&   operator<< (std::ostream&, LLMD5 context); +    // methods for controlled operation: +    LLMD5(); // simple initializer +    void update(const uint8_t* input, const size_t input_length); +    void update(std::istream& stream); +    void update(FILE* file); +    void update(const std::string& str); +    void finalize(); + +    // constructors for special circumstances.  All these constructors finalize +    // the MD5 context. +    LLMD5(const unsigned char* string); // digest string, finalize +    LLMD5(std::istream& stream);        // digest stream, finalize +    LLMD5(FILE* file);                  // digest file, close, finalize +    LLMD5(const unsigned char* string, const unsigned int number); + +    // methods to acquire finalized result +    void raw_digest(unsigned char* array) const; // provide 16-byte array for binary data +    void hex_digest(char* string) const;         // provide 33-byte array for ascii-hex string + +    friend LL_COMMON_API std::ostream& operator<<(std::ostream&, const LLMD5& context);  private: - - -// next, the private data: -  uint32_t state[4]; -  uint64_t count;     // number of *bits*, mod 2^64 -  uint8_t buffer[64];   // input buffer -  uint8_t digest[16]; -  uint8_t finalized; - -// last, the private methods, mostly static: -  void init             ();               // called by all constructors -  void transform        (const uint8_t *buffer);  // does the real update work.  Note -                                          // that length is implied to be 64. - -  static void encode    (uint8_t *dest, const uint32_t *src, const size_t length); -  static void decode    (uint32_t *dest, const uint8_t *src, const size_t length); - +    // next, the private data: +    uint32_t state[4]; +    uint64_t count;      // number of *bits*, mod 2^64 +    uint8_t  buffer[64]; // input buffer +    uint8_t  digest[16]; +    bool     finalized; + +    // last, the private methods, mostly static: +    void init();                           // called by all constructors +    void transform(const uint8_t* buffer); // does the real update work.  Note +                                           // that length is implied to be 64. + +    static void encode(uint8_t* dest, const uint32_t* src, const size_t length); +    static void decode(uint32_t* dest, const uint8_t* src, const size_t length);  };  LL_COMMON_API bool operator==(const LLMD5& a, const LLMD5& b); diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index cf5ead718d..ba48319a16 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; @@ -120,7 +129,7 @@ void LLMemory::updateMemoryInfo()      {          // Our Windows definition of PagefileUsage is documented by Microsoft as "the total amount of          // memory that the memory manager has committed for a running process", which is rss. -        sAllocatedPageSizeInKB = U32Bytes(info.resident_size); +        sAllocatedPageSizeInKB = U32Kilobytes::convert(U64Bytes(info.resident_size));          // Activity Monitor => Inspect Process => Real Memory Size appears to report resident_size          // Activity monitor => main window memory column appears to report phys_footprint, which spot checks as at least 30% less. @@ -130,37 +139,25 @@ void LLMemory::updateMemoryInfo()          // reported for the app by the Memory Monitor in Instruments.' It is still about 8% bigger than phys_footprint.          //          // (On Windows, we use WorkingSetSize.) -        sAllocatedMemInKB = U32Bytes(info.resident_size - info.reusable); +        sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(info.resident_size - info.reusable));       }      else      {          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..b616edfde7 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) @@ -222,7 +222,7 @@ inline void* ll_aligned_realloc_16(void* ptr, size_t size, size_t old_size) // r          ll_aligned_free_16(ptr);      }  #endif -    LL_PROFILE_ALLOC(ptr, size); +    LL_PROFILE_ALLOC(ret, size);      return ret;  } @@ -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..62943845a5 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,60 @@ 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>(); +    } + +    void lock() +    { +        if (mSharedMutex) +            mSharedMutex->lock<SHARED>(); +    } + +    void unlock() +    { +        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 +240,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..048547e4cc 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();          } @@ -341,6 +418,17 @@ private:      bool mStayUnique;  }; +template<typename Type> +bool operator!=(Type* lhs, const LLPointer<Type>& rhs) +{ +    return (lhs != rhs.get()); +} + +template<typename Type> +bool operator==(Type* lhs, const LLPointer<Type>& rhs) +{ +    return (lhs == rhs.get()); +}  // boost hash adapter  template <class Type> diff --git a/indra/llcommon/llpredicate.h b/indra/llcommon/llpredicate.h index 7c6874d279..91c623eae1 100644 --- a/indra/llcommon/llpredicate.h +++ b/indra/llcommon/llpredicate.h @@ -139,7 +139,7 @@ namespace LLPredicate          Rule()          {} -        void require(ENUM e, bool match) +        void mandate(ENUM e, bool match)          {              mRule.set(e, match);          } @@ -154,7 +154,7 @@ namespace LLPredicate              return (mRule && value).someSet();          } -        bool requires(const Value<ENUM> value) const +        bool mandates(const Value<ENUM> value) const          {              return (mRule && value).someSet() && (!mRule && value).noneSet();          } diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index a54408a852..b499a9ce10 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. @@ -101,15 +98,6 @@  # define LL_THREAD_LOCAL __thread  #endif -// Static linking with apr on windows needs to be declared. -#if LL_WINDOWS && !LL_COMMON_LINK_SHARED -#ifndef APR_DECLARE_STATIC -#define APR_DECLARE_STATIC // For APR on Windows -#endif -#ifndef APU_DECLARE_STATIC -#define APU_DECLARE_STATIC // For APR util on Windows -#endif -#endif  #if defined(LL_WINDOWS)  #define BOOST_REGEX_NO_LIB 1 @@ -120,44 +108,11 @@  #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) -#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/llprocess.h b/indra/llcommon/llprocess.h index 166da8f424..cc2d6566fc 100644 --- a/indra/llcommon/llprocess.h +++ b/indra/llcommon/llprocess.h @@ -29,17 +29,15 @@  #include "llinitparam.h"  #include "llsdparam.h" -#include "llwin32headerslean.h"  #include "llexception.h"  #include "apr_thread_proc.h" -#include <boost/shared_ptr.hpp>  #include <boost/ptr_container/ptr_vector.hpp>  #include <boost/optional.hpp>  #include <boost/noncopyable.hpp>  #include <iosfwd>                   // std::ostream  #if LL_WINDOWS -#include "llwin32headerslean.h" // for HANDLE +#include "llwin32headers.h" // for HANDLE  #elif LL_LINUX  #if defined(Status)  #undef Status diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index d3ff48073d..2e94651083 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -34,7 +34,7 @@  //#include <memory>  #if LL_WINDOWS -#   include "llwin32headerslean.h" +#   include "llwin32headers.h"  #   define _interlockedbittestandset _renamed_interlockedbittestandset  #   define _interlockedbittestandreset _renamed_interlockedbittestandreset  #   include <intrin.h> @@ -700,7 +700,8 @@ private:          memset(cpu_vendor, 0, len);          sysctlbyname("machdep.cpu.vendor", (void*)cpu_vendor, &len, NULL, 0);          cpu_vendor[0x1f] = 0; -        setInfo(eVendor, cpu_vendor); +        // M series CPUs don't provide this field so if empty, just fall back to Apple. +        setInfo(eVendor, (cpu_vendor[0] != '\0') ? cpu_vendor : "Apple");          setInfo(eStepping, getSysctlInt("machdep.cpu.stepping"));          setInfo(eModel, getSysctlInt("machdep.cpu.model")); diff --git a/indra/llcommon/llprofiler.cpp b/indra/llcommon/llprofiler.cpp new file mode 100644 index 0000000000..bdddabf977 --- /dev/null +++ b/indra/llcommon/llprofiler.cpp @@ -0,0 +1,30 @@ +/** +* @file llprofiler.cpp +* @brief Implementation of llprofiler +* @author Rye Cogtail +* +* $LicenseInfo:firstyear=2024&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2024, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA +* $/LicenseInfo$ +*/ + +#include "linden_common.h" + +#include "TracyClient.cpp" diff --git a/indra/llcommon/llprofiler.h b/indra/llcommon/llprofiler.h index af5e5777bf..f6a4d24747 100644 --- a/indra/llcommon/llprofiler.h +++ b/indra/llcommon/llprofiler.h @@ -78,13 +78,7 @@ extern thread_local bool gProfilerEnabled;  #if defined(LL_PROFILER_CONFIGURATION) && (LL_PROFILER_CONFIGURATION > LL_PROFILER_CONFIG_NONE)      #if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY || LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER -        #define TRACY_ENABLE         1 -// Normally these would be enabled but we want to be able to build any viewer with Tracy enabled and run the Tracy server on another machine -// They must be undefined in order to work across multiple machines -//      #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 @@ -108,6 +102,12 @@ extern thread_local bool gProfilerEnabled;          #define LL_PROFILE_ZONE_ERR(name)               LL_PROFILE_ZONE_NAMED_COLOR( name, 0XFF0000  )  // RGB yellow          #define LL_PROFILE_ZONE_INFO(name)              LL_PROFILE_ZONE_NAMED_COLOR( name, 0X00FFFF  )  // RGB cyan          #define LL_PROFILE_ZONE_WARN(name)              LL_PROFILE_ZONE_NAMED_COLOR( name, 0x0FFFF00 )  // RGB red + +        #define LL_PROFILE_MUTEX(type, varname)                     TracyLockable(type, varname) +        #define LL_PROFILE_MUTEX_NAMED(type, varname, desc)         TracyLockableN(type, varname, desc) +        #define LL_PROFILE_MUTEX_SHARED(type, varname)              TracySharedLockable(type, varname) +        #define LL_PROFILE_MUTEX_SHARED_NAMED(type, varname, desc)  TracySharedLockableN(type, varname, desc) +        #define LL_PROFILE_MUTEX_LOCK(varname) { auto& mutex = varname; LockMark(mutex); }      #endif      #if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_FAST_TIMER          #define LL_PROFILER_FRAME_END @@ -124,6 +124,12 @@ extern thread_local bool gProfilerEnabled;          #define LL_PROFILE_ZONE_ERR(name)               (void)(name); // Not supported          #define LL_PROFILE_ZONE_INFO(name)              (void)(name); // Not supported          #define LL_PROFILE_ZONE_WARN(name)              (void)(name); // Not supported + +        #define LL_PROFILE_MUTEX(type, varname) type varname +        #define LL_PROFILE_MUTEX_NAMED(type, varname, desc) type varname +        #define LL_PROFILE_MUTEX_SHARED(type, varname) type varname +        #define LL_PROFILE_MUTEX_SHARED_NAMED(type, varname, desc) type varname +        #define LL_PROFILE_MUTEX_LOCK(varname) // LL_PROFILE_MUTEX_LOCK is a no-op when Tracy is disabled      #endif      #if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER          #define LL_PROFILER_FRAME_END                   FrameMark @@ -139,6 +145,12 @@ extern thread_local bool gProfilerEnabled;          #define LL_PROFILE_ZONE_ERR(name)               LL_PROFILE_ZONE_NAMED_COLOR( name, 0XFF0000  )  // RGB yellow          #define LL_PROFILE_ZONE_INFO(name)              LL_PROFILE_ZONE_NAMED_COLOR( name, 0X00FFFF  )  // RGB cyan          #define LL_PROFILE_ZONE_WARN(name)              LL_PROFILE_ZONE_NAMED_COLOR( name, 0x0FFFF00 )  // RGB red + +        #define LL_PROFILE_MUTEX(type, varname)                     TracyLockable(type, varname) +        #define LL_PROFILE_MUTEX_NAMED(type, varname, desc)         TracyLockableN(type, varname, desc) +        #define LL_PROFILE_MUTEX_SHARED(type, varname)              TracySharedLockable(type, varname) +        #define LL_PROFILE_MUTEX_SHARED_NAMED(type, varname, desc)  TracySharedLockableN(type, varname, desc) +        #define LL_PROFILE_MUTEX_LOCK(varname) { auto& mutex = varname; LockMark(mutex); } // see https://github.com/wolfpld/tracy/issues/575      #endif  #else      #define LL_PROFILER_FRAME_END @@ -162,7 +174,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..0196a24b18 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); @@ -146,12 +146,12 @@ size_t LLQueuedThread::updateQueue(F32 max_time_ms)          // schedule a call to threadedUpdate for every call to updateQueue          if (!isQuitting())          { -            mRequestQueue.post([=]() +            mRequestQueue.post([=, this]()                  {                      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 @@ -474,7 +474,7 @@ void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req)  #else                  using namespace std::chrono_literals;                  auto retry_time = LL::WorkQueue::TimePoint::clock::now() + 16ms; -                mRequestQueue.post([=] +                mRequestQueue.post([=, this]                      {                          LL_PROFILE_ZONE_NAMED("processRequest - retry");                          if (LL::WorkQueue::TimePoint::clock::now() < retry_time) @@ -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/llrun.h b/indra/llcommon/llrun.h index 8061117ad5..70767572ff 100644 --- a/indra/llcommon/llrun.h +++ b/indra/llcommon/llrun.h @@ -30,7 +30,6 @@  #define LL_LLRUN_H  #include <vector> -#include <boost/shared_ptr.hpp>  class LLRunnable; 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..655869a704 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" +#include <boost/json/src.hpp> +  //========================================================================= -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) +        const boost::json::array& array = val.as_array(); +        size_t size = array.size(); +        // allocate elements 0 .. (size() - 1) to avoid incremental allocation +        if (! array.empty()) +        { +            result[size - 1] = LLSD(); +        } +        for (size_t i = 0; i < size; i++)          { -            result.append(LlsdFromJson((*it))); +            result[i] = (LlsdFromJson(array[i]));          }          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,47 +88,54 @@ 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(); +        obj.reserve(val.size()); +        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(); +        json_array.reserve(val.size()); +        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; +        LL_ERRS("LlsdToJson") << "Unsupported conversion to JSON from LLSD type (" +                              << val.type() << ")." << LL_ENDL;          break;      } 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..dbd89118c9 100644 --- a/indra/llcommon/llsdutil.cpp +++ b/indra/llcommon/llsdutil.cpp @@ -32,8 +32,7 @@  #include <sstream>  #if LL_WINDOWS -#   define WIN32_LEAN_AND_MEAN -#   include <winsock2.h>    // for htonl +#   include "llwin32headers.h" // for htonl  #elif LL_LINUX  #   include <netinet/in.h>  #elif LL_DARWIN @@ -51,7 +50,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 +62,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 +75,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 +93,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 +111,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 +122,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 +134,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 +208,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 +254,7 @@ BOOL compare_llsd_with_template(                       data) )              {                  resultant_llsd = LLSD(); -                return FALSE; +                return false;              }              else              { @@ -298,7 +297,7 @@ BOOL compare_llsd_with_template(                           value) )                  {                      resultant_llsd = LLSD(); -                    return FALSE; +                    return false;                  }                  else                  { @@ -321,7 +320,7 @@ BOOL compare_llsd_with_template(      } -    return TRUE; +    return true;  }  // filter_llsd_with_template() is a direct clone (copy-n-paste) of @@ -337,7 +336,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 +532,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 +542,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 +594,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 +633,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 +767,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 +877,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 +904,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 +934,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 +948,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 +989,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.cpp b/indra/llcommon/llsingleton.cpp index d00e703a10..05dc3cde79 100644 --- a/indra/llcommon/llsingleton.cpp +++ b/indra/llcommon/llsingleton.cpp @@ -59,9 +59,8 @@ private:      // it's safe to log -- which involves querying a different LLSingleton --      // which requires accessing the master list.      typedef std::recursive_mutex mutex_t; -    typedef std::unique_lock<mutex_t> lock_t; - -    mutex_t mMutex; +    LL_PROFILE_MUTEX_NAMED(mutex_t, mMutex, "Singleton MasterList"); +    typedef std::unique_lock<decltype(mMutex)> lock_t;  public:      // Instantiate this to both obtain a reference to MasterList::instance() diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 91c05bd5ed..b5659e053c 100644 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -35,6 +35,13 @@  #include "lockstatic.h"  #include "llthread.h"               // on_main_thread()  #include "llmainthreadtask.h" +#include "llprofiler.h" +#include "llerror.h" + +#ifdef LL_WINDOWS +#pragma warning(push) +#pragma warning(disable : 4506)   // no definition for inline function +#endif  class LLSingletonBase: private boost::noncopyable  { @@ -293,7 +300,7 @@ private:          // Use a recursive_mutex in case of constructor circularity. With a          // non-recursive mutex, that would result in deadlock.          typedef std::recursive_mutex mutex_t; -        mutex_t mMutex;             // LockStatic looks for mMutex +        LL_PROFILE_MUTEX_NAMED(mutex_t, mMutex, "Singleton Data"); // LockStatic looks for mMutex          EInitState      mInitState{UNINITIALIZED};          DERIVED_TYPE*   mInstance{nullptr}; @@ -415,7 +422,7 @@ protected:          // deleteSingleton() to defend against manual deletion. When we moved          // cleanup to deleteSingleton(), we hit crashes due to dangling          // pointers in the MasterList. -        LockStatic lk; +        LockStatic lk; LL_PROFILE_MUTEX_LOCK(lk->mMutex);          lk->mInstance  = nullptr;          lk->mInitState = DELETED; @@ -443,7 +450,7 @@ public:          // Hold the lock while we call cleanupSingleton() and the destructor.          // Our destructor also instantiates LockStatic, requiring a recursive          // mutex. -        LockStatic lk; +        LockStatic lk; LL_PROFILE_MUTEX_LOCK(lk->mMutex);          // of course, only cleanup and delete if there's something there          if (lk->mInstance)          { @@ -500,7 +507,7 @@ public:          { // nested scope for 'lk'              // In case racing threads call getInstance() at the same moment,              // serialize the calls. -            LockStatic lk; +            LockStatic lk; LL_PROFILE_MUTEX_LOCK(lk->mMutex);              switch (lk->mInitState)              { @@ -528,6 +535,7 @@ public:                           classname<DERIVED_TYPE>(),                           " -- creating new instance"});                  // fall through +                [[fallthrough]];              case UNINITIALIZED:              case QUEUED:                  // QUEUED means some secondary thread has already requested an @@ -589,7 +597,7 @@ public:      static bool instanceExists()      {          // defend any access to sData from racing threads -        LockStatic lk; +        LockStatic lk; LL_PROFILE_MUTEX_LOCK(lk->mMutex);          return lk->mInitState == INITIALIZED;      } @@ -599,7 +607,7 @@ public:      static bool wasDeleted()      {          // defend any access to sData from racing threads -        LockStatic lk; +        LockStatic lk; LL_PROFILE_MUTEX_LOCK(lk->mMutex);          return lk->mInitState == DELETED;      }  }; @@ -638,7 +646,7 @@ private:          // In case racing threads both call initParamSingleton() at the same          // time, serialize them. One should initialize; the other should see          // mInitState already set. -        LockStatic lk; +        LockStatic lk; LL_PROFILE_MUTEX_LOCK(lk->mMutex);          // For organizational purposes this function shouldn't be called twice          if (lk->mInitState != super::UNINITIALIZED)          { @@ -702,7 +710,7 @@ public:      {          // In case racing threads call getInstance() at the same moment as          // initParamSingleton(), serialize the calls. -        LockStatic lk; +        LockStatic lk; LL_PROFILE_MUTEX_LOCK(lk->mMutex);          switch (lk->mInitState)          { @@ -807,17 +815,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 +832,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 +864,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..c223c26bb0 100644 --- a/indra/llcommon/llstacktrace.cpp +++ b/indra/llcommon/llstacktrace.cpp @@ -32,11 +32,8 @@  #include <iostream>  #include <sstream> -#include "llwin32headerslean.h" -#pragma warning (push) -#pragma warning (disable:4091) // a microsoft header has warnings. Very nice. +#include "llwin32headers.h"  #include <dbghelp.h> -#pragma warning (pop)  typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(      IN ULONG frames_to_skip, @@ -53,8 +50,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 +89,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 +131,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/llstrider.h b/indra/llcommon/llstrider.h index 06cf8d3480..d756aca62b 100644 --- a/indra/llcommon/llstrider.h +++ b/indra/llcommon/llstrider.h @@ -41,6 +41,13 @@ public:      LLStrider(Object* first) { mObjectp = first; mSkip = sizeof(Object); }      ~LLStrider() { } +    const LLStrider<Object>& operator=(const LLStrider<Object>& rhs) +    { +        mBytep = rhs.mBytep; +        mSkip = rhs.mSkip; +        return *this; +    } +      const LLStrider<Object>& operator =  (Object *first)    { mObjectp = first; return *this;}      void setStride (S32 skipBytes)  { mSkip = (skipBytes ? skipBytes : sizeof(Object));} diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 6512bbc392..07adf71d18 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -33,8 +33,7 @@  #include <vector>  #if LL_WINDOWS -#include "llwin32headerslean.h" -#include <winnls.h> // for WideCharToMultiByte +#include "llwin32headers.h"  #endif  std::string ll_safe_string(const char* in) @@ -250,7 +249,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 +307,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 +757,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 +808,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 +823,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 +850,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; @@ -900,6 +899,11 @@ void HeapFree_deleter(void* ptr)  } // anonymous namespace +unsigned long windows_get_last_error() +{ +    return GetLastError(); +} +  template<>  std::wstring windows_message<std::wstring>(DWORD error)  { @@ -938,12 +942,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 +955,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 +972,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 +1021,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 +1212,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. @@ -1336,6 +1409,14 @@ bool LLStringUtil::simpleReplacement(std::string &replacement, std::string token  template<>  void LLStringUtil::setLocale(std::string inLocale)  { +    if(startsWith(inLocale, "MissingString")) +    { +        // it seems this hasn't been working for some time, and I'm not sure how it is intentded to +        // properly discover the correct locale.  early out now to avoid failures later in +        // formatNumber() +        LL_WARNS() << "Failed attempting to set invalid locale: " << inLocale << LL_ENDL; +        return; +    }      sLocale = inLocale;  }; @@ -1552,7 +1633,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..db716b1431 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> @@ -45,7 +46,6 @@  #endif  #include <string.h> -#include <boost/scoped_ptr.hpp>  const char LL_UNKNOWN_CHAR = '?';  class LLSD; @@ -317,7 +317,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 +348,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 +361,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 +387,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 +420,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 +447,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 +465,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 +695,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 +749,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); @@ -830,16 +831,18 @@ template<>  LL_COMMON_API std::wstring windows_message<std::wstring>(unsigned long error);  /// Get Windows message string, implicitly calling GetLastError() +LL_COMMON_API unsigned long windows_get_last_error(); +  template<typename STRING> -STRING windows_message() { return windows_message<STRING>(GetLastError()); } +STRING windows_message() { return windows_message<STRING>(windows_get_last_error()); }  //@} -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 +891,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 +1395,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 +1651,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 +1788,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 +1829,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 +1860,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 +1877,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 +1889,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 +1963,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 +1986,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 +2026,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..3f33ad61c5 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -59,7 +59,7 @@  using namespace llsd;  #if LL_WINDOWS -#   include "llwin32headerslean.h" +#   include "llwin32headers.h"  #   include <psapi.h>               // GetPerformanceInfo() et al.  #   include <VersionHelpers.h>  #elif LL_DARWIN @@ -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..f36d223100 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -34,7 +34,7 @@  #include <thread>  #if LL_WINDOWS -#   include "llwin32headerslean.h" +#   include "llwin32headers.h"  #elif LL_LINUX || LL_DARWIN  #   include <errno.h>  #   include <sys/time.h> @@ -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/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp index be3e585ef8..375cb050cc 100644 --- a/indra/llcommon/lltracethreadrecorder.cpp +++ b/indra/llcommon/lltracethreadrecorder.cpp @@ -159,7 +159,8 @@ AccumulatorBufferGroup* ThreadRecorder::activate( AccumulatorBufferGroup* record  ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::bringUpToDate( AccumulatorBufferGroup* recording )  {  #if LL_TRACE_ENABLED -    if (mActiveRecordings.empty()) return mActiveRecordings.end(); +    if (mActiveRecordings.empty()) +        return mActiveRecordings.end();      mActiveRecordings.back()->mPartialRecording.sync();      BlockTimer::updateTimes(); @@ -202,7 +203,7 @@ ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::bringUpToDate(  #endif  } -void ThreadRecorder::deactivate( AccumulatorBufferGroup* recording ) +void ThreadRecorder::deactivate(AccumulatorBufferGroup* recording)  {  #if LL_TRACE_ENABLED      active_recording_list_t::iterator recording_it = bringUpToDate(recording); @@ -228,9 +229,10 @@ void ThreadRecorder::deactivate( AccumulatorBufferGroup* recording )  #endif  } -ThreadRecorder::ActiveRecording::ActiveRecording( AccumulatorBufferGroup* target ) +ThreadRecorder::ActiveRecording::ActiveRecording(AccumulatorBufferGroup* target)  :   mTargetRecording(target) -{} +{ +}  void ThreadRecorder::ActiveRecording::movePartialToTarget()  { @@ -243,30 +245,30 @@ void ThreadRecorder::ActiveRecording::movePartialToTarget()  // called by child thread -void ThreadRecorder::addChildRecorder( class ThreadRecorder* child ) +void ThreadRecorder::addChildRecorder(ThreadRecorder* child)  {  #if LL_TRACE_ENABLED -    { LLMutexLock lock(&mChildListMutex); -        mChildThreadRecorders.push_back(child); -    } +    LLMutexLock lock(&mChildListMutex); +    mChildThreadRecorders.push_back(child);  #endif  }  // called by child thread -void ThreadRecorder::removeChildRecorder( class ThreadRecorder* child ) +void ThreadRecorder::removeChildRecorder(ThreadRecorder* child)  {  #if LL_TRACE_ENABLED -    { LLMutexLock lock(&mChildListMutex); -        mChildThreadRecorders.remove(child); -    } +    LLMutexLock lock(&mChildListMutex); +    mChildThreadRecorders.remove(child);  #endif  }  void ThreadRecorder::pushToParent()  {  #if LL_TRACE_ENABLED -    { LLMutexLock lock(&mSharedRecordingMutex); -        LLTrace::get_thread_recorder()->bringUpToDate(&mThreadRecordingBuffers); +    if (ThreadRecorder* recorder = LLTrace::get_thread_recorder()) +    { +        LLMutexLock lock(&mSharedRecordingMutex); +        recorder->bringUpToDate(&mThreadRecordingBuffers);          mSharedRecordingBuffers.append(mThreadRecordingBuffers);          mThreadRecordingBuffers.reset();      } @@ -278,15 +280,14 @@ void ThreadRecorder::pullFromChildren()  {  #if LL_TRACE_ENABLED      LL_PROFILE_ZONE_SCOPED_CATEGORY_STATS; -    if (mActiveRecordings.empty()) return; - -    { LLMutexLock lock(&mChildListMutex); - +    if (!mActiveRecordings.empty()) +    { +        LLMutexLock lock(&mChildListMutex);          AccumulatorBufferGroup& target_recording_buffers = mActiveRecordings.back()->mPartialRecording;          target_recording_buffers.sync();          for (LLTrace::ThreadRecorder* rec : mChildThreadRecorders) -        { LLMutexLock lock(&(rec->mSharedRecordingMutex)); - +        { +            LLMutexLock lock(&(rec->mSharedRecordingMutex));              target_recording_buffers.merge(rec->mSharedRecordingBuffers);              rec->mSharedRecordingBuffers.reset();          } @@ -294,13 +295,11 @@ void ThreadRecorder::pullFromChildren()  #endif  } - -void set_master_thread_recorder( ThreadRecorder* recorder ) +void set_master_thread_recorder(ThreadRecorder* recorder)  {      sMasterThreadRecorder = recorder;  } -  ThreadRecorder* get_master_thread_recorder()  {      return sMasterThreadRecorder; 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..b9bd27aa17 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -25,12 +25,10 @@  #include "linden_common.h" - // We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes.  #if LL_WINDOWS  #include "llwin32headers.h" -// ugh, this is ugly.  We need to straighten out our linking for this library -#pragma comment(lib, "IPHLPAPI.lib")  #include <iphlpapi.h> +#include <nb30.h>  #endif  #include "llapp.h" @@ -211,20 +209,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 +235,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 +246,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 +285,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 +310,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 +358,7 @@ BOOL LLUUID::validate(const std::string& in_string)          }          else          { -            return FALSE; +            return false;          }          cur_pos++; @@ -376,11 +374,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 +508,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 +734,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 +887,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 +899,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 +987,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 +995,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/llwin32headers.h b/indra/llcommon/llwin32headers.h index f679adc200..df433deb7a 100644 --- a/indra/llcommon/llwin32headers.h +++ b/indra/llcommon/llwin32headers.h @@ -28,15 +28,8 @@  #define LL_LLWINDOWS_H  #ifdef LL_WINDOWS -#ifndef NOMINMAX -#define NOMINMAX -#endif -#undef WIN32_LEAN_AND_MEAN -#include <winsock2.h> -#include <windows.h> -// reset to default, which is lean -#define WIN32_LEAN_AND_MEAN -#undef NOMINMAX +#include <windows.h> // Does not include winsock.h because WIN32_LEAN_AND_MEAN is defined +#include <winsock2.h> // Requires windows.h  #endif  #endif diff --git a/indra/llcommon/llwin32headerslean.h b/indra/llcommon/llwin32headerslean.h deleted file mode 100644 index 97c8edb8cf..0000000000 --- a/indra/llcommon/llwin32headerslean.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file llwin32headerslean.h - * @brief sanitized include of windows header files - * - * $LicenseInfo:firstyear=2001&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$ - */ - -#ifndef LL_LLWINDOWS_H -#define LL_LLWINDOWS_H - -#ifdef LL_WINDOWS -#ifndef NOMINMAX -#define NOMINMAX -#endif -#define WIN32_LEAN_AND_MEAN -#include <winsock2.h> -#include <windows.h> -#undef NOMINMAX -#endif - -#endif 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..b1a284225e 100644 --- a/indra/llcommon/tests/commonmisc_test.cpp +++ b/indra/llcommon/tests/commonmisc_test.cpp @@ -46,12 +46,6 @@  #include "../test/lltut.h" - -#if LL_WINDOWS -// disable overflow warnings -#pragma warning(disable: 4307) -#endif -  namespace tut  {      struct sd_data @@ -67,7 +61,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 +246,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 +450,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/lleventcoro_test.cpp b/indra/llcommon/tests/lleventcoro_test.cpp index a3c54ffaa2..ab174a8bde 100644 --- a/indra/llcommon/tests/lleventcoro_test.cpp +++ b/indra/llcommon/tests/lleventcoro_test.cpp @@ -30,8 +30,6 @@  #include <boost/bind.hpp>  #include <boost/range.hpp>  #include <boost/utility.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/make_shared.hpp>  #include "linden_common.h" 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/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp index c6eb0fdf75..bf661dc051 100644 --- a/indra/llcommon/tests/llinstancetracker_test.cpp +++ b/indra/llcommon/tests/llinstancetracker_test.cpp @@ -37,8 +37,6 @@  #include <algorithm>                // std::sort()  #include <stdexcept>  // std headers -// external library headers -#include <boost/scoped_ptr.hpp>  // other Linden headers  #include "../test/lltut.h" diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp index 6e8422ca0c..b63cc52bec 100644 --- a/indra/llcommon/tests/llprocess_test.cpp +++ b/indra/llcommon/tests/llprocess_test.cpp @@ -1085,7 +1085,27 @@ namespace tut              return false;          } -        std::list<LLSD> mHistory; +        template <typename CALLABLE> +        void checkHistory(CALLABLE&& code) +        { +            try +            { +                // we expect this lambda to contain tut::ensure() calls +                std::forward<CALLABLE>(code)(mHistory); +            } +            catch (const failure&) +            { +                LL_INFOS() << "event history:" << LL_ENDL; +                for (const LLSD& item : mHistory) +                { +                    LL_INFOS() << item << LL_ENDL; +                } +                throw; +            } +        } + +        using Listory = std::list<LLSD>; +        Listory mHistory;          LLTempBoundListener mConnection;      }; @@ -1136,23 +1156,26 @@ namespace tut          // finish out the run          waitfor(*py.mPy);          // now verify history -        std::list<LLSD>::const_iterator li(listener.mHistory.begin()), -                                        lend(listener.mHistory.end()); -        ensure("no events", li != lend); -        ensure_equals("history[0]", (*li)["data"].asString(), "abc"); -        ensure_equals("history[0] len", (*li)["len"].asInteger(), 3); -        ++li; -        ensure("only 1 event", li != lend); -        ensure_equals("history[1]", (*li)["data"].asString(), "abcdef"); -        ensure_equals("history[0] len", (*li)["len"].asInteger(), 6); -        ++li; -        ensure("only 2 events", li != lend); -        ensure_equals("history[2]", (*li)["data"].asString(), "abcdefghi" EOL); -        ensure_equals("history[0] len", (*li)["len"].asInteger(), 9 + sizeof(EOL) - 1); -        ++li; -        // We DO NOT expect a whole new event for the second line because we -        // disconnected. -        ensure("more than 3 events", li == lend); +        listener.checkHistory( +            [](const EventListener::Listory& history) +            { +                auto li(history.begin()), lend(history.end()); +                ensure("no events", li != lend); +                ensure_equals("history[0]", (*li)["data"].asString(), "abc"); +                ensure_equals("history[0] len", (*li)["len"].asInteger(), 3); +                ++li; +                ensure("only 1 event", li != lend); +                ensure_equals("history[1]", (*li)["data"].asString(), "abcdef"); +                ensure_equals("history[0] len", (*li)["len"].asInteger(), 6); +                ++li; +                ensure("only 2 events", li != lend); +                ensure_equals("history[2]", (*li)["data"].asString(), "abcdefghi" EOL); +                ensure_equals("history[0] len", (*li)["len"].asInteger(), 9 + sizeof(EOL) - 1); +                ++li; +                // We DO NOT expect a whole new event for the second line because we +                // disconnected. +                ensure("more than 3 events", li == lend); +            });      }      template<> template<> @@ -1172,14 +1195,17 @@ namespace tut          // (or any other intervening layer) does crazy buffering. What we want          // to ensure is that there was exactly ONE event with "eof" true, and          // that it was the LAST event. -        std::list<LLSD>::const_reverse_iterator rli(listener.mHistory.rbegin()), -                                                rlend(listener.mHistory.rend()); -        ensure("no events", rli != rlend); -        ensure("last event not \"eof\"", (*rli)["eof"].asBoolean()); -        while (++rli != rlend) -        { -            ensure("\"eof\" event not last", ! (*rli)["eof"].asBoolean()); -        } +        listener.checkHistory( +            [](const EventListener::Listory& history) +            { +                auto rli(history.rbegin()), rlend(history.rend()); +                ensure("no events", rli != rlend); +                ensure("last event not \"eof\"", (*rli)["eof"].asBoolean()); +                while (++rli != rlend) +                { +                    ensure("\"eof\" event not last", ! (*rli)["eof"].asBoolean()); +                } +            });      }      template<> template<> @@ -1202,13 +1228,17 @@ namespace tut          ensure_equals("getLimit() after setlimit(10)", childout.getLimit(), 10);          // okay, pump I/O to pick up output from child          waitfor(*py.mPy); -        ensure("no events", ! listener.mHistory.empty()); -        // For all we know, that data could have arrived in several different -        // bursts... probably not, but anyway, only check the last one. -        ensure_equals("event[\"len\"]", -                      listener.mHistory.back()["len"].asInteger(), abc.length()); -        ensure_equals("length of setLimit(10) data", -                      listener.mHistory.back()["data"].asString().length(), 10); +        listener.checkHistory( +            [abc](const EventListener::Listory& history) +            { +                ensure("no events", ! history.empty()); +                // For all we know, that data could have arrived in several different +                // bursts... probably not, but anyway, only check the last one. +                ensure_equals("event[\"len\"]", +                              history.back()["len"].asInteger(), abc.length()); +                ensure_equals("length of setLimit(10) data", +                              history.back()["data"].asString().length(), 10); +            });      }      template<> template<> @@ -1275,18 +1305,22 @@ namespace tut          params.postend = pumpname;          LLProcessPtr child = LLProcess::create(params);          ensure("shouldn't have launched", ! child); -        ensure_equals("number of postend events", listener.mHistory.size(), 1); -        LLSD postend(listener.mHistory.front()); -        ensure("has id", ! postend.has("id")); -        ensure_equals("desc", postend["desc"].asString(), std::string(params.desc)); -        ensure_equals("state", postend["state"].asInteger(), LLProcess::UNSTARTED); -        ensure("has data", ! postend.has("data")); -        std::string error(postend["string"]); -        // All we get from canned parameter validation is a bool, so the -        // "validation failed" message we ourselves generate can't mention -        // "executable" by name. Just check that it's nonempty. -        //ensure_contains("error", error, "executable"); -        ensure("string", ! error.empty()); +        listener.checkHistory( +            [¶ms](const EventListener::Listory& history) +            { +                ensure_equals("number of postend events", history.size(), 1); +                LLSD postend(history.front()); +                ensure("has id", ! postend.has("id")); +                ensure_equals("desc", postend["desc"].asString(), std::string(params.desc)); +                ensure_equals("state", postend["state"].asInteger(), LLProcess::UNSTARTED); +                ensure("has data", ! postend.has("data")); +                std::string error(postend["string"]); +                // All we get from canned parameter validation is a bool, so the +                // "validation failed" message we ourselves generate can't mention +                // "executable" by name. Just check that it's nonempty. +                //ensure_contains("error", error, "executable"); +                ensure("string", ! error.empty()); +            });      }      template<> template<> @@ -1308,16 +1342,20 @@ namespace tut          {              yield();          } -        ensure("no postend event", i < timeout); -        ensure_equals("number of postend events", listener.mHistory.size(), 1); -        LLSD postend(listener.mHistory.front()); -        ensure_equals("id",    postend["id"].asInteger(), childid); -        ensure("desc empty", ! postend["desc"].asString().empty()); -        ensure_equals("state", postend["state"].asInteger(), LLProcess::EXITED); -        ensure_equals("data",  postend["data"].asInteger(),  35); -        std::string str(postend["string"]); -        ensure_contains("string", str, "exited"); -        ensure_contains("string", str, "35"); +        listener.checkHistory( +            [i, timeout, childid](const EventListener::Listory& history) +            { +                ensure("no postend event", i < timeout); +                ensure_equals("number of postend events", history.size(), 1); +                LLSD postend(history.front()); +                ensure_equals("id",    postend["id"].asInteger(), childid); +                ensure("desc empty", ! postend["desc"].asString().empty()); +                ensure_equals("state", postend["state"].asInteger(), LLProcess::EXITED); +                ensure_equals("data",  postend["data"].asInteger(),  35); +                std::string str(postend["string"]); +                ensure_contains("string", str, "exited"); +                ensure_contains("string", str, "35"); +            });      }      struct PostendListener 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() | 
